2

I'm hoping that I can get some help in improving my ellipse fitting method. I'm thinking of trying to use a RANSAC style method but I'm not sure if it is the right direction to go in. Any help on the direction I should begin going in would be greatly appreciated, even if it is just an improvement on my edge finding.

I've been working on this problem for a while, and I'm not making very much progress. I think the main problem is the quality of the images but I can only work which what I have now.

My current method I am testing is to use edge detection on the image, and then try and to fit ellipses around the edges I find. The images below will highlight my main problem which is that my method deals very poorly with noise.

Original Image: https://i.sstatic.net/QRYCD.jpg

After Canny Edge detection: https://i.sstatic.net/4Yl8o.png

After Ellipse Fitting: https://i.sstatic.net/waHzJ.jpg

Below is my code which I use. For the Canny edge detection I found some values and are using them statically for now. It is code taken from online which I have then modified, and is a bit hacky for now sorry.

#!/usr/bin/python import cv2 import numpy as np import sys from numpy.linalg import eig, inv # param is the result of canny edge detection def process_image(img): # for every pixel in the image: for (x,y), intensity in np.ndenumerate(img): # if the pixel is part of an edge: if intensity == 255: # determine if the edge is similar to an ellipse ellipse_test(img, x, y) def ellipse_test(img, i, j): #poor coding practice but what I'm doing for now global output, image i_array = [] j_array = [] # flood fill i,j while storing all unique i,j values in arrays flood_fill(img, i, j, i_array, j_array) i_array = np.array(i_array) j_array = np.array(j_array) if i_array.size >= 10: #put those values in a numpy array #which can have an ellipse fit around it array = [] for i, elm in enumerate(i_array): array.append([int(j_array[i]), int(i_array[i])]) array = np.array([array]) ellp = cv2.fitEllipse(array) cv2.ellipse(image, ellp, (0,0,0)) cv2.ellipse(output, ellp, (0,0,0)) def flood_fill(img, i, j, i_array, j_array): if img[i][j] != 255: return # store i,j values i_array.append(float(i)) j_array.append(float(j)) # mark i,j as 'visited' img[i][j] = 250 # flood_fill adjacent and diagonal pixels (i_max, j_max) = img.shape if i - 1 > 0 and j - 1 > 0: flood_fill(img, i - 1, j - 1, i_array, j_array) if j - 1 > 0: flood_fill(img, i, j - 1, i_array, j_array) if i - 1 > 0: flood_fill(img, i - 1, j, i_array, j_array) if i + 1 < i_max and j + 1 < j_max: flood_fill(img, i + 1, j + 1, i_array, j_array) if j + 1 < j_max: flood_fill(img, i, j + 1, i_array, j_array) if i + 1 < i_max: flood_fill(img, i + 1, j, i_array, j_array) if i + 1 < i_max and j - 1 > 0: flood_fill(img, i + 1, j - 1, i_array, j_array) if i - 1 > 0 and j + 1 < j_max: flood_fill(img, i - 1, j + 1, i_array, j_array) image = cv2.imread(sys.argv[1], 0) canny_result = cv2.GaussianBlur(image, (3,3), 0) canny_result = cv2.Canny(canny_result, 107, 208, apertureSize=3, L2gradient=False) #output is a blank images which the ellipses are drawn on output = np.zeros(image.shape, np.uint8) output[:] = [255] cv2.waitKey(0) cv2.namedWindow("Canny result:", cv2.WINDOW_NORMAL) cv2.imshow('Canny result:', canny_result) print "Press any key to find the edges" cv2.waitKey(0) print "Now finding ellipses" process_image(canny_result) print "Ellipses found!" cv2.namedWindow("Original image:", cv2.WINDOW_NORMAL) cv2.imshow('Original image:', image) cv2.namedWindow("Output image:", cv2.WINDOW_NORMAL) cv2.imshow("Output image:", output) cv2.waitKey(0) 

1 Answer 1

2

Here is what I tried, I use dilate and scipy.ndimage to do some process:

import cv2 import numpy as np image = cv2.imread("ellipse.jpg", 0) bimage = cv2.GaussianBlur(image, (3, 3), 0) edge_image = cv2.Canny(bimage, 107, 208, apertureSize=3, L2gradient=False) img2 = cv2.dilate(edge_image, np.ones((3, 3)), iterations=3) dis_image = cv2.cvtColor(img2, cv2.COLOR_GRAY2BGR) import scipy.ndimage as ndimage labels, count = ndimage.label(img2) for lab, idx in enumerate(ndimage.find_objects(labels.astype(int)), 1): sy = idx[0].start sx = idx[1].start y, x = np.where(labels[idx] == lab) ellp = cv2.fitEllipse(np.column_stack((x+sx, y+sy))) cv2.ellipse(dis_image, ellp, (0, 0, 255)) 

here is the output:

enter image description here

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.