First, you want to invert the colors on your image - then work with that inverted image. You can do what is described here to accomplish that.
I've just written some code which seems to be successfully detecting the bottom of each leg on the inverted image. In short, what I've done is access each element in the contour array and find the maximum (for some reason) y values. From there, it's easy to get the associated x values and draw circles at those coordinates. You can play with the threshold, smoothness, etc, until the circles are drawn. Note: you need to specify the path to the inverted image. Here is the code to do that (it is REALLY disorganized and messy, I just cobbled this together AQAP so you could get going):
class test():
def __init__(self):
cv2.namedWindow("w1", cv.CV_WINDOW_AUTOSIZE)
cv2.createTrackbar('Threshold', 'w1', 100, 225, self.passdef)
cv2.createTrackbar('Smoothen', 'w1', 15, 24, self.passdef)
cv2.createTrackbar('Brightness', 'w1', 50, 100, self.passdef)
cv2.createTrackbar('Contrast', 'w1', 0, 100, self.passdef)
self.vid_contour_selection()
def passdef(self, x):
pass
def vid_contour_selection(self):
while True:
self.t1 = cv2.getTrackbarPos('Threshold', 'w1')
self.gb1 = cv2.getTrackbarPos('Smoothen', 'w1')
bright = cv2.getTrackbarPos('Brightness', 'w1')
contrast = cv2.getTrackbarPos('Contrast', 'w1')
c = float(contrast)/100
b = float(bright)/100
im = cv2.imread('/home/rm/invertida.png')
aframe = numpy.asarray(im[:,:])
g = cv.fromarray(aframe)
if self.gb1 != 0:
cv.Smooth(g, g ,cv.CV_GAUSSIAN, self.gb1,15 )
g = numpy.asarray(g)
imgray = cv2.cvtColor(g,cv2.COLOR_BGR2GRAY)
ret,thresh = cv2.threshold(imgray,self.t1,225, cv2.THRESH_BINARY) #mouseover colony to see val
threshbgr = cv2.cvtColor(thresh, cv.CV_GRAY2BGR)
contours, hierarchy = cv2.findContours(thresh,cv.CV_RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE) #or CV_RETR_LIST
self.ctrs = []
for i in contours:
if cv2.contourArea(i) < 150000 and cv2.contourArea(i) >500:
self.ctrs.append(i)
ally = []
for i in self.ctrs:
for q in i:
for p in q:
ally.append(p[1])
ally.sort()
miny = ally[-1]
miny2 = miny
count = -2
while miny2 == miny:
miny2 = ally[count]
count -=1
for i in self.ctrs:
for q in i:
for p in q:
if p[1] == miny:
corda = (p[0], miny)
if p[1] == miny2:
cordb = (p[0], miny2)
cv2.circle(threshbgr, corda,20,color= (0,0,225),thickness= 2)
cv2.circle(threshbgr, cordb,20,color= (0,0,225),thickness= 2)
cv2.drawContours(threshbgr,self.ctrs,-1,(0,225,0),2)
cv2.imshow("w1", threshbgr)
c = cv2.waitKey(5)
p = test()
Apologies for the formatting- you'll have to indent everything below class test()
.