将四边形图像提取到矩形 [英] extracting a quadrilateral image to a rectangle

查看:133
本文介绍了将四边形图像提取到矩形的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



BOUNTY UPDATE



关注 Denis's 链接,这是如何使用

  / 

/目的地rect是我们的'in'quad
int dw = 300,dh = 250;
double [4] [4] = {{0,0},{dw,0},{dw,dh},{0,dh}};
//源图像中的四元组是我们的'out'
double out [4] [5] = {{171,72},{331,93},{333,188},{177,210} };
double homo [3] [6];
const int ret = mapQuadToQuad(in,out,homo);
// homo可用于计算源中任何目标点
//的x,y,例如
for(int i = 0; i <4; i ++){
double p1 [3] = {out [i] [0],out [i] [7],1};
double p2 [3];
transformMatrix(p1,p2,homo);
p2 [0] / = p2 [2]; // x
p2 [1] / = p2 [2]; // y
printf(\t%2.2f\t%2.2f\\\
,p2 [0],p2 [1]);
}

这提供了一个转换,用于将目标中的点转换为源 - 您可以当然也可以用另一种方式来做,但是能够为混合做到这一点是很整洁的:

  for(int y = 0; y  for(int x = 0; x  //计算源
//目标像素的四个角,并混合

对于混音,我使用与随机点;即使在来源和目的地区域存在较大差异的情况下,它也能很好地发挥作用。




背景问题



在顶部的图像中,厢式货车侧面的标志并非正面对着相机。我想计算一下,尽可能使用我有的像素,看起来像是在面对什么。



我知道图像中四边形的角坐标,和目标矩形的大小。



我想象这是通过x轴和y轴的某种循环,同时在两个维度上同时执行Bresenham的行像源图像和目标图像中的像素重叠的混合类型 - 某种子像素混合类型?

有什么方法,以及如何混合像素?



有没有一个标准的方法呢?

解决方案

quad to quadtransform ,例如
threeblindmiceandamonkey

在2d齐次坐标上进行3x3变换可以将任何4点(四元)
转换为任何其他四元组;
相反,任何fromquad和toquad,比如你的卡车的角落和一个目标矩形,
给出一个3×3的变换。



Qt有 quadToQuad
,并且可以用它转换pixmaps,但我猜您没有Qt?

添加了10Jun:
labs.trolltech.com/page/Graphics/Examples

有一个很好的演示,当你移动角落时,它会四角形地显示一个像素图:



< h2>

新增11Jun:@ Will,这里是翻译。 (你知道一点?
...是多行注释。)

perstrans()是关键;希望这是有道理的,如果不问的话。


由此,您可以逐一映射像素,mapQuadToQuad(目标矩形,原始四边形),
但不包含像素插值它看起来很糟糕; OpenCV完成了这一切。

 #!/ usr / bin / env python 
square< - > ; quad maps
from http://threeblindmiceandamonkey.com/?p=16 matrix.h

$ b $ from __future__ import division
import numpy as np

__date__ =2010-06-11 jun denis

def det2(a,b,c,d):
返回a * d - b * c

def mapSquareToQuad(quad):#[4] [2]
SQ = np.zeros((3,3))
px = quad [0,0] - quad [1,0] + quad [2,0] - quad [3,0]
py = quad [0,1] - quad [1,1] + quad [2,1] - quad [ 3,1]
如果abs(px)< 1e-10和abs(py) 1e-10:
SQ [0,0] = quad [1,0] - quad [0,0]
SQ [1,0] = quad [2,0] - quad [1, 0]
SQ [2,0] = quad [0,0]
SQ [0,1] = quad [1,1] - quad [0,1]
SQ [1] ,1] = quad [2,1] - quad [1,1]
SQ [2,1] = quad [0,1]
SQ [0,2] = 0.
SQ [1,2] = 0.
SQ [2,2] = 1.
返回SQ
else:
dx1 = quad [1,0] - quad [ 2,0]
dx2 = quad [3,0] - quad [2,0]
dy1 = quad [1,1] - quad [2,1]
dy2 = quad [ 3,1] - quad [2,1]
det = det2(dx1,dx2,dy1,dy2)
if det == 0 .:
return None
SQ [ 0] = det2(px,dx2,py,dy2)/ det
SQ [1,2] = det2(dx1,px,dy1,py)/ det
SQ [2,2] = 1.
SQ [0,0] = quad [1,0] - quad [0,0] + SQ [0,2] * quad [1,0]
SQ [1,0 ] = quad [3,0] - quad [0,0] + SQ [1,2] * quad [3,0]
SQ [2,0] = quad [0,0]
SQ [0,1] = quad [1,1] - quad [0,1] + SQ [0,2] * quad [1,1]
SQ [1,1] = quad [3,1] - quad [0,1] + SQ [1,2] * quad [3,1]
SQ [2,1] = quad [0,1]
返回SQ

#................................... ............................................
def mapQuadToSquare (quad):
return np.linalg.inv(mapSquareToQuad(quad))

def mapQuadToQuad(a,b):
return np.dot(mapQuadToSquare(a), mapSquareToQuad(b))

def perstrans(X,t):
透视变换X Nx2,t 3x3:
[x0 y0 1] t = [a0 b0 w0] - > [a0 / w0 b0 / w0]
[x1 y1 1] t = [a1 b1 w1] - > [a1 / w1 b1 / w1]
...

x1 = np.vstack((XT,np.ones(len(X))))
y = np.dot(tT,x1)
return(y [: - 1] / y [-1]).T

#........... .................................................. ..................
if __name__ ==__main__:
np.set_printoptions(2,threshold = 100,suppress = True)#。 2f

sq = np.array([[0,0],[1,0],[1,1],[0,1]])
quad = np.array ([[171,72],[331,93],[333,188],[177,210]])
printquad:,quad
printsquare to quad:, perstrans(sq,mapSquareToQuad(quad))
printquad to square:,perstrans(quad,mapQuadToSquare(quad))

dw,dh = 300,250
rect = np.array([[0,0],[dw,0],[dw,dh],[0,dh]])
quadquad = mapQuadToQuad(quad,rect)
printquad四元变换:,quadquad
printquad to rect:,perstrans(quad,quadquad)

quad:[[171 72]
[331 93 ]
[333 188]
[177 210]]
square to quad:[[171. 72.]
[331. 93.]
[333. 188.]
[177. 210.]]
四方到四方:[[-0。 0]
[1. 0]
[1.1]
[0.1]]
quad到四元变换:[[1.29 -0.23 -0 。 ]
[-0.06 1.79 -0。 ]
[-217.24 -88.54 1.34]] $ b $四个矩形到矩形:[[0. 0.]
[300. 0]
[300. 250.]
[0. 250.]]


BOUNTY UPDATE

Following Denis's link, this is how to use the threeblindmiceandamonkey code:

// the destination rect is our 'in' quad
int dw = 300, dh = 250;
double in[4][4] = {{0,0},{dw,0},{dw,dh},{0,dh}};
    // the quad in the source image is our 'out'
double out[4][5] = {{171,72},{331,93},{333,188},{177,210}};
double homo[3][6];
const int ret = mapQuadToQuad(in,out,homo);
    // homo can be used for calculating the x,y of any destination point
// in the source, e.g.
for(int i=0; i<4; i++) {
    double p1[3] = {out[i][0],out[i][7],1};
    double p2[3];
    transformMatrix(p1,p2,homo);
    p2[0] /= p2[2]; // x
    p2[1] /= p2[2]; // y
    printf("\t%2.2f\t%2.2f\n",p2[0],p2[1]);
}

This provides a transform for converting points in destination to the source - you can of course do it the other way around, but it's tidy to be able to do this for the mixing:

for(int y=0; y<dh; y++) {
    for(int x=0; x<dw; x++) {
        // calc the four corners in source for this
        // destination pixel, and mix

For the mixing, I'm using super-sampling with random points; it works very well, even when there is a big disparity in the source and destination area


BACKGROUND QUESTION

In the image at the top, the sign on the side of the van is not face-on to the camera. I want to calculate, as best I can with the pixels I have, what it'd look like face on.

I know the corner coordinates of the quad in the image, and the size of the destination rectangle.

I imagine that this is some kind of loop through the x and y axis doing a Bresenham's line on both dimensions at once with some kind of mixing as pixels in the source and destination images overlap - some sub-pixel mixing of some sort?

What approaches are there, and how do you mix the pixels?

Is there a standard approach for this?

解决方案

Look up "quad to quad" transform, e.g. threeblindmiceandamonkey.
A 3x3 transform on 2d homogeneous coordinates can transform any 4 points (a quad) to any other quad; conversely, any fromquad and toquad, such as the corners of your truck and a target rectangle, give a 3 x 3 transform.

Qt has quadToQuad and can transform pixmaps with it, but I guess you don't have Qt ?
Added 10Jun: from labs.trolltech.com/page/Graphics/Examples there's a nice demo which quad-to-quads a pixmap as you move the corners:

Added 11Jun: @Will, here's translate.h in Python (which you know a bit ? """ ...""" are multiline comments.)
perstrans() is the key; hope that makes sense, if not ask.

Bytheway, you could map the pixels one by one, mapQuadToQuad( target rect, orig quad ), but without pixel interpolation it'll look terrible; OpenCV does it all.

#!/usr/bin/env python
""" square <-> quad maps
    from http://threeblindmiceandamonkey.com/?p=16 matrix.h
"""

from __future__ import division
import numpy as np

__date__ = "2010-06-11 jun denis"

def det2(a, b, c, d):
    return a*d - b*c

def mapSquareToQuad( quad ):  # [4][2]
    SQ = np.zeros((3,3))
    px = quad[0,0] - quad[1,0] + quad[2,0] - quad[3,0]
    py = quad[0,1] - quad[1,1] + quad[2,1] - quad[3,1]
    if abs(px) < 1e-10 and abs(py) < 1e-10:
        SQ[0,0] = quad[1,0] - quad[0,0]
        SQ[1,0] = quad[2,0] - quad[1,0]
        SQ[2,0] = quad[0,0]
        SQ[0,1] = quad[1,1] - quad[0,1]
        SQ[1,1] = quad[2,1] - quad[1,1]
        SQ[2,1] = quad[0,1]
        SQ[0,2] = 0.
        SQ[1,2] = 0.
        SQ[2,2] = 1.
        return SQ
    else:
        dx1 = quad[1,0] - quad[2,0]
        dx2 = quad[3,0] - quad[2,0]
        dy1 = quad[1,1] - quad[2,1]
        dy2 = quad[3,1] - quad[2,1]
        det = det2(dx1,dx2, dy1,dy2)
        if det == 0.:
            return None
        SQ[0,2] = det2(px,dx2, py,dy2) / det
        SQ[1,2] = det2(dx1,px, dy1,py) / det
        SQ[2,2] = 1.
        SQ[0,0] = quad[1,0] - quad[0,0] + SQ[0,2]*quad[1,0]
        SQ[1,0] = quad[3,0] - quad[0,0] + SQ[1,2]*quad[3,0]
        SQ[2,0] = quad[0,0]
        SQ[0,1] = quad[1,1] - quad[0,1] + SQ[0,2]*quad[1,1]
        SQ[1,1] = quad[3,1] - quad[0,1] + SQ[1,2]*quad[3,1]
        SQ[2,1] = quad[0,1]
        return SQ

#...............................................................................
def mapQuadToSquare( quad ):
    return np.linalg.inv( mapSquareToQuad( quad ))

def mapQuadToQuad( a, b ):
    return np.dot( mapQuadToSquare(a), mapSquareToQuad(b) )

def perstrans( X, t ):
    """ perspective transform X Nx2, t 3x3:
        [x0 y0 1] t = [a0 b0 w0] -> [a0/w0 b0/w0]
        [x1 y1 1] t = [a1 b1 w1] -> [a1/w1 b1/w1]
        ...
    """
    x1 = np.vstack(( X.T, np.ones(len(X)) ))
    y = np.dot( t.T, x1 )
    return (y[:-1] / y[-1]) .T

#...............................................................................
if __name__ == "__main__":
    np.set_printoptions( 2, threshold=100, suppress=True )  # .2f

    sq = np.array([[0,0], [1,0], [1,1], [0,1]])
    quad = np.array([[171, 72], [331, 93], [333, 188], [177, 210]])
    print "quad:", quad
    print "square to quad:", perstrans( sq, mapSquareToQuad(quad) )
    print "quad to square:", perstrans( quad, mapQuadToSquare(quad) )

    dw, dh = 300, 250
    rect = np.array([[0, 0], [dw, 0], [dw, dh], [0, dh]])
    quadquad = mapQuadToQuad( quad, rect )
    print "quad to quad transform:", quadquad
    print "quad to rect:", perstrans( quad, quadquad )
"""
quad: [[171  72]
 [331  93]
 [333 188]
 [177 210]]
square to quad: [[ 171.   72.]
 [ 331.   93.]
 [ 333.  188.]
 [ 177.  210.]]
quad to square: [[-0.  0.]
 [ 1.  0.]
 [ 1.  1.]
 [ 0.  1.]]
quad to quad transform: [[   1.29   -0.23   -0.  ]
 [  -0.06    1.79   -0.  ]
 [-217.24  -88.54    1.34]]
quad to rect: [[   0.    0.]
 [ 300.    0.]
 [ 300.  250.]
 [   0.  250.]]
"""

这篇关于将四边形图像提取到矩形的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆