如何提取图像中开放曲线/轮廓的顶点?

问题描述 投票:0回答:1

我有如下图所示的图像,我想提取轮廓并按顺时针或逆时针顺序排列顶点。我需要使用它们进行一些计算,因此必须对其进行排序,以便通过遍历轮廓找到点。

我尝试使用

cv2.findContours()
但是,它返回闭合轮廓。

标题是脚本当前的执行时间。

你可以看到它明显翻倍了。

我尝试仅提取唯一的坐标,但这会导致排序出现一些问题。 (忽略红线)

提取轮廓的代码:

代码

 dirPictures = os.listdir(sourcePath)

 for path in dirPictures:
    if( '.' in path and path.split('.')[-1].lower() in acceptedFileTypes):
        
        #Reset plots to default figure size
        plt.rcParams["figure.figsize"] = plt.rcParamsDefault["figure.figsize"]
        plt.gca().invert_yaxis()
        
                    
        # Extract contour
        img = cv2.imread(sourcePath + '/' + path, cv2.IMREAD_GRAYSCALE)
        cont, hier = cv2.findContours(img, cv2.RETR_LIST, cv2.CHAIN_APPROX_NONE)

编辑:

我认为使用

np.where()
和排序的想法是有效的,但在某些情况下仍然会失败。计数顶点不是从轮廓的边缘开始,所以我不相信排序会起作用。

结束位置:

编辑2: 我尝试使用 svg 路径,但也失败了。我利用了tatrize的

potracer
这里

代码:

        # Extract contour
        img = cv2.imread(sourcePath + '/' + path, cv2.IMREAD_GRAYSCALE)
        img = np.array(img)

        # Create a bitmap from the array
        bmp = potrace.Bitmap(img)
        
        # Trace the bitmap to a path
        path = bmp.trace()

        # Iterate over path curves
        x = []
        y = []
        
        for curve in path:
            print ("start_point =", curve.start_point)
            for segment in curve:
                print(segment)
                end_point_x, end_point_y = segment.end_point.x, segment.end_point.y
                if segment.is_corner:
                    c_x, c_y = segment.c.x, segment.c.y 
                else:
                    c1_x, c1_y = segment.c1.x, segment.c1.y
                    c2_x, c2_y = segment.c2.x, segment.c2.y
                    x.append(c1_x)
                    y.append(c1_y)
                    x.append(c2_x)
                    y.append(c2_y)

        #turn into array of coord pairs [[x,y]...]         
        k = np.stack((x,y), axis=-1)

        #Keep unique, ordered points
        _, idx = np.unique(k, axis=0,  return_index=True)
        k = k[np.sort(idx)]
        
        plt.plot(k[:,0], k[:,1], 'g.-')
        plt.show()
python opencv image-processing contour
1个回答
2
投票

您可能会发现使用

potrace
将形状转换为 SVG 并解析其输出更容易。因此,如果将形状保存为 PGM 文件,则可以运行:

potrace YOURIMAGE.PGM --svg

您将得到以下信息:

<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
 width="88.000000pt"     height="51.000000pt" viewBox="0 0 88.000000 51.000000" preserveAspectRatio="xMidYMid meet">
<metadata>
Created by potrace 1.16, written by Peter Selinger 2001-2019
</metadata>
<g transform="translate(0.000000,51.000000) scale(0.100000,-0.100000)"
fill="#000000" stroke="none">
<path d="M0 255 l0 -255 424 0 c284 0 427 3 431 10 4 6 -23 39 -59 74 -54 52
-66 68 -66 95 0 30 -5 34 -82 72 -46 22 -94 38 -108 37 -25 -3 -25 -4 -22 -78
3 -68 2 -77 -20 -96 -14 -13 -43 -25 -73 -28 -44 -6 -54 -4 -84 18 -45 34 -71
33 -103 -4 -14 -17 -36 -30 -47 -30 -13 0 -25 -9 -31 -22 -5 -14 -9 -17 -9 -7
-1 20 19 39 41 39 10 0 30 14 45 30 32 37 59 38 104 4 30 -22 40 -24 84 -18
78 10 89 25 81 110 -9 110 22 119 159 46 64 -34 70 -40 73 -71 3 -27 17 -48
69 -97 35 -35 62 -68 58 -74 -3 -5 -1 -10 4 -10 8 0 11 82 11 255 l0 255 -440
0 -440 0 0 -255z"/>
</g>
</svg>
© www.soinside.com 2019 - 2024. All rights reserved.