如何在轮廓的质心到轮廓的周长之间画一条线? [英] How to draw a line from the centroid of a contour to the perimeter of the contour?

查看:133
本文介绍了如何在轮廓的质心到轮廓的周长之间画一条线?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用像这样的矩来获取轮廓的质心:

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'])

我想将轮廓划分为4个象限,这样就需要绘制两条线,一条垂直线和一条水平线,均穿过获得的质心.我该怎么做?

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?

推荐答案

尽管这看起来像是OpenCV的任务,但您可能需要看一下Shapely软件包:

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允许您计算多边形之间的交点,因此解决方案变得非常简单:对于穿过轮廓质心的水平线和垂直线,您只需计算轮廓线的交点并绘制到这些交点的线

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:

由于所有可视化,源代码很长,但希望可以自我解释:

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

这篇关于如何在轮廓的质心到轮廓的周长之间画一条线?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆