确定凹点

时间:2018-09-22 02:40:28

标签: algorithm opencv image-processing

如果使用goodFeaturesToTrack,则可以获得所有角点(红色,蓝色)。但是,我只想保留凹点(蓝色)。我不知道如何执行。我该怎么办?

enter image description here enter image description here

下图是实际的运行示例: enter image description here

2 个答案:

答案 0 :(得分:2)

正如评论中提到的那样,似乎很容易在这里做的事情是使用盒式滤波器(或类似的椭圆形形状)对图像进行卷积,这将为您提供整个图像的窗口平均值。您只需在转折点处索引此卷积结果即可。如果在这些点处的卷积结果超过50%,则该点周围会有更多白色,因此,这是一个凹点。否则,它是凸的。这就是代码中的样子。

import cv2
import numpy as np
from itertools import tee

def pairwise(iterable):
    a, b = tee(iterable)
    next(b, None)
    return zip(a, b)

# read image as grayscale
img = cv2.imread('example.png', 0)

# get corner points, remove duplicate/nearby points
contours = cv2.findContours(img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)[1]
contour = contours[0]
pts = np.array([contour[0]] + [pt1 for pt0, pt1 in pairwise(contour) if not (abs(pt0 - pt1) <= 1).all()])
x, y = pts[:, -1, 0], pts[:, -1, 1]

# get the kernel that you will sum around your corner points
kernel = np.float64(cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (13, 13)))
kernel /= np.sum(kernel)

# convolve the image with the kernel, and pull out the sums at the corner points
conv = cv2.filter2D(img/255, cv2.CV_64F, kernel)
neighborhood_sums = conv[y, x]

# concave indices have more white than black around them, so convolution will be >= 1/2
concave_indices = neighborhood_sums >= 0.5

# draw markers
marked = cv2.merge([img, img, img])
for pt, concave in zip(pts, concave_indices):
    color = (255, 0, 255) if concave else (0, 255, 0)
    marker = cv2.MARKER_TRIANGLE_UP if concave else cv2.MARKER_TRIANGLE_DOWN
    cv2.drawMarker(marked, tuple(pt[0]), color, markerType=marker, markerSize=10, thickness=3)

在导入之后,我定义了itertools recipes中的一个用于成对迭代(例如s -> (s0, s1), (s1, s2), ...)。这对问题并不是很重要,但对我来说,摆脱了从findContours()抓取的重复点很有用。之后,其余部分将按照前面的描述进行。您可以绘制自己的内核或任何您喜欢的内核,但是我只是从getStructuringElement()中提取了一个内核,因为您可以绘制任意大小的椭圆形(尽管请注意,这会返回形状奇怪的内核,但您可能会定义一个更好的圆) 。请注意,内核的大小是在此处指定的总宽度,而不仅仅是半径,并且通过其中的1数对其进行了归一化,因此结果始终在0到1之间。

这是上面第一张图片中的结果:

Marked concave vs convex points

答案 1 :(得分:1)

在不同的内核中使用HIT_MISS_MORPH的解决方案之一:

如果选择此内核:

[[-1 -1  1]
 [-1 -1  1]
 [ 1  1  1]]

然后将脱粒的图像击中,您可以获得两个锚点:

mask = cv2.morphologyEx(threshed, cv2.MORPH_HITMISS, kernel, anchor=(-1,-1))

enter image description here

在原始图片上绘制:

enter image description here


在不同内核中找到锚点(旋转基本内核并对其进行逆转或|):

enter image description here

在原始图像上以彩色显示:

enter image description here