从曲率的上下阈值进行点/特征检测 - 曲线四边形形状检测算法

7

能否从具有粗糙曲率的一条线上的一组点创建多边形,使得这些点在两个曲率值之间选择?

我试图使用Python的OpenCV包(cv2)从给定图像中检索一个近似的曲线四边形形状。

例如: 给定经过边缘检测的图像如下:

使用cv2.findContours找到轮廓,如下所示:

(顺便提一下:如果它能给出一个类似正方形的形状而不是绕着线走就太好了 - 还需要一种算法来填补该图像右侧形状的空隙。膨胀/腐蚀可能有效,但可能会丢失某些需要保留的特征。)

之后,我们可以像这样在轮廓上使用polyDPApprox:

然而,这并不依赖于曲率-它只是通过使用与直线最大偏差来近似。如果我们想要省略一些细节(这些细节可能来自错误),并保留曲率较小的点(广义形状)-我们可以使用一个函数提供类似的东西吗?(红色填充仅显示该形状将闭合为曲线四边形。)

相关问题: 在OpenCV中,是否可以绘制局部曲率作为热图来表示物体的“尖锐度”?

以下是用于分析输入图像的函数(如果有人需要):

# input binary image
def find_feature_points(img):
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    cv2.namedWindow('img', WINDOW_NORMAL)
    cv2.imshow("img", gray)
    cv2.waitKey(0)

    contours, hierarchy = cv2.findContours(gray, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

    # Draw contours to image
    print contours
    copy = img.copy()
    # img - Image.
    # pts - Array of polygonal curves.
    # npts - Array of polygon vertex counters.
    # ncontours - Number of curves.
    # isClosed - Flag indicating whether the drawn polylines are closed or not. If they are closed, the function draws a line from the last vertex of each curve to its first vertex.
    # color - Polyline color.
    # thickness - Thickness of the polyline edges.
    # lineType - Type of the line segments. See the line() description.
    # shift - Number of fractional bits in the vertex coordinates.
    cv2.polylines(img=copy, pts=contours, isClosed=1,  color=(0,0,255), thickness=3)

    cv2.namedWindow('contour', WINDOW_NORMAL)
    cv2.imshow("contour", copy)
    cv2.waitKey(0)

    # Find approximation to contours
    approx_conts = []
    for c in contours:
        curve = c
        epsilon = 200
        closed = True
        approx_conts.append(cv2.approxPolyDP(curve, epsilon, closed))

    # draw them
    cv2.drawContours(img, approx_conts, -1, (0, 255, 0), 3)
    cv2.namedWindow('approx', WINDOW_NORMAL)
    cv2.imshow("approx", img)
    cv2.waitKey(0)
    return 
1个回答

0

这里是一个可能的解决方案。思路如下:

  1. 获取二进制图像。 加载图像,转换为灰度图像,并使用Otsu阈值
  2. 找到凸包。 确定对象的周围周长并将其绘制到掩模上
  3. 执行形态学操作。 使用形态学闭合填充小孔以连接轮廓
  4. 绘制轮廓。 找到掩模的外部轮廓并绘制到图像上

输入图像 -> 结果

enter image description here enter image description here

代码

import cv2
import numpy as np

# Load image, convert to grayscale, threshold
image = cv2.imread('1.png')
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)[1]

# Find convex hull and draw onto a mask
mask = np.zeros(image.shape, dtype=np.uint8)
cnts = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
cnt = cnts[0]
hull = cv2.convexHull(cnt,returnPoints = False)
defects = cv2.convexityDefects(cnt,hull)
for i in range(defects.shape[0]):
    s,e,f,d = defects[i,0]
    start = tuple(cnt[s][0])
    end = tuple(cnt[e][0])
    far = tuple(cnt[f][0])
    cv2.line(mask,start,end,[255,255,255],3)

# Morph close to fill small holes
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (3,3))
close = cv2.morphologyEx(mask, cv2.MORPH_CLOSE, kernel, iterations=2)

# Draw outline around input image
close = cv2.cvtColor(close, cv2.COLOR_BGR2GRAY)
cnts = cv2.findContours(close, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
cv2.drawContours(image,cnts,0,(36,255,12),1)

cv2.imshow('image', image)
cv2.waitKey()

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接