我试图找到一条手绘线的两个端点 我写了这个片段,找到了轮廓, 但终点并不正确:
img = cv2.imread("my_img.jpeg")
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# Binary Threshold:
_, thr_img = cv2.threshold(img_gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)
cv2.imshow(winname="after threshold", mat=thr_img)
cv2.waitKey(0)
contours, _ = cv2.findContours(image=thr_img, mode=cv2.RETR_TREE, method=cv2.CHAIN_APPROX_SIMPLE)
for idx, cnt in enumerate(contours):
print("Contour #", idx)
cv2.drawContours(image=img, contours=[cnt], contourIdx=0, color=(255, 0, 0), thickness=3)
cv2.circle(img, tuple(cnt[0][0]), 5, (255, 255, 0), 5) # Result in wrong result
cv2.circle(img, tuple(cnt[-1][0]), 5, (0, 0, 255), 5) # Result in wrong result
cv2.imshow(winname="contour" + str(idx), mat=img)
cv2.waitKey(0)
原始图像:
我也试过cornerHarris
,但它给了我一些额外的分数
有人能提出一个准确和更好的方法吗
我想建议一种更简单、更有效的方法,更重要的是,它不会产生错误的端点:
想法很简单,在细化后,计算相邻像素(8连接性)
if neighbours count equals 1 > the point is an end point
代码是不言自明的:
主要内容:
输出:
编辑:您可能有兴趣访问我对this similar question的答案。它有一些额外的功能,它检测端点和连接器点以及
此解决方案使用this approach的Python实现。其思想是使用一个特殊的内核来卷积图像,该内核标识一行中的起点/终点。以下是步骤:
现在,这将是所提出算法的第一次迭代。但是,根据输入图像的不同,可能存在重复的端点-彼此太近的单个点,可以连接。因此,让我们合并一些额外的处理来消除这些重复点
这些最后的步骤太笼统了,让我进一步阐述一下当我们达到这一步时消除重复的想法。让我们看看第一部分的代码:
到目前为止,我已经调整了图像的大小(到原始比例的
0.5
),并将其转换为灰度(实际上是一个反转的二值图像)。现在,检测端点的第一步是将线width
规范化为1 pixel
。这是通过计算skeleton
来实现的,可以使用OpenCV的扩展图像处理模块来实现:这是骨架:
现在,让我们运行端点检测部分:
查看原始链接以了解有关此方法的信息,但一般的要点是,内核是这样的:作为邻域求和的结果,与一行中的端点进行卷积将产生
110
的值。涉及到float
操作,因此必须小心数据类型和转换。可在此处观察该程序的结果:但是,请注意,这些是端点,如果它们太近,则可以连接一些点。现在是重复消除步骤。让我们首先定义检查点是否重复的标准。如果点太近,我们将加入他们。让我们提出一种基于形态学的点接近方法。我将用大小为
3
和3
的rectangular kernel
迭代来扩展端点掩码。如果两个或多个点太近,它们的膨胀将产生一个大的、独特的斑点:这是扩张的结果。我将此图像称为
groupsMask
:请注意,有些点现在是如何共享邻接的。我将使用此遮罩作为生成最终质心的指南。算法是这样的:通过
endPointsMask
循环,为每个点生成一个标签。使用dictionary
存储标签和共享该标签的所有质心-使用groupsMask
通过flood-filling
在不同点之间传播标签。在dictionary
中,我们将存储质心簇标签、质心总和的累积以及累积的质心数量的计数,这样我们可以生成最终平均值。像这样:这里有一些程序的动画,首先,一个接一个地处理质心。我们正试图将这些似乎彼此接近的点连接起来:
正在使用新标签填充的组掩码。将共享标签的点添加在一起以生成最终平均点。这有点难看,因为我的标签从
1
开始,但您几乎看不到正在填充的标签:现在,剩下的就是得出最后的结论。循环浏览字典,检查质心及其计数。如果计数大于
1
,则质心表示累加,必须除以其计数要得出最后一点:这是最终图像,显示线条的端点/起点:
现在,端点检测方法,或者更确切地说,卷积步骤,在曲线上产生了一个明显的额外点,这可能是因为直线上的一段与其邻域过于分离——将曲线分成两部分。也许在卷积之前应用一点形态学可以解决这个问题
相关问题 更多 >
编程相关推荐