跟随OpenCV的山脊 - 返回'ridges'阵列

时间:2016-04-12 12:16:46

标签: opencv image-processing emgucv

我正在寻找一种方法,在图像中找到脊(局部最大值)并将它们作为脊的阵列返回(其中脊是定义脊的点的矢量)。也就是说,一种方法,其行为与findContours完全相同(查找轮廓并将其作为定义轮廓的矢量数组返回),除了脊。

这是否存在,如果不存在,我将如何实现这种效果? (我正在使用OpenCV的Emgu CV包装器)

我有这个图像(它有点模糊,对不起),使用道路系统的二进制图像的距离变换获得:

Distance transform of binary image of a road system

我可以轻松地在原始二进制图像上使用findContours来获取道路轮廓作为点的向量。不过我对道路中心线感兴趣。道路中心线由上面的图像的局部最大值表示。

显然,在这张图片上使用findContours再次为我提供了道路轮廓。我打算使用非最大值抑制除去中心线以外的所有内容,并使用findContours,但我不知道如何进行非最大值抑制,因此我的问题here

1 个答案:

答案 0 :(得分:0)

您希望沿每条线的渐变方向进行最大抑制。

  1. 计算渐变方向。
  2. 对于每个点,沿着局部渐变方向的线搜索最大值。 2.1如果当前点是最大标记,否则标记为零
  3. import cv2
    import numpy as np
    import math
    from matplotlib import pyplot as plt
    
    # Read image
    Irgb = cv2.imread('road.png')
    I = Irgb[:,:,0]
    
    # Find the gradient direction
    sobelx = cv2.Sobel(I,cv2.CV_64F,1,0,ksize=1)
    sobely = cv2.Sobel(I,cv2.CV_64F,0,1,ksize=1)
    
    gradDirection = np.zeros(I.shape, np.float64)
    
    for y in range(I.shape[0]):
        for x in range(I.shape[1]):
            gradDirection[y, x] = np.float64(math.atan2(sobely[y,x], sobelx[y,x]))
    
    # Iterate on all points and do max suppression
    points = np.nonzero(I)
    points = zip(points[0], points[1])
    maxSuppresion = np.zeros_like(I)
    for point in points:
        y = point[0]
        x = point[1]
    
        # Look at local line along the point in the grad direction
        direction = gradDirection[y, x]
        pointValues = []
        for l in range(-1,2):
            yLine = int(np.round(y + l * math.sin(direction)))
            xLine = int(np.round(x + l * math.cos(direction)))
    
            if(yLine < 0 or yLine >= maxSuppresion.shape[0] or xLine < 0 or xLine >= maxSuppresion.shape[1]):
                continue
    
            pointValues.append(I[yLine,xLine])
    
        # Find maximum on line
        maxVal = np.max(np.asarray(pointValues))
    
        # Check if the current point is the max val
        if I[y,x] == maxVal:
            maxSuppresion[y, x] = 1
        else:
            maxSuppresion[y, x] = 0
    
    # Remove small areas
    im2, contours, hierarchy = cv2.findContours(maxSuppresion,cv2.RETR_CCOMP,cv2.CHAIN_APPROX_NONE )
    minArea = 5
    maxSuppresionFilter = np.zeros_like(maxSuppresion)
    finalShapes = []
    for contour in contours:
        if contour.size > minArea:
            finalShapes.append(contour)
    
    cv2.fillPoly(maxSuppresionFilter, finalShapes, 1)
    cv2.imshow('road',maxSuppresionFilter*255)
    

    最后会得到以下图片: enter image description here

    您可以看到在交叉点周​​围仍然存在问题,其中局部最大抑制抑制了交叉点中心旁边的点。您可以尝试使用形态学操作来克服这些问题。