【问题标题】:Determine corner coords from a set of coords on a page Python / OpenCV从页面 Python / OpenCV 上的一组坐标中确定角坐标
【发布时间】:2013-12-18 09:54:34
【问题描述】:

给定一组点,我如何确定左上、右上、右下和左下(TL、TR、BR、BL)

这些是黑色方块的坐标,如下图所示。 (页面两边各 4 个)

这是坐标 (x,y)(原点 0,0 在左上角):

[(147.68485399616046, 3304.5385975548143),
(168.3419544680192, 2336.686128749161),
(188.1491476566771, 1331.864619054719),
(211.6472437750393, 155.6040367158578),
(2216.6064720878203, 3330.396441392227),
(2233.7510405426237, 2363.6828015004367),
(2250.9856437171966, 1360.935679736544),
(2273.392518618822, 187.8742947415933)]

通过沿 x 轴对这些内容进行排序,我可以取顶部 4 和底部 4 的 4,这为页面的每一侧提供了两列。

然后我对坐标对求和,即 147+3304 = 3451 等等。通过对这个求和值上的坐标进行排序,我可以将最小值作为 TL 的坐标,将最高的值作为 BR(因为这将有最大的 x+y 组合)

http://i.stack.imgur.com/GxXJd.jpg

这工作正常,除了我遇到这组坐标:

     [(203.68919057903938, 154.66471253728272),
     (2264.8873935264055, 180.78268029528675),
     (987.6169366297244, 1156.4133276499006),
     (184.2811080835604, 1331.004238570996),
     (167.45816773667582, 2336.89386528075),
     (2236.836364657011, 2356.0815089255643),
     (150.94371083838226, 3304.3057324840765),
     (2223.8576991353148, 3323.427188913703)]

当按上述方式处理时,我得到一个错误的 TR 位置 987、1156 而不是 2264、180

    http://i.stack.imgur.com/aVp4f.jpg

那么我如何以编程方式确定我的 4 个角坐标?

请注意,我已经编辑了这些图像,但它们仍然提供相同的输出。

http://i.stack.imgur.com/cyMG5.jpg
http://i.stack.imgur.com/aVp4f.jpg
http://i.stack.imgur.com/h8ylN.jpg
http://i.stack.imgur.com/rF7Sw.jpg
http://i.stack.imgur.com/GxXJd.jpg
http://i.stack.imgur.com/837nR.jpg

【问题讨论】:

  • 您是否总是知道您在图像中搜索的正方形的分辨率/大小?如果是这样,也许模板匹配会容易得多。此外,其中一张图像根本没有正方形。您对此有何期待?剪掉正方形的那个怎么样(整个正方形不在图像中)?最后,也是最重要的是,我并没有真正看到对“问题”本身的描述。你得到了一些你不喜欢的结果,但我不确定你到底想要什么。你能给出每个示例图像的预期输出(以简单的格式)吗?
  • pdf 中的大小为 5 平方毫米,但这些是打印和扫描的,因此图像中正方形的实际大小会有所不同。有 2 组 3 张图像,1. 输入,2. 检测到的正方形,以及 3. 基于正方形的变换图像。第一个输出严重倾斜,因为它检测到图像中间的 TR 正方形 - 我的问题是如何计算“正确”的 TR 正方形位置,以便我可以安全地转换图像?第二组图像产生的是正确的输出。实际输出的是最后一张图片。
  • 我有一些建议可能会让您更有可能获得帮助。 1)清楚地列出你想做什么。 2) 清楚地识别出你所期望的事情和你所期望的事情。 3) 最重要的是,在这种情况下,隔离您的问题的最小版本,该版本不起作用。可能对您来说看起来很容易,因为您已经处理过它,但是该代码块对于 stackoverflow 来说是巨大的,并且程序输出也很大。任何想提供帮助的人或多或少都必须深入了解整个事情以了解如何改进它。如果可能,进一步隔离问题。
  • 我不是要撕破你的问题——我想帮忙,但我没有时间研究整个事情,另外我仍然不清楚哪些部分正在工作,哪些部分不是,预期的结果是什么。如果您有机会,请按原样编辑问题(而不是发布新问题),我会尝试再次查看它。或者也许比我更好的人会在此期间解决它。
  • 谢谢 显然这是我对 SO 的第一篇文章,显然我太冗长了。我刚刚重写了这个问题,希望现在更简洁。

标签: python opencv registration coords


【解决方案1】:

这是一种效率低下,但我认为直截了当的方法。

TL、TR、BL、BR的基本特点是离每个角最近。如果你取任意一组 xy 点,那么你需要做的就是找到到每个角落的最短距离。

下面的代码正是用蛮力完成的(比较所有点和所有角)。它可以复制粘贴到解释器。由于我不知道您给定图像的极值,因此我必须根据可用点来获取它们。您可以通过提供图像本身的角来跳过它。


ok = [(147.68485399616046, 3304.5385975548143),
      (168.3419544680192, 2336.686128749161),
      (188.1491476566771, 1331.864619054719),
      (211.6472437750393, 155.6040367158578),
      (2216.6064720878203, 3330.396441392227),
      (2233.7510405426237, 2363.6828015004367),
      (2250.9856437171966, 1360.935679736544),
      (2273.392518618822, 187.8742947415933)]
bad = [(203.68919057903938, 154.66471253728272),
       (2264.8873935264055, 180.78268029528675),
       (987.6169366297244, 1156.4133276499006),
       (184.2811080835604, 1331.004238570996),
       (167.45816773667582, 2336.89386528075),
       (2236.836364657011, 2356.0815089255643),
       (150.94371083838226, 3304.3057324840765),
       (2223.8576991353148, 3323.427188913703)]


def distance(xy1, xy2):
    (x1, y1), (x2, y2) = xy1, xy2
    return ((float(y2-y1))**2 + (float(x2-x1))**2)**0.5


def fake_image_corners(xy_sequence):
    """Get an approximation of image corners based on available data."""
    all_x, all_y = zip(*xy_sequence)
    min_x, max_x, min_y, max_y = min(all_x), max(all_x), min(all_y), max(all_y)
    d = dict()
    d['tl'] = min_x, min_y
    d['tr'] = max_x, min_y
    d['bl'] = min_x, max_y
    d['br'] = max_x, max_y
    return d


def corners(xy_sequence, image_corners):
    """Return a dict with the best point for each corner."""
    d = dict()
    d['tl'] = min(xy_sequence, key=lambda xy: distance(xy, image_corners['tl']))
    d['tr'] = min(xy_sequence, key=lambda xy: distance(xy, image_corners['tr']))
    d['bl'] = min(xy_sequence, key=lambda xy: distance(xy, image_corners['bl']))
    d['br'] = min(xy_sequence, key=lambda xy: distance(xy, image_corners['br']))
    return d


def main():
    for xy_sequence in (ok, bad):
        image_corners = fake_image_corners(xy_sequence)
        d = corners(xy_sequence, image_corners)
        print '********'
        for k, v in d.items():
            print k, v

main()

输出:

********
bl (147.68485399616046, 3304.5385975548143)
tl (211.6472437750393, 155.6040367158578)
tr (2273.392518618822, 187.8742947415933)
br (2216.6064720878203, 3330.396441392227)
********
bl (150.94371083838226, 3304.3057324840765)
tl (203.68919057903938, 154.66471253728272)
tr (2264.8873935264055, 180.78268029528675)
br (2223.8576991353148, 3323.427188913703)

【讨论】:

  • 谢谢。我设法尝试了这个,它确实工作得很好。我不得不在 main( ) 在该位置绘制,因为它抱怨需要整数而不是浮点数。
猜你喜欢
  • 2021-06-29
  • 2016-12-31
  • 2012-03-16
  • 1970-01-01
  • 2021-03-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多