Reputation: 31
I want to fit ellipses around different clusters. Until now, I used cv2.fitEllipse
and it worked fine. But I discovered a problem with one ellipse (out of more than 100).
Here is a sample of code that reproduces the unexpected behavior.
import numpy as np
import cv2
import itertools
import matplotlib.pyplot as mpl
test=np.zeros((40,40))
test[27,12]=1
test[28,11:13]=1
test[29,11:14]=1
test[30,10:14]=1
test[31,11:14]=1
test[32,12:14]=1
test[33,13]=1
def getContours(clusters):
map_contour=np.ones(clusters.shape).astype(np.uint8)
int_cnts=[]
for label in np.unique(clusters):
# if the label is zero, we are examining the 'background'
if label == 0:
continue
mask = np.zeros(test.shape, dtype="uint8")
mask[clusters == label] = 255
cnts, hierarchy = \
cv2.findContours(mask.copy(),cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
int_cnts.append(cnts)
c = max(cnts, key=cv2.contourArea)
cv2.drawContours(map_contour, cnts, 0, (0, 255, 0), 1)
list_contours=list(itertools.chain.from_iterable(int_cnts))
return list_contours, map_contour
list_test,map_test=getContours(test)
info=np.zeros((len(list_test),5))
map_ellipse=np.ones(test.shape).astype(np.uint8)
for index,cnt in enumerate(list_test):
ellipse=cv2.fitEllipse(cnt)
info[index,0:2],info[index,2:4],info[index,4] = ellipse
cv2.ellipse(map_ellipse,ellipse,(255,0,0))
print cnt
print ellipse
mpl.contourf(map_ellipse)
mpl.contour(test)
mpl.show()
cnt gives:
array([[[12, 27]],
[[11, 28]],
[[11, 29]],
[[10, 30]],
[[13, 33]],
[[13, 29]],
[[12, 28]]], dtype=int32)
ellipse is:
((23.71430015563965, -20.397018432617188),
(8.957982063293457, 98.63383483886719),
0.0)
As you can see if you copy/paste and run the code above, the top of the ellipse (cut in half) appears to be totally disconnected from the zone that it is supposed to represent (top left). I have no idea what is wrong is the code, especially since it works for other forms in the same picture.
What is causing this issue?
Edit: It seems that the ellipse is much better placed and sized (although not good enough) when I set test[30,9:14]=1
instead of test[30,10:14]=1
. But when I use test[30,9:14]=1
instead, the ellipse is now bigger again and located in the top left corner. Such a sensitivity to one pixel that doesn't really change the shape of the form is outstanding.
Upvotes: 0
Views: 258
Reputation: 31
I finally found what was going on. Because of the approximation cv2.CHAIN_APPROX_SIMPLE
, the number of points used to calculate the ellipse was too small.
The problem is solved if I use cv2.CHAIN_APPROX_NONE
, which takes into account all the points of contour.
Upvotes: 1