【问题标题】:pupil detection in OpenCV & PythonOpenCV 和 Python 中的瞳孔检测
【发布时间】:2016-04-30 14:44:52
【问题描述】:

我正在为我的学校项目进行瞳孔检测。这是我第一次使用 OpenCV 和 Python,使用 Python 版本 3.4.2 和 OpenCV 3.1.0。

我正在使用 Raspberry Pi NoIR 相机,并且我得到了很好的图像。

但我无法很好地检测到瞳孔(因为闪烁、睫毛和阴影。 我参考了网上的一些代码,以下是该代码的一部分。

...

kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))

# capture frames from the camera
for frame in camera.capture_continuous(rawCapture, format="bgr", use_video_port=True):

    image = frame.array
    cv2.imshow("image", image)


    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    retval, thresholded = cv2.threshold(gray, 80, 255, 0)
    cv2.imshow("threshold", thresholded)

    closed = cv2.erode(cv2.dilate(thresholded, kernel, iterations=1), kernel, iterations=1)
    #closed = cv2.morphologyEx(close, cv2.MORPH_CLOSE, kernel)

    cv2.imshow("closed", closed)

    thresholded, contours, hierarchy = cv2.findContours(closed, cv2.RETR_LIST, cv2.CHAIN_APPROX_NONE)

    drawing = np.copy(image)
    cv2.drawContours(drawing, contours, -1, (255, 0, 0), 2)

    for contour in contours:

        area = cv2.contourArea(contour)
        bounding_box = cv2.boundingRect(contour)

        extend = area / (bounding_box[2] * bounding_box[3])

        # reject the contours with big extend
        if extend > 0.8:
            continue

        # calculate countour center and draw a dot there
        m = cv2.moments(contour)
        if m['m00'] != 0:
            center = (int(m['m10'] / m['m00']), int(m['m01'] / m['m00']))
            cv2.circle(drawing, center, 3, (0, 255, 0), -1)

        # fit an ellipse around the contour and draw it into the image
        try:
            ellipse = cv2.fitEllipse(contour)
            cv2.ellipse(drawing, box=ellipse, color=(0, 255, 0))
        except:
            pass

    # show the frame
    cv2.imshow("Drawing", drawing)

    ...

输入图片:

输出图像:

如何去除图片中与瞳孔无关的部分,如上图?

除了答案,也欢迎任何提示。

【问题讨论】:

  • 相关:Speeding up vectorized eye-tracking algorithm in numpy。您还可以检查循环性 (example code)。
  • 其他选项:使用HoughCircles 直接检测圆圈和/或如果内部区域比外部更暗,则仅保留轮廓。如果眼睛始终居中且距离相同,您还可以定义感兴趣区域 (ROI) + 使用该区域。
  • 我会在二值图像上使用erode,然后简单地使用HoughCircles 来检测图像中最重要的圆圈。
  • 谢谢!我尝试只使用侵蚀,但有时结果不够好......但完整的形态学对性能不利(丢帧等)。

标签: python opencv


【解决方案1】:

您可以做几件事。它们的工作情况取决于您要应用算法的图像中有多少变化。您可以做出几个假设,然后丢弃所有不符合这些假设的候选人。

删除小的检测

起初,我会考虑通过在循环开头添加以下行来删除太小的候选:

if area < 100:
    continue

阈值是随机选择的,适用于该特定图像。它消除了几乎所有的错误检测。只剩下最大的一个。但是您必须将其与您的其他图像进行检查并根据您的需要进行调整。

删除不圆的检测

您可以做出的另一个假设是瞳孔通常是圆形的,您可以删除所有不够“圆形”的检测。一种简单的圆度测量方法是查看周长与面积的比率。

circumference = cv2.arcLength(contour,True)
circularity = circumference ** 2 / (4*math.pi*area)

右侧阴影的圆度约为 2.72,瞳孔的圆度约为 1.31。

提高圆度

您注意到,由于反射,您的瞳孔轮廓并不完美。您可以通过计算轮廓的凸包来改善这一点。

contour = cv2.convexHull(contour)

如果在计算面积和周长之前执行此操作,则会得到 1.01 和 1.37 的圆度值。 (正圆的圆度为 1)这意味着反射造成的缺陷几乎被完美修复。在这种情况下这可能不是必需的,但在有更多反射的情况下可能很有用。

【讨论】:

  • 谢谢!我设置了一个限制循环1.1,并且工作得很好。我想让这个项目“实时”。由于形态学(在我看来),随着内核大小变大,FPS 会下降。我可以提高形态学表现吗?
【解决方案2】:

几年前,我实现了一个非常相似的项目。对于上面添加的所有内容,我可以建议一个小技巧。

如您所见,任何光源都有两次反射。一次在眼睛表面,第二次在玻璃表面反射。

如果您移除玻璃(如果可能的话),您将在瞳孔中心几乎看到非常明亮的反射。在这种情况下,您可以忽略所有没有这种明亮反射的物体。这也将帮助您在相机附近的空间中找到眼睛的位置

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-11-19
    • 2018-10-04
    • 2017-05-19
    • 2015-01-08
    • 1970-01-01
    • 2021-06-28
    • 2012-09-01
    • 1970-01-01
    相关资源
    最近更新 更多