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

时间:2013-12-02 16:05:45

标签: python opencv registration coords

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

这些是位于下方图像上的黑色方块的坐标。 (页面两侧各4个)

这是coords(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

1 个答案:

答案 0 :(得分:0)

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

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)