如何使用OpenCV连接最接近的点

4
使用Python中的OpenCV模块,可以将下面图像中的红点连接起来,使得每个红点只与其最近的邻居红点相连吗?

Red dots surrounding a pentagon


  1. 找到红点的坐标。
  2. 做两个列表,一个包含所有点(A),另一个为空(B)。
  3. 取一个点(C),找到另一个距离它最近的点(D),然后将这两个点从 A 中移除并放入 B 中,再对找到的与初始点最接近的点(D)重复此步骤,直到 A 中的点用完...如果出现像图片中的间隙,找到 B 中成对的点之间最大的距离,并将列表移到该点...然后使用 drawContours 就完成了 :)
- api55
1
“once” 是什么意思? - user1196549
1个回答

7

首先,您应该使用适当的工具(如cv2.cvtColor()cv2.threshold()cv2.bitwise_not()等)将图像转换为二进制图像 - 这意味着您的图像只包含黑色或白色像素。

示例:

enter image description here

然后您应该在图像上找到轮廓(cv2.findContours),并使用大小标准(cv2.contourArea())过滤掉其他轮廓,如图像中间的大五边形。

下一步,您应该找到每个轮廓的矩(cv2.moments()),这样您就可以获取轮廓中心的x和y坐标,并将它们放入列表中。(注意将正确的x和y坐标一起附加)。

在获取到您的点之后,您可以计算所有点之间的距离(使用两点之间的距离公式-sqrt((x2-x1)^2+(y2-y1)^2)

然后,您可以使用任何逻辑来获取每个点最短距离的点的坐标(在下面的示例中,我将它们压缩在一个列表中,并创建了一个包含每个点的距离、x和y坐标的数组)。

代码示例:

    import numpy as np
    import cv2

    img = cv2.imread('points.jpg')
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    ret, threshold = cv2.threshold(gray,150,255,cv2.THRESH_BINARY)
    cv2.bitwise_not(threshold, threshold)
    contours, hierarchy = cv2.findContours(threshold,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE)
    listx = []
    listy=[]
                         
    for cntr in range(0, len(contours)):
        cntr = contours[i]
        size = cv2.contourArea(cntr)
        if size < 1000:
            M = cv2.moments(cntr)
            cX = int(M["m10"] / (M["m00"] + 1e-5))
            cY = int(M["m01"] / (M["m00"] + 1e-5))
            listx.append(cX)
            listy.append(cY)

    listxy = list(zip(listx,listy))
    listxy = np.array(listxy)

    for x1, y1 in listxy:    
        distance = 0
        secondx = []
        secondy = []
        dist_listappend = []
        sort = []   
        for x2, y2 in listxy:      
            if (x1, y1) == (x2, y2):
                pass     
            else:
                distance = np.sqrt((x1-x2)**2 + (y1-y2)**2)
                secondx.append(x2)
                secondy.append(y2)
                dist_listappend.append(distance)               
        secondxy = list(zip(dist_listappend,secondx,secondy))
        sort = sorted(secondxy, key=lambda second: second[0])
        sort = np.array(sort)
        cv2.line(img, (x1,y1), (int(sort[0,1]), int(sort[0,2])), (0,0,255), 2)

    cv2.imshow('img', img)
    cv2.imwrite('connected.png', img)

结果:

enter image description here

如您所见,结果中的每个点现在都与其最近的邻居点相连。希望这能有所帮助,或者至少给出解决问题的思路。干杯!


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接