4

算法赏析——寻找线条的转折点

 3 years ago
source link: https://qixinbo.info/2021/03/27/algorithm-find-peak/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

算法赏析——寻找线条的转折点

Posted on

2021-03-27 Edited on 2021-03-29 In algorithm

Disqus: 0 Comments

图像中有一条线,如何判断这条线的转折点?
比如下面一张图:
test
目的是找到图中的三个转折点。

找到轮廓线

img = cv2.imread('test.png', 0)
conts = cv2.findContours(img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)[0][0]
xs, ys = conts[:,:,0], conts[:,:,1]

这一步实际作用是通过寻找轮廓线,从像素类型的位图中提取有意义的这条线的坐标序列,即矢量序列。
同时将横坐标和纵坐标分别提取出来。

gxs = ndimg.gaussian_filter(xs, 15, mode='wrap')
gys = ndimg.gaussian_filter(ys, 15, mode='wrap')

对横纵坐标分别做高斯模糊,相当于对一维数据做高斯模糊,同时注意上面的轮廓线寻找到的序列是首尾相连,要用到wrap这个模式。

新旧坐标对比

ds = ((xs-gxs)**2+(ys-gys)**2)**0.5

将高斯模糊后的坐标与之前的坐标进行对比,用标准差来衡量差距大小。

寻找局部极大值

maxds = ndimg.maximum_filter(ds, 100, mode='wrap')
idx = np.where((ds > ds.std()*3) & (ds==maxds))[0]

这个地方首先使用一个极大值滤波,然后再通过两个判断条件:是否大于标准差的3倍以及同时等于局部极大值。
这样就找到了局部极大值点所在的位置。
当然也可以直接用那种寻找局部极值的算法,但不如这种“极大值滤波+大于某个阈值”的方法来得简单直接。

ax = plt.subplot(211)
ax.plot(xs, ys)
ax.plot(gxs, gys)
plt.plot(xs[idx], ys[idx], 'ro')

ax = plt.subplot(212)
ax.plot(ds)
ax.plot(maxds)
ax.plot(ds/ds*ds.std()*3)
ax.plot(idx, ds[idx], 'ro')
plt.show()

将结果可视化出来:
vis_peak


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK