线组之间的距离

4
假设我的图像是简单的形状-一组线条、点、曲线和简单的物体,如何计算图像之间的距离-所以长度很重要但总比例不重要,线\曲线的位置很重要,角度也很重要等等。
例如附图:
我的比较对象是左上角的立方体,分数只是为了这个例子而虚构的。
1.到圆柱体的距离为80(有2条线,但顶部几何形状不同)。 2.左下角的立方体得分为100,因为它与不同比例的线完全匹配。 3.右下角的矩形得分为90,因为它在顶部有完全匹配的线,但在侧面有不同比例的线。
我正在寻找算法名称或通用方法,可以帮助我开始思考解决方案...
谢谢您的帮助。

你忘记在问题中评论一个非常重要和关键的方面:这些形状是如何获得的?是有人手动绘制它们吗?或者,也许你有一组定义形状的点?如果是前者,那么你有一个非常困难的问题,只能通过猜测来近似解决。 - mmgp
我将通过边缘和线条检测或霍夫变换获取图像。原始图像是简单形状的灰度图像,如立方体、圆形、三角形等,因此变换输出应该(理论上)与原始输入匹配。 - JavaSheriff
好的,但我很好奇你将如何使用Hough处理任意行 :) 如果我晚些时候有时间,我会根据您更新的信息贡献一些答案。 - mmgp
我在考虑任意的线条和点将参与评分机制,我不知道这将如何工作,我需要寻找算法名称或方法。 - JavaSheriff
我仍然好奇你怎么打算使用Hough处理任意曲线线条。 - mmgp
3个回答

2
这里有一些基本信息。当解决新问题时,我不认为尝试许多复杂步骤是有价值的,只因为它们可以在某个地方使用。所以我的重点是使用相对简单的东西,在更多的情况下会失败,但希望你能看到它的价值并对问题有一些感觉。
这种方法完全基于角点检测; 这种检测的两种典型方法是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 = []

# Corner detection parameters.
params = (
        200,  # max number of corners
        0.01, # minimum quality level of corners
        10,   # minimum distance between corners
)
# Params for visual circle markers.
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)

    # Just to visually check for correct corners.
    cv.imwrite('temp_%d.png' % i, img_color)

    # Convert corner coordinates to [0, 1]
    cornerUnity = (corner - corner.min()) / (corner.max() - corner.min())
    # You might want to use other descriptors here. XXX
    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

非常感谢您提供详细的答案,任意曲线确实是我的问题。您认为如何处理曲线? - JavaSheriff
角点检测也是一个很好的起点。在检测到角点之后,您可以轻松地分割线条。现在这取决于这些曲线实际上有多么任意。如果我自己解决这个问题,并且在我的头脑中施加了一些限制,我可能会执行样条逼近来确定两个图形中的线条相似程度。 - mmgp

1
需要跟随的过程取决于您考虑的功能深度和所需的准确性。
如果您想要更准确的结果,请查阅一些技术论文,例如this,这可以提供一个具体且经过验证的方法或算法。
编辑:
从AI中Waltz算法的思路可以进行调整,这只是我的想法。解释原始图像,生成一些约束条件。对于每个候选者,找出它满足的约束数量。满足更多限制条件的候选者将与原始图像最相似。

0
尝试为每个图形计算质心。将图形的每个点视为具有质量等于1的粒子。
然后计算每个距离为sqrt((x1-x2)^2 + (y1-y2)^2),其中(xi,yi)是图形i的质心坐标。

你对这些距离做什么? - irrelephant

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