[英]OpenCV: get perspective matrix from translation & rotation
我正在尝试验证我的相机校准,所以我想纠正校准图像。 我预计这将涉及使用对warpPerspective
的调用,但我没有看到一个明显的函数,它采用相机矩阵以及旋转和平移向量来生成此调用的透视矩阵。
本质上,我想做这里描述的过程(尤其是最后的图像),但从已知的相机模型和姿势开始。
是否有一个直接的函数调用,它采用相机的内在和外在参数并计算用于warpPerspective
的透视矩阵?
我会打电话warpPerspective
在传唤后undistort
在图像上。
原则上,在指定约束Z=0
后,我可以通过求解在opencv 相机校准文档顶部定义的方程组来推导出解决方案,但我认为必须有一个固定的例程可以让我正射校正我的测试图片。
在我的搜索中,我发现很难通过所有立体校准结果——我只有一台相机,但想在我只查看平面测试图案的约束下校正图像。
实际上没有必要涉及正交相机。 以下是如何获得适当的透视变换。
如果您使用cv::calibrateCamera
校准相机,您将获得一个相机矩阵K
一个相机镜头失真系数D
的向量,并且对于您使用的每个图像,一个旋转向量rvec
(您可以将其转换为 3x3 矩阵R
使用cv::rodrigues
, doc ) 和翻译向量T
。 考虑这些图像之一以及相关的R
和T
。 使用失真系数调用cv::undistort
,图像将就像是由投影矩阵K * [ R | T ]
的相机获取的一样K * [ R | T ]
K * [ R | T ]
。
基本上(正如@DavidNilosek 直觉的那样),您想要取消旋转并获得图像,就好像它是通过K * [ I | -C ]
形式的投影矩阵获得的一样K * [ I | -C ]
K * [ I | -C ]
其中C=-R.inv()*T
是相机位置。 为此,您必须应用以下转换:
Hr = K * R.inv() * K.inv()
唯一的潜在问题是扭曲的图像可能会超出图像平面的可见部分。 因此,您可以使用额外的翻译来解决该问题,如下所示:
[ 1 0 | ]
Ht = [ 0 1 | -K*C/Cz ]
[ 0 0 | ]
其中 Cz 是 C 沿 Oz 轴的分量。
最后,根据上面的定义, H = Ht * Hr
是所考虑图像的校正透视变换。
这是我所说的“求解方程组”的草图(在 Python 中):
import cv2
import scipy # I use scipy by habit; numpy would be fine too
#rvec= the rotation vector
#tvec = the translation *emphasized text*matrix
#A = the camera intrinsic
def unit_vector(v):
return v/scipy.sqrt(scipy.sum(v*v))
(fx,fy)=(A[0,0], A[1,1])
Ainv=scipy.array( [ [1.0/fx, 0.0, -A[0,2]/fx],
[ 0.0, 1.0/fy, -A[1,2]/fy],
[ 0.0, 0.0, 1.0] ], dtype=scipy.float32 )
R=cv2.Rodrigues( rvec )
Rinv=scipy.transpose( R )
u=scipy.dot( Rinv, tvec ) # displacement between camera and world coordinate origin, in world coordinates
# corners of the image, for here hard coded
pixel_corners=[ scipy.array( c, dtype=scipy.float32 ) for c in [ (0+0.5,0+0.5,1), (0+0.5,640-0.5,1), (480-0.5,640-0.5,1), (480-0.5,0+0.5,1)] ]
scene_corners=[]
for c in pixel_corners:
lhat=scipy.dot( Rinv, scipy.dot( Ainv, c) ) #direction of the ray that the corner images, in world coordinates
s=u[2]/lhat[2]
# now we have the case that (s*lhat-u)[2]==0,
# i.e. s is how far along the line of sight that we need
# to move to get to the Z==0 plane.
g=s*lhat-u
scene_corners.append( (g[0], g[1]) )
# now we have: 4 pixel_corners (image coordinates), and 4 corresponding scene_coordinates
# can call cv2.getPerspectiveTransform on them and so on..
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.