Question :
I’m trying to target both the iris and pupil edge using opencv’s Canny Edge, but all of the parameters I’ve used do not meet the criteria of making the two borders well delimited. The only way I found of segmenting at least the edge of the iris was binarizing it and then applying the Canny Edge and actually gave a good return.
-
Is there any way to improve the result? Or is it trial and error?
-
How do I target the pupil?
Attempt to target only the binarizing pupil in the dark range:
#'guarda' o pixel se ele estiver no intervalo que é preto
for x in range(0,suavizada.shape[0]):
for y in range(0,suavizada.shape[1]):
if img[x][y] >=0 and suavizada[x][y] <65:
escala[x][y] = 255
Iris targeting code:
img = cv2.imread('path',0)
suavizada = cv2.medianBlur(img,7)
_,limites = cv2.threshold(suavizada,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)
bordas = cv2.Canny(limites,0,0)
cv2.imshow('bordas',bordas)
cv2.waitKey(0)
cv2.destroyAllWindows()
ImageafterbinarizingandgoingthroughCanny:
I’m using Python 3.x with the library installed via PyPi
Answer :
Canny Edge in the way it is being implemented is leaving a pupil very small and similar to the noises created by eyelashes.
I think black slice is the best choice for pupil removal, then use Hough Circles to find pupil cuticle and Grab Cut to remove the pupil.
Black Slice
Extract from the image what is in the range of (0, 0, 0) to (60, 60, 60) of the BGR color space
Detectionofcircles
DetectsthepupilcirclewithHoughCircles
RegionofInterestandGrabCut
Createtheregionofinterest(ROI)withthecoordinatesofthecirclefoundandusetheGrabCuttoextractthepupil
Code
importcv2importnumpyasnpimporturllib.requestresp=urllib.request.urlopen("https://i.stack.imgur.com/NL10Y.jpg")
img = np.asarray(bytearray(resp.read()), dtype="uint8")
img = cv2.imdecode(img, cv2.IMREAD_COLOR)
copia = img.copy()
# Extrai as cores entre o intervalo BGR definido
mask = cv2.inRange(img, (0, 0, 0), (60, 60, 60))
## slice no preto
imask = mask > 0
preto = np.zeros_like(img, np.uint8)
preto[imask] = img[imask]
preto = cv2.cvtColor(preto, cv2.COLOR_BGR2GRAY)
cv2.imshow('Preto', preto)
# detecção de círculos
circles = cv2.HoughCircles(preto, cv2.HOUGH_GRADIENT, 1, 100,
param1=30, param2=30, minRadius=20, maxRadius=100)
#param do Grab Cut
bgdModel = np.zeros((1, 65), np.float64)
fgdModel = np.zeros((1, 65), np.float64)
# pelo menos um círculo encontrado
if circles is not None:
# converte para int
circles = np.round(circles[0, :]).astype("int")
# loop nas coordenadas (x, y) e raio dos círculos encontrados
for (x, y, r) in circles:
roi = img.copy()
r=r+50
# Desenha o círculo encontrado
cv2.circle(copia, (x, y), r - 25, (0, 255, 0), 4)
# Desenha o retângulo do centro do círculo
cv2.rectangle(copia, (x - 5, y - 5), (x + 5, y + 5), (0, 128, 255), -1)
# Região de interesse com a pupila
roi = roi[y-r:y+r, x-r:x+r]
roi_x, roi_y, _ = roi.shape
#Grab Cut da Pupila
mask = np.zeros(roi.shape[:2], np.uint8)
rect = (10, 10,roi_x-10, roi_y-10)
cv2.grabCut(roi, mask, rect, bgdModel, fgdModel, 5, cv2.GC_INIT_WITH_RECT)
mask2 = np.where((mask == 2) | (mask == 0), 0, 1).astype('uint8')
roi_grab = roi * mask2[:, :, np.newaxis]
# Mostra o Grab Cut
cv2.imshow("Grab Cut", np.hstack([roi, roi_grab]))
# Mostra a imagem com o círcuto e centro encontrado pelo Hough Circle
cv2.imshow("output", np.hstack([img, copia]))
cv2.waitKey(0)