找到精确的轮廓(opencv,python)

2024-06-16 10:06:03 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在使用OpenCV+Python从(脸部)图像中检测和提取眼镜。我遵循了这篇文章(https://stackoverflow.com/questi..)的推理思路,如下所示:

1)检测脸部

2)找出面部区域的最大轮廓,必须是眼镜的外框

3)找出面部区域的第二和第三大轮廓,必须是两个透镜的框架

4)提取这些轮廓之间基本上代表眼镜的区域

然而,findContours()确实找到了眼镜的外框作为轮廓,但它并没有精确地找到两个镜片的边框作为轮廓。在

我的结果如下: Original image, Outer frameLeft lens

我的源代码如下:

import cv2
import numpy as np
import matplotlib.pyplot as plt

img = cv2.imread('Luc_Marion.jpg')

RGB_img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)    
gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# Detect the face in the image
haar_face_cascade = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')
faces = haar_face_cascade.detectMultiScale(gray_img, scaleFactor=1.1, minNeighbors=8);

# Loop in all detected faces - in our case it is only one
for (x,y,w,h) in faces:
        cv2.rectangle(RGB_img,(x,y),(x+w,y+h),(255,0,0), 1)

        # Focus on the face as a region of interest
        roi = RGB_img[int(y+h/4):int(y+2.3*h/4), x:x+w]
        roi_gray = gray_img[int(y+h/4):int(y+2.3*h/4), x:x+w]

        # Apply smoothing to roi
        roi_blur = cv2.GaussianBlur(roi_gray, (5, 5), 0)

        # Use Canny to detect edges
        edges = cv2.Canny(roi_gray, 250, 300, 3)

        # Dilate and erode to thicken the edges
        kernel = np.ones((3, 3), np.uint8)
        edg_dil = cv2.dilate(edges, kernel, iterations = 3)
        edg_er = cv2.erode(edg_dil, kernel, iterations = 3)

        # Thresholding instead of Canny does not really make things better
        # ret, thresh = cv2.threshold(roi_blur, 127, 255, cv2.THRESH_BINARY+cv2.THRESH_OTSU)
        # thresh = cv2.adaptiveThreshold(blur_edg, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 115, 1)

        # Find and sort contours by contour area
        cont_img, contours, hierarchy = cv2.findContours(edg_er, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
        print("Number of contours: ", len(contours))
        cont_sort = sorted(contours, key=cv2.contourArea, reverse=True)

        # Draw largest contour on original roi (which is the outer 
        # frame of eyeglasses)
        cv2.drawContours(roi, cont_sort[0], -1, (0, 255, 0), 2)

        # Draw  second largest contour on original roi (which is the left 
        # lens of the eyeglasses)
        # cv2.drawContours(roi, cont_sort[1], -1, (0, 255, 0), 2)

    plt.imshow(RGB_img)
    plt.show()

我怎样才能准确地检测出眼镜左镜片和右镜片的轮廓?在

我希望很明显,我的最终输出必须是眼镜本身,因为我的最终目标是从人脸图像中提取眼镜。


Tags: oftheinimgrgbcv2int轮廓