这里有一些基本信息。当解决新问题时,我不认为尝试许多复杂步骤是有价值的,只因为它们可以在某个地方使用。所以我的重点是使用相对简单的东西,在更多的情况下会失败,但希望你能看到它的价值并对问题有一些感觉。
这种方法完全基于角点检测; 这种检测的两种典型方法是Harris检测器或Shi和Tomasi在1994年的论文“Good Features to Track”中描述的方法。我将使用第二种方法,只是因为OpenCV、新版Matlab和可能许多其他地方都有现成的实现。这些软件包上的实现还允许更容易地调整参数,例如角质量和角之间的最小距离。那么,假设您可以正确检测出所有角点,如何基于这些点测量一个形状与另一个形状的接近程度?图像具有任意大小,因此我的想法是将点坐标归一化到[0,1]范围内。这解决了缩放问题,这是原始描述所需的。现在我们必须在[0,1]范围内比较点集。这里我们采用最简单的方法:考虑来自形状a的一个点p,那么形状b中最接近的点是什么?我们假设它是与这个点p和b中任何点之间的最小绝对差异。如果我们将所有值相加,我们就会得到形状之间的评分。得分越低,形状越相似(根据这种方法)。
这里有一些我画的形状:
这里是检测到的角点:
通过上述图片,我们可以清晰地看到这种方法很容易将矩形/正方形与圆柱体混淆。为了解决这个问题,您需要将此方法与其他描述符相结合。最初,您可以考虑一个简单的比率,即形状面积与其边界框面积之间的比值(矩形为1,圆柱体则更低)。
使用上述方法,以下是第一和第二形状、第一和第三形状等之间的测量值:0.02358485、0.41350339、0.30128458、0.4980852、0.18031262。第二个立方体是第一个立方体的调整大小版本,如您所见,它们在这个指标上非常相似。最后一个形状是第一个立方体的调整大小版本,但没有保持长宽比,因此该指标显示出更高的差异。
如果您想尝试执行此操作的代码,请参见下面的Python代码(取决于OpenCV、numpy):
import sys
import cv2 as cv
import numpy
inp = []
for fname in sys.argv[1:]:
img_color = cv.imread(fname)
img = cv.cvtColor(img_color, cv.COLOR_RGB2GRAY)
inp.append((img_color, img))
ptsets = []
params = (
200,
0.01,
10,
)
circle_radii = 3
circle_color = (255, 0, 0)
for i, (img_color, img) in enumerate(inp):
height, width = img.shape
cornerMap = cv.goodFeaturesToTrack(img, *params)
corner = numpy.array([c[0] for c in cornerMap])
for c in corner:
cv.circle(img_color, tuple(c), circle_radii, circle_color, -1)
cv.imwrite('temp_%d.png' % i, img_color)
cornerUnity = (corner - corner.min()) / (corner.max() - corner.min())
ptsets.append(cornerUnity)
def compare_ptsets(p):
res = numpy.zeros(len(p))
base = p[0]
for i in xrange(1, len(p)):
sum_min_diff = sum(numpy.abs(p[i] - value).min() for value in base)
res[i] = sum_min_diff
return res
res = compare_ptsets(ptsets)
print res