【问题标题】:Follow ridges with OpenCV - return array of 'ridges'使用 OpenCV 跟随山脊 - 返回“山脊”数组
【发布时间】:2016-08-03 01:11:53
【问题描述】:

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

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

我有这张图片(有点模糊,抱歉),使用距离变换从道路系统的二值图像获得:

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

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

【问题讨论】:

  • findContours 怎么不给你你想要的?您是否有示例说明您尝试过的方法以及它们如何未能为您提供所需的结果?
  • 感谢您的评论 - 请查看新的修改。

标签: opencv image-processing emgucv


【解决方案1】:

你想沿着每条线的梯度方向做最大抑制。

  1. 计算梯度方向。
  2. 对于每个点,沿着局部梯度方向的一条线搜索最大值。 2.1 如果当前点是最大值标记为1,否则标记为0
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)

最后会得到如下图:

您可以看到仍然存在问题,特别是在交叉点周​​围,局部最大值抑制抑制了交叉点中心旁边的点。您可以尝试使用形态学运算来解决这些问题。

【讨论】:

    猜你喜欢
    • 2014-08-01
    • 2020-10-08
    • 2016-06-24
    • 1970-01-01
    • 2018-05-02
    • 1970-01-01
    • 1970-01-01
    • 2020-06-01
    • 1970-01-01
    相关资源
    最近更新 更多