【问题标题】:OpenCV: get perspective matrix from translation & rotationOpenCV:从平移和旋转中获取透视矩阵
【发布时间】:2014-06-10 03:36:21
【问题描述】:

我正在尝试验证我的相机校准,因此我想更正校准图像。我预计这将涉及使用对 warpPerspective 的调用,但我没有看到一个明显的函数,它采用相机矩阵、旋转和平移向量来生成此调用的透视矩阵。

基本上我想做here 描述的过程(尤其是最后的图像),但从已知的相机模型和姿势开始。

是否有一个简单的函数调用来获取相机的内在和外在参数并计算用于warpPerspective 的透视矩阵?

在图片上调用undistort 后,我将调用warpPerspective

原则上,在指定约束Z=0 之后,我可以通过求解在opencv camera calibration documentation 顶部定义的方程组来得出解,但我认为必须有一个固定例程允许我进行正射校正我的测试图像。

在我的搜索中,我发现很难浏览所有的立体校准结果——我只有一台相机,但想要在我只查看平面测试图案的约束下校正图像。

【问题讨论】:

  • 那么,纠正是指去除旋转效果吗?这意味着,您只有一个视图,而不是两个相对于彼此的视图,您想要纠正(对齐极线)。
  • @DavidNilosek 是的,我有一个校准圆阵列的倾斜图像,我想恢复“自上而下”的视图。
  • 我正在努力思考,但不幸的是我的时间不多了。尝试使用旋转矩阵的逆矩阵作为 warpPerspective 的透视矩阵,如果可行,我可以写一些东西来更好地解释它。
  • 你想把perspective相机看到的图像转换成orthographic相机看到的图像,我觉得这不行使用逆旋转矩阵完成。一种直接的方法是使用 cv::getPerspectiveTransform 和 4 个适当的点。但是,可能可以直接从相机校准中得出转换,我会研究一下。

标签: opencv camera-calibration


【解决方案1】:

实际上没有必要涉及正交相机。以下是获得适当透视变换的方法。

如果您使用cv::calibrateCamera 校准相机,您将获得相机矩阵K 一个相机的镜头畸变系数矢量D,并且对于您使用的每张图像,一个旋转矢量rvec(其中您可以使用cv::rodriguesdoc) 和平移向量T 转换为3x3 矩阵R。考虑这些图像之一以及相关联的RT。使用畸变系数调用cv::undistort后,图像就像是由投影矩阵K * [ R | T ]的相机获取的一样。

基本上(正如@DavidNilosek 的直觉),您想要取消旋转并获得图像,就好像它是由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 是所考虑图像的校正透视变换。

【讨论】:

  • 为了使图像居中,我必须执行以下操作:让u0=-K*C/Cz(上面Ht的翻译部分);将其移动输入图像大小的一半:u[0] = u0[0] - image_size[0]u[1] = u0[1]-image_size[1]u[2]=u0[2],然后在 Ht 的构造中使用这个移动的u 向量代替-K*C/Cz。这与我的世界坐标系的原点位于校准网格的中心这一事实有关
  • 代码中有typeos-sn-ps我之前的评论:我移动了图片大小的1/2。
  • 嗨,奥尔德。你能看看我的类似问题stackoverflow.com/questions/46679422/…。我还尝试将 warpPerspective 中使用的 matPerspective 更改为您上面提到的 H。结果是空的。谢谢。
  • @Dave:为了获得正确的重新投影,我需要反转 'u[2]'。
  • @AlduurDisciple 你能解释一下最终 Ht 方程中 Cz 的含义吗?
【解决方案2】:

这是我所说的“求解方程组”(在 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..

【讨论】:

  • 我怀疑这是达到与@AldurDisciple 的答案相同效果的一种不优雅的方式
猜你喜欢
  • 2012-09-09
  • 2011-10-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-05-05
  • 2013-04-29
  • 2016-06-26
  • 1970-01-01
相关资源
最近更新 更多