我有如下图所示的图像,我想提取轮廓并按顺时针或逆时针顺序排列顶点。我需要使用它们进行一些计算,因此必须对其进行排序,以便通过遍历轮廓找到点。
我尝试使用
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()
您可能会发现使用
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>