user4414636
user4414636

Reputation:

How to draw a line from the centroid of a contour to the perimeter of the contour?

I'm obtaining the centroid of a contour using moments like so:

cnt = np.vstack([cnt[0]]).squeeze()
M = cv2.moments(cnt)
cx = int(M['m10']/M['m00'])
cy = int(M['m01']/M['m00'])

I want to divide the contour into 4 quadrants, so that would require two lines to be drawn, one vertical and one horizontal, both passing through the obtained centroid. How do I go about doing it?

Upvotes: 2

Views: 1913

Answers (1)

tfv
tfv

Reputation: 6259

Though this looks like a task for OpenCV, you may want to have a look at the Shapely package:

http://toblerity.org/shapely/manual.html

Shapely allows you to calculate intersections between polygons, and so the solution gets quite simple: For both the horizontal and the vertical line running through the centroid of your contour, you just calculate the intersections with the contour and draw lines to those intersections.

Lacking your original figure, I have used an ellipse to demonstrate the solution. Since you said that you have only some sample points of your contour, I have used a "coarse" ellipse which is just approximated by a few points.

Output looks like this, hope that this is what you were looking for:

enter image description here

Source code is lengthy due to all the visualization, but hopefully self-explaining:

import shapely.geometry as shapgeo
import numpy as np
import cv2

def make_image():
    img = np.zeros((500, 500), np.uint8)
    white = 255
    cv2.ellipse( img, (250, 300), (100,70), 30, 0, 360, white, -1 )
    return img


if __name__ == '__main__':
    img = make_image()

    #Create a "coarse" ellipse 
    _, contours0, hierarchy = cv2.findContours( img.copy(), cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
    contours = [cv2.approxPolyDP(cnt, 3, True) for cnt in contours0]
    h, w = img.shape[:2]
    vis = np.zeros((h, w, 3), np.uint8)
    cv2.drawContours( vis, contours, -1, (128,255,255), 1)

    #Extract contour of ellipse
    cnt = np.vstack([contours[0]]).squeeze()

    #Determine centroid
    M = cv2.moments(cnt)
    cx = int(M['m10']/M['m00'])
    cy = int(M['m01']/M['m00'])
    print cx, cy

    #Draw full segment lines 
    cv2.line(vis,(cx,0),(cx,w),(150,0,0),1)
    cv2.line(vis,(0,cy),(h,cy),(150,0,0),1)


    # Calculate intersections using Shapely
    # http://toblerity.org/shapely/manual.html
    PolygonEllipse= shapgeo.asLineString(cnt)
    PolygonVerticalLine=shapgeo.LineString([(cx,0),(cx,w)])
    PolygonHorizontalLine=shapgeo.LineString([(0,cy),(h,cy)])

    insecv= np.array(PolygonEllipse.intersection(PolygonVerticalLine)).astype(np.int)
    insech= np.array(PolygonEllipse.intersection(PolygonHorizontalLine)).astype(np.int)
    cv2.line(vis,(insecv[0,0], insecv[0,1]),(insecv[1,0], insecv[1,1]),(0,255,0),2)
    cv2.line(vis,(insech[0,0], insech[0,1]),(insech[1,0], insech[1,1]),(0,255,0),2)

    cv2.imshow('contours', vis)

    0xFF & cv2.waitKey()
    cv2.destroyAllWindows()    

Upvotes: 1

Related Questions