Good night! I have been trying to fit an ellipse to the border of a roughly elliptic region. The ellipse fits nicely, but whenever I try to plot the major axis, it fails. Of note, the approach below works well for phi \in [pi/4, 3pi/4], but not on other semi-cuadrants. I think the problem lies on the output of xc, yc, a, b, alpha = ellipse.params. Here, xc and yc are the coordinates of the center of the ellipse, a and b are the length of major and minor axis, and alpha is (I guess) the angle that the major axis makes against the horizontal axis. Does anyone have a hint for handling properly that angle, so that the code below works under any orientation of the ellipse? Many thanks! from matplotlib import pyplot as plt import numpy as np import skimage.io as io from skimage.measure import EllipseModel from skimage import feature from skimage.transform import rotate bin_im = io.imread( 'https://www.dropbox.com/s/fantqj8x4mbbsxf/bin_mask.png?dl=0') ##################################################### #This routine fails for ellipses oriented in [0,pi/4] # bin_im = rotate(bin_im, 0, order=1) # bin_im = rotate(bin_im, 30, order=1) #It also seems to fail for [3*pi/4 ,pi] #bin_im = rotate(bin_im, 140, order=1) #However, it does not seem to fail for complementary #orientations belonging to [pi/4, 3*pi/4] - approximately # bin_im = rotate(bin_im, 70, order=1) #bin_im = rotate(bin_im, 100, order=1) ##################################################### #Initial data processing fig, ax = plt.subplots(nrows=1, ncols=2) edges = feature.canny(bin_im) data_x, data_y = np.where( edges > 0.5 ) ################################ #Subsample data points for speed indexes = np.arange(0,len(data_x),10) data_x = data_x[indexes] data_y = data_y[indexes] data = np.column_stack([data_x, data_y]) ############################### #Plot original image and border ax[0].imshow(bin_im, cmap=plt.cm.gray) ax[1].imshow(edges, cmap=plt.cm.gray) plt.show() ###################################### #Estimate ellipse parameters from data ellipse = EllipseModel() ellipse.estimate(data) xc, yc, a, b, alpha = ellipse.params ######################################## #Build ellipse from estimated parameters #Rotation matrix R = np.array([ [np.cos(alpha), -np.sin(alpha)], [np.sin(alpha), np.cos(alpha)] ]) a0, a1 = (0, 2*np.pi) angles = np.linspace(a0, a1, 300) X = np.vstack([ np.cos(angles) * a, np.sin(angles) * b]).T ell = np.dot(X, R.T) + (xc, yc) #################### #Plot fitted ellipse fig2, ax2 = plt.subplots(nrows=1, ncols=1) ax2.plot(bin_im.shape[1]-data[:, 1], data[:, 0], '.b', label='Input data') ax2.plot(bin_im.shape[1]-ell[:,1],ell[:,0],'r', label = 'Estimated data') ax2.legend(loc='upper left') # plt.show() #Equation of the lower half of the ellipse should be: #y = y_c + (x-x_c)*tan(alpha) major_axis_length = max(a, b) xx = np.linspace(xc-major_axis_length, xc+major_axis_length, 300) #as an aside question, how should i properly set this range? yy = yc + (xx-xc)*np.tan(alpha) line = np.column_stack([xx, yy]) ax2.plot(bin_im.shape[1]-line[:, 1], line[:, 0], 'g') ax2.set_xlim([0, bin_im.shape[1]]) ax2.set_ylim([0,bin_im.shape[0]]) plt.show() #Build masked semi-ellipse h=bin_im.shape[0] w=bin_im.shape[1] xaxis = np.linspace(0, h-1, h) yaxis = np.linspace(0, w-1, w) yyy, xxx = np.meshgrid(yaxis, xaxis) mask = yyy > yc + (xxx-xc)*np.tan(alpha) new_bin_im = np.zeros_like(bin_im) new_bin_im[mask]=bin_im[mask] fig, ax3 = plt.subplots(nrows=1, ncols=1) ax3.imshow(new_bin_im,cmap=plt.cm.gray) plt.show()
Hi Adrián
On 2015-05-12 15:55:45, Adrián Galdrán
I have been trying to fit an ellipse to the border of a roughly elliptic region. The ellipse fits nicely, but whenever I try to plot the major axis, it fails. Of note, the approach below works well for phi \in [pi/4, 3pi/4], but not on other semi-cuadrants. I think the problem lies on the output of xc, yc, a, b, alpha = ellipse.params. Here, xc and yc are the coordinates of the center of the ellipse, a and b are the length of major and minor axis, and alpha is (I guess) the angle that the major axis makes against the horizontal axis.
Have a look at: http://stackoverflow.com/a/28289147/214686 Perhaps that helps? We also have examples in the documentation on how to plot these axes. Regards Stéfan
participants (2)
-
Adrián Galdrán
-
Stefan van der Walt