OpenCV обнаружение окружности / эллипса с размытым краем - PullRequest
0 голосов
/ 21 декабря 2018

Как найти зрачка (маленький кружок в глазном яблоке) на следующем рисунке и рассчитать площадь зрачка.Я пробовал обнаружение круга Хафа и подбор эллипса на контурах с различным порогом, но ни один из этих наивных подходов не работает очень хорошо.

В частности, обнаружение HoughCircle полностью теряется во многих шумах, а обнаружение эллипса с обрезкой часто приводит к большему кругу.

И я не уверен, как определить функциональный порог без ручной настройки на трекбар.Может кто-нибудь дать мне несколько советов о том, как точно это сделать?

Образец глазного яблока

1 Ответ

0 голосов
/ 25 декабря 2018

Простой процесс обработки изображения должен помочь вам достичь вашей цели.

Сначала загрузите изображение в оттенках серого.Я думаю, что пороговый метод Оцу достаточно надежен, чтобы извлечь область зрачка глаза.Дополнительный морфологический процесс требуется для удаления шума и незаполненных областей

enter image description here

Затем, используя анализ подключенных компонентов, мы можем выделить область зрачка для дальнейшей обработки.

enter image description here

С этой областью мы можем получить край, вычитая расширенную область с исходной областью, как показано ниже.

enter image description here

Наконец, мы можем запустить подгонку окружности или алгоритм подбора эллипса, чтобы получить соответствующую форму,

enter image description here

Подгонка круга показана красным, а эллипс - зеленым.Оба возвращают одну и ту же центральную позицию, хотя и слегка различную форму.

Здесь используется код.Я уменьшаю изображение, чтобы ускорить процесс, но оно будет работать так же, используя оригинальный размер.

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)
...