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

时间:2017-11-29 09:34:03

标签: python opencv

我正在使用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()

如何准确检测左眼镜片和眼镜右镜片的轮廓?

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

0 个答案:

没有答案