【问题标题】:OpenCV circle/ellipse detection with blurred edge边缘模糊的 OpenCV 圆/椭圆检测
【发布时间】:2018-12-25 21:06:05
【问题描述】:

如何在下图中定位瞳孔(眼球中的小圆圈)并计算瞳孔的面积。我尝试了霍夫圆检测和椭圆拟合各种阈值的轮廓,但这些天真的方法都不是很好。

具体来说,HoughCircle 检测完全丢失在许多噪声中,而带有修剪的椭圆检测通常最终会给出更大的圆。

而且我不确定如何在不手动调整轨迹栏的情况下确定功能阈值。有人可以就如何准确地做到这一点给我一些指导吗?

眼球样本

【问题讨论】:

  • 您要检测哪个圆圈?你能在多个阶段做到这一点 - 首先检测虹膜和巩膜之间的边界,然后通过增加这个圆圈/椭圆内的对比度来找到足够的颜色差异来识别瞳孔?
  • 眼睛内最暗、最小的圆圈,希望这是有道理的……瞳孔并不总是图像中最暗的区域,否则我可以用直方图确定阈值
  • 好奇,中间那个黑色的细圆边是什么?
  • 这是一个非常具有挑战性的问题。瞳孔和虹膜的反差很小,轮廓并非处处可见。
  • @YvesDaoust 我不确定最小的黑色圆形边缘是什么。虹膜和瞳孔之间的区别是对的。

标签: opencv edge-detection


【解决方案1】:

一个简单的图像处理过程应该可以帮助您实现目标。

首先以灰度加载图像。我认为 Otsu 阈值方法足够稳健,可以提取眼睛的瞳孔区域。去除噪声和未填充区域需要额外的形态处理

然后使用连通分量分析,我们可以隔离瞳孔区域以进行进一步处理。

有了这个区域,我们可以通过用原始区域减去一个扩大的区域来得到边缘,如下所示。

最后,我们可以运行圆形拟合或者椭圆拟合算法来得到对应的形状,

圆形拟合显示为红色,椭圆显示为绿色。两者都返回相同的中心位置,尽管形状略有不同。

这是使用的代码。我缩小图像以加快处理速度,但使用原始尺寸时效果相同。

import cv2
import numpy as np

img = cv2.imread('eye.jpg',0)

small_img = cv2.resize(img,(0,0),fx = 0.25, fy = 0.25)
r,c = small_img.shape
# Threshold objs
_, thresh = cv2.threshold(small_img,0,255,cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)

# Morphological close process to cluster nearby objects
bin_img = cv2.dilate(thresh, None,iterations = 5)
bin_img = cv2.erode(bin_img, None,iterations = 5)

# Analyse connected components
num_labels, labels, stats, centroids = cv2.connectedComponentsWithStats(bin_img)

# Find circle center and radius
# Radius calculated by averaging the height and width of bounding box
bin_eye = np.zeros((r,c))
cnt_label = labels[r/2,c/2]
bin_eye[labels == cnt_label] = 255
area = stats[cnt_label][4]
radius = np.sqrt(area / np.pi)
cnt_pt = ((centroids[cnt_label][0]),(centroids[cnt_label][1]))

# fit ellipse
bin_eye_large = cv2.dilate(bin_eye, None,iterations = 1)

# Get ellipse edge
edge_eye = bin_eye_large - bin_eye

# extract location points for fitting
ellip_pts = np.where(edge_eye > 0)
ellip_pts = np.transpose(ellip_pts)
temp = np.copy(ellip_pts[:,0])
ellip_pts[:,0] = ellip_pts[:,1]
ellip_pts[:,1] = temp

# fit ellipse
ellip = cv2.fitEllipse(ellip_pts)


# Display final result
edges_color = cv2.cvtColor(small_img,cv2.COLOR_GRAY2BGR)
cv2.circle(edges_color,(int(cnt_pt[0]),int(cnt_pt[1])),int(radius),(0,0,255),1)
cv2.circle(edges_color,(int(cnt_pt[0]),int(cnt_pt[1])),5,(0,0,255),1)
cv2.ellipse(edges_color,ellip, (0,255,0))
cv2.circle(edges_color,(int(ellip[0][0]),int(ellip[0][1])),5,(0,255,0),1)

cv2.imshow('edges_color',edges_color)
cv2.imshow('bin_img',bin_img)
cv2.imshow('eye_label',bin_eye)
cv2.imshow('eye_edge',edge_eye)

cv2.waitKey(0)

【讨论】:

  • 您检测到的是虹膜,而不是瞳孔。
猜你喜欢
  • 2017-07-01
  • 2012-06-14
  • 2014-03-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-08-26
  • 1970-01-01
相关资源
最近更新 更多