我有一个名为cnt
的轮廓,它来自下面的图像:
我可以找到像这样的质心:
M = cv2.moments(cnt)
centroid_x = int(M['m10']/M['m00'])
centroid_y = int(M['m01']/M['m00'])
我现在要画N条线,每一条线间隔360/N度,从质心开始,在所有可能的交点处切割轮廓。line()函数需要起点和终点,但我没有终点。在
如果我用Tan(360/N)的斜率画一条穿过质心的线,我就可以用bitwise_and
找到这条线与轮廓的交点,但我无法找到绘制这条线的方法。在
如果您能帮助我们画出这样的界线,我们将不胜感激。在
我将使用一种老式的方法,我怀疑STL或对编译器的普遍信任可以加快速度;)。顺便说一下,C++。在
画线。在
我有点事要做。这有点特别,但这基本上就是我写的算法。我必须重建你图像的轮廓,所以我所做的就是手动读取图像,提取出物体最外层的轮廓,然后从那里开始。
cv2.line
方法的优点是,如果您绘制一条超出边界的线,该线将被图像边界剪裁。这对我写的算法很有用。在无需赘言,这些步骤如下:
out
。在N
。在对于每个角度,对于
i = 0, 1
到N - 1
:a.创建临时空白图像
b.计算合适的角度:
i*(360 / N)
并转换为弧度在临时图像上,从轮廓的质心到图像外部的坐标画一条线,以确保我们沿着我们想要的角度朝图像边界画一条线。这条线的水平分量是
cos(360/N)
(这里的参数是以度为单位),而垂直分量是-sin(360/N)
(参数也是以度为单位)。负数是由于y
轴在我们的图像坐标空间中向下是正的,所以负数是将它还原,使正轴相对于笛卡尔坐标向上。这样做的原因是,当我们计算每一条线与中心的夹角时,这些角是正确的,因为正角度逆时针扫掠。从质心开始,我们将移动图像的水平宽度和垂直方向的图像高度,保持之前发现的水平和垂直分量。这将使我们画出边界线,但该线将被图像边界剪裁。在另一个复杂的问题是在这个临时图像中画一条足够厚的线。如果我们画了一条只有1像素厚的线,你可能会得到这样一种情况:由于像素采样和绘制线的方式,这条线与轮廓线不相交。我选择了5像素的厚度来确定。在
d.使用此临时图像,查看哪些位置等于参考图像。对于任何相等的位置,我们已经找到了这条线与原始图像的轮廓相交的地方。因此,选择任何相交的位置,因为粗线很可能与最外层轮廓产生多个交点。在
使用步骤(d),从
out
的质心到步骤(d)中找到的位置画一条线。对所有角度重复步骤6。
out
将在步骤6完成后包含结果。不用多说,下面是我写的代码:
这是我得到的结果。我选择了20个角度:
{1美元^
相关问题 更多 >
编程相关推荐