一个简单的图像处理过程应该可以帮助您实现目标。
首先以灰度加载图像。我认为 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)