在二进制图像中找到曲线的末端

时间:2017-01-13 10:21:56

标签: algorithm image-processing

我正在寻找能够检测曲线末端的算法。我要将二进制图像转换为点云作为坐标,我需要找到该行的结尾,以便我可以启动另一种算法。

我在考虑将每个点的N个最接近的'1'像素的矢量平均值,并且说具有最长矢量的像素必须是端点,因为如果一个点在一条线的中间那么向量的平均值将抵消。但是,我认为这一定是一个在图像处理中众所周知的问题所以我想我会把它扔到这里看看是否有人知道'正确'的算法。enter image description here

2 个答案:

答案 0 :(得分:2)

如果该行只有一个或两个像素厚,您可以在评论中使用Malcolm McLean建议的方法。

否则,一种方法是为每个红色像素计算距离最远的同一组件中的红色像素,以及距离最远像素的距离。 (在图论中,这两个像素之间的距离是每个像素的偏心率。)长线末端附近的像素将具有最大的偏心率,因为它们之间的最短路径和点在该行的另一端很长。 (请注意,无论最大偏心距离是多少,都会有至少两个像素,因为从a到b的距离与从b到a的距离相同。)

如果您有n个红色像素,则可以在O(n ^ 2)时间内计算所有偏心率(以及相应的最远像素):依次为每个像素,在该像素处启动BFS,并获取您找到的最深节点作为最远的像素(可能有几个;任何人都会这样做)。每个BFS在O(n)时间内运行,因为在任何像素上只有恒定数量的边(4或8,取决于您建模像素连接的方式)。

为了获得稳健性,您可以考虑使用前10或50(等)像素对,并检查它们是否形成2个分离良好,定义明确的聚类。然后,您可以将每个群集中的平均位置作为2个端点。

答案 1 :(得分:0)

如果对行应用细化,则行仅1像素粗,您可以利用morphologyEX并在OpenCV中使用MORPH_HITMISS。本质上,您为每个可能的角(有8个可能的角)创建一个模板(内核或过滤器),并由每个角进行卷积。每次卷积的结果在内核匹配的位置为1,否则为0。因此,如果您认为自己可以在c中做得更好,则可以手动执行相同操作。

这是一个示例。它将任何零线和零线的图像作为输入图像,其中线的宽度为一个像素。

import numpy as np
import cv2
import matplotlib.pylab as plt

def find_endoflines(input_image, show=0):

kernel_0 = np.array((
        [-1, -1, -1],
        [-1, 1, -1],
        [-1, 1, -1]), dtype="int")

kernel_1 = np.array((
        [-1, -1, -1],
        [-1, 1, -1],
        [1,-1, -1]), dtype="int")

kernel_2 = np.array((
        [-1, -1, -1],
        [1, 1, -1],
        [-1,-1, -1]), dtype="int")

kernel_3 = np.array((
        [1, -1, -1],
        [-1, 1, -1],
        [-1,-1, -1]), dtype="int")

kernel_4 = np.array((
        [-1, 1, -1],
        [-1, 1, -1],
        [-1,-1, -1]), dtype="int")

kernel_5 = np.array((
        [-1, -1, 1],
        [-1, 1, -1],
        [-1,-1, -1]), dtype="int")

kernel_6 = np.array((
        [-1, -1, -1],
        [-1, 1, 1],
        [-1,-1, -1]), dtype="int")

kernel_7 = np.array((
        [-1, -1, -1],
        [-1, 1, -1],
        [-1,-1, 1]), dtype="int")

kernel = np.array((kernel_0,kernel_1,kernel_2,kernel_3,kernel_4,kernel_5,kernel_6, kernel_7))
output_image = np.zeros(input_image.shape)
for i in np.arange(8):
    out = cv2.morphologyEx(input_image, cv2.MORPH_HITMISS, kernel[i,:,:])
    output_image = output_image + out

return output_image

if show == 1:
    show_image = np.reshape(np.repeat(input_image, 3, axis=1),(input_image.shape[0],input_image.shape[1],3))*255
    show_image[:,:,1] = show_image[:,:,1] -  output_image *255
    show_image[:,:,2] = show_image[:,:,2] -  output_image *255
    plt.imshow(show_image)