【问题标题】:OpenCV: fit the detected edgesOpenCV:拟合检测到的边缘
【发布时间】:2015-08-21 18:00:27
【问题描述】:

我使用精明的边缘检测来检测水波的边缘。但是,我想为这个边缘拟合一条曲线。这在 OpenCV 中可能吗?

这是边缘检测之前的图像:

这是边缘检测操作的结果:

代码复制自 OpenCV 教程中的示例:

import cv2
import numpy as np
from matplotlib import pyplot as plt

img = cv2.imread('BW.JPG',0)
edges = cv2.Canny(img,100,200)

plt.plot(1),plt.imshow(edges,cmap = 'gray')
plt.title('WAVE')
plt.show()

【问题讨论】:

    标签: python opencv curve-fitting edge-detection


    【解决方案1】:

    波浪非常简单,因此我们将多项式曲线拟合到由cv2 的输出定义的主边。首先,我们想要获得主边的 of 点。假设您的原点与图像上的左上角一样。查看原始图像,我认为如果我们只取范围 (750, 1500) 中具有最大 y 的点,我们将对我们的兴趣点有一个很好的近似值。

    import cv2
    import numpy as np
    from matplotlib import pyplot as plt
    from numba import jit
    
    # Show plot
    img = cv2.imread('wave.jpg',0)
    edges = cv2.Canny(img,100,200)
    
    # http://stackoverflow.com/a/29799815/1698058
    # Get index of matching value.
    @jit(nopython=True)
    def find_first(item, vec):
        """return the index of the first occurence of item in vec"""
        for i in range(len(vec)):
            if item == vec[i]:
                return i
        return -1
    
    bounds = [750, 1500]
    # Now the points we want are the lowest-index 255 in each row
    window = edges[bounds[1]:bounds[0]:-1].transpose()
    
    xy = []
    for i in range(len(window)):
        col = window[i]
        j = find_first(255, col)
        if j != -1:
            xy.extend((i, j))
    # Reshape into [[x1, y1],...]
    data = np.array(xy).reshape((-1, 2))
    # Translate points back to original positions.
    data[:, 1] = bounds[1] - data[:, 1]
    

    如果我们绘制这些点,我们可以看到它们非常接近我们的目标。

    plt.figure(1, figsize=(8, 16))
    ax1 = plt.subplot(211)
    ax1.imshow(edges,cmap = 'gray')
    ax2 = plt.subplot(212)
    ax2.axis([0, edges.shape[1], edges.shape[0], 0])
    ax2.plot(data[:,1])
    plt.show()
    

    现在我们已经有了一个坐标对数组,我们可以使用numpy.polyfit 来生成最佳拟合多项式的系数,并使用numpy.poly1d 从这些系数中生成函数。

    xdata = data[:,0]
    ydata = data[:,1]
    
    z = np.polyfit(xdata, ydata, 5)
    f = np.poly1d(z)
    

    然后绘制验证

    t = np.arange(0, edges.shape[1], 1)
    plt.figure(2, figsize=(8, 16))
    ax1 = plt.subplot(211)
    ax1.imshow(edges,cmap = 'gray')
    ax2 = plt.subplot(212)
    ax2.axis([0, edges.shape[1], edges.shape[0], 0])
    ax2.plot(t, f(t))
    plt.show()
    

    【讨论】:

    • 三角函数不是更自然地建模波浪吗?形状明显正弦。
    • 我试试看!我的想法是多项式在这里可能会更好地工作,因为它可以更紧密地拟合最左边和最右边的较浅区域。不是我的,但过滤和/或丢弃一些点可能会产生更好的结果。
    • 谢谢克里斯,这就是我想要的。抱歉,我看到这个有点晚了。它可以在我的笔记本电脑上运行,但是我无法让它在我的 Raspberry Pi 2 上运行,因为我找不到安装“numba”的方法。有什么建议吗?
    • 不用担心。 numba 只需要通过在执行之前编译 find_first 操作来提高效率。您可以只删除导入语句和装饰器@jit(nopython=True)。我刚刚做了一个测试,numba 运行时间约为 80 毫秒,没有运行时间约为 3.5 秒,这很重要,但仍然合理,具体取决于您的应用程序。
    猜你喜欢
    • 2017-01-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多