2

I'm playing with openCV (on Python) and trying to do a simple task. I have this human body contour and I need to find bottommost points on each of his halfs (so, basically, legs bottommost points. I highlited them on image) and I just have no idea how to do this.

Is there any way to split contour in half? Or is there an easier way?

contour

Thanks!

Nausik
  • 735
  • 8
  • 22

2 Answers2

3

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().

Community
  • 1
  • 1
Ryan
  • 3,555
  • 1
  • 22
  • 36
  • could you try to replace the deprecated cv api calls with cv2 ones ? (opencv3 is around the corner, and it *won't* let you use that) – berak Oct 16 '14 at 18:13
  • I forgot the `import` statements at the top of the code (now they're there). I'm importing `cv2 as cv`. Is that what you meant? – Ryan Oct 16 '14 at 18:17
  • not quite (and that kind of shadowing is a total bad idea). e.g. cv2.namedWindow vs cv.NamedWindow – berak Oct 16 '14 at 18:25
  • [cv2..GaussianBlur](http://docs.opencv.org/modules/imgproc/doc/filtering.html#cv2.GaussianBlur) - still an eye-opener no ? you thought your 'import cv2 as cv' would use the cv2 api, but it *did not* – berak Oct 16 '14 at 18:57
1

I would sort the points of that contour based on their y-coordinate (lowest point first). Take the first point, assume it is the bottom-most point of one leg. Now browse the other points in this sequence, and check if the line connecting the first point satisfies this condition:

  • at least (say) 50% points are not part of the contour;
  • the line itself is at least (say) 30 pixels long.

Accept the first point where this is true.

This should give you a point that is on the other leg and is (among) the bottom-most.

Pafka
  • 256
  • 2
  • 6