将四边形图像提取为矩形 [英] extracting a quadrilateral image to a rectangle
问题描述
赏金更新
按照丹尼斯的链接,这就是方法使用 threeblindmiceandamonkey 代码:
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(" %2.2f %2.2f
",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
背景问题
在顶部的图像中,货车侧面的标志没有正对着相机.我想用我拥有的像素尽我所能计算出它的脸是什么样子.
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.
我想象这是一种通过 x 和 y 轴的循环,同时在两个维度上执行 Bresenham 线,并在源图像和目标图像中的像素重叠时进行某种混合 - 某种子像素混合?
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?
对此有标准方法吗?
推荐答案
查找quad to quad"转换
,例如threeblindmiceandamonkey.
二维齐次坐标上的 3x3 变换可以变换任何 4 个点(四边形)到任何其他四边形;相反,任何 fromquad 和 toquad,例如卡车的角和目标矩形,进行 3 x 3 变换.
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 有 quadToQuad并且可以用它转换像素图,但我猜你没有 Qt 吗?
新增 10Jun:来自 labs.trolltech.com/page/Graphics/Examples有一个很好的演示,当你移动角落时,它可以将像素图从四边形变成四边形:
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:
添加了 11Jun:@Will,这是 Python 中的 translate.h(你知道一点吗?""" ...""" 是多行注释.)perstrans()
是关键;希望这是有道理的,如果不是问.
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.
顺便说一下,你可以将像素一一映射,mapQuadToQuad(target rect, orig quad),但如果没有像素插值,它看起来会很糟糕;OpenCV 做到了这一切.
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屋!