从Python/OpenCV页面上的一组坐标确定角坐标

从Python/OpenCV页面上的一组坐标确定角坐标,python,opencv,registration,coords,Python,Opencv,Registration,Coords,给定一组点,我如何确定哪些是左上角、右上角、右下角和左下角(TL、TR、BR、BL) 这些是黑色正方形的坐标,如下图所示。(页面每侧下方4个) 以下是坐标(x,y)(原点0,0位于左上方): 通过沿x轴对这些列进行排序,我可以选择顶部的4列和底部的4列,这两列分别对应于页面的每一侧 然后我对坐标对求和,即147+3304=3451,依此类推。。通过对这个求和值上的坐标进行排序,我可以将TL的坐标取最小值,BR的坐标取最大值(因为这将有最大的x+y组合) 这很有效,除了我遇到这组坐标:

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

这些是黑色正方形的坐标,如下图所示。(页面每侧下方4个)

以下是坐标(x,y)(原点0,0位于左上方):

通过沿x轴对这些列进行排序,我可以选择顶部的4列和底部的4列,这两列分别对应于页面的每一侧

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

这很有效,除了我遇到这组坐标:

     [(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位置9871156,而不是2264180

    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

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

TL、TR、BL、BR的基本特征是它们距离每个角最近。如果取任意一组xy点,则只需找到到每个角的最短距离

下面的代码就是使用蛮力(将所有点与所有角进行比较)实现的。它可以复制粘贴到解释器。因为我不知道你给定的图像的极值,所以我不得不根据可用的点来获取它们。通过提供图像本身的角点,可以跳过此操作



输出:

********
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)

您是否始终知道在图像中搜索的正方形的分辨率/大小?如果是这样,模板匹配可能会容易得多。另外,其中一个图像根本没有正方形。你期望那会有什么结果?剪下正方形的那个怎么样(整个正方形不在图像中)?最后,也是最重要的一点,我真的看不到对“问题”本身的描述。你得到了一些你不喜欢的结果,但我不确定你到底想要什么。您能给出每个示例图像的预期输出(简单格式)吗?pdf中的大小为5mm正方形,但这些是打印和扫描的,因此图像中正方形的实际大小存在变化。共有2组3幅图像,1幅。输入,2。检测到正方形,和3。基于正方形的变换图像。第一个输出是非常扭曲的,因为它已经检测到图像中间的TR方块-我的问题是如何计算“正确”的TR正方形位置,这样我可以安全地转换图像?生成的第二组图像是正确的输出。实际输出是最后一幅图像。我有一些建议,可能会让您更有可能获得帮助。1) 清楚地列出你想做的事情。2) 清楚地确定哪些事情没有按你预期的方式进行,哪些事情是你确实期望的。3) 最重要的是,在这种情况下,隔离出问题的最小版本。可能这看起来很容易,因为您已经完成了这项工作,但这段代码对于stackoverflow来说是巨大的,并且程序输出也是巨大的。任何想帮忙的人或多或少都得摸索整个过程,看看如何改进。如果可能的话,进一步隔离问题。我不是想扯开你的问题-我想帮忙,但我没有时间研究整个问题,而且我仍然不清楚哪些部分在工作,哪些部分没有工作,以及预期的结果是什么。如果您有机会,请按原样编辑问题(而不是发布新问题),我将再次尝试查看。或者可能有比我更好的人会同时解决这个问题。很显然,这是我第一次向SO发帖,我显然太啰嗦了。我刚刚重新写了这个问题,希望现在能更简洁。谢谢。我试过了,效果很好。我不得不在main()中使用cv2.circle(frame,(int(round(v[0]))、int(round(v[1]))、12,(0255,0),-1)来绘制位置,因为它抱怨需要整数而不是浮点。
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
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)