【问题标题】:Warping an image using roll, pitch, and yaw使用滚动、俯仰和偏航扭曲图像
【发布时间】:2013-10-19 20:45:18
【问题描述】:

我目前在 Python 中使用 OpenCV 来校正航拍图像中的图像失真。我有滚动、俯仰和偏航的数据。我知道我需要创建一个扭曲矩阵,并将该矩阵应用于我的原始坐标点以创建图像的输出点。我能够影响图像移动的方式,但我觉得有一个错误,因为唯一的值似乎适用于非常小的值。

这是我当前的代码:

warp_mat = np.array([[math.cos(theta)*math.cos(psy), math.cos(phi)*math.sin(psy)+math.sin(phi)*math.sin(theta)*math.cos(psy), math.sin(phi)*math.sin(psy)-math.cos(phi)*math.sin(theta)*math.cos(psy)],\
                    [-1*math.cos(theta)*math.sin(psy), math.cos(phi)*math.cos(psy)-math.sin(phi)*math.sin(theta)*math.sin(psy), math.sin(phi)*math.cos(psy)+math.cos(phi)*math.sin(theta)*math.sin(psy)],\
                    [math.sin(theta), -1*math.sin(phi)*math.cos(theta), math.cos(phi)*math.cos(theta)]], dtype='float32')


srcPts = np.array([[-2064, 1161, 1],\
                  [2064, 1161, 1],\
                  [2064, -1161, 1],\
                  [-2064, -1161, 1]], dtype='float32')

dstPts = np.empty(shape = (4,3), dtype='float32')


dstPts[0][0] = srcPts[0][0] * warp_mat[0][0] + srcPts[0][1] * warp_mat[1][0] + srcPts[0][2] * warp_mat[2][0];
dstPts[0][1] = srcPts[0][0] * warp_mat[0][1] + srcPts[0][1] * warp_mat[1][1] + srcPts[0][2] * warp_mat[2][1];
dstPts[0][2] = srcPts[0][0] * warp_mat[0][2] + srcPts[0][1] * warp_mat[1][2] + srcPts[0][2] * warp_mat[2][2];

dstPts[1][0] = srcPts[1][0] * warp_mat[0][0] + srcPts[1][1] * warp_mat[1][0] + srcPts[1][2] * warp_mat[2][0];
dstPts[1][1] = srcPts[1][0] * warp_mat[0][1] + srcPts[1][1] * warp_mat[1][1] +     srcPts[1][2] * warp_mat[2][1];
dstPts[1][2] = srcPts[1][0] * warp_mat[0][2] + srcPts[1][1] * warp_mat[1][2] + srcPts[1][2] * warp_mat[2][2];

dstPts[2][0] = srcPts[2][0] * warp_mat[0][0] + srcPts[2][1] * warp_mat[1][0] + srcPts[2][2] * warp_mat[2][0];
dstPts[2][1] = srcPts[2][0] * warp_mat[0][1] + srcPts[2][1] * warp_mat[1][1] + srcPts[2][2] * warp_mat[2][1];
dstPts[2][2] = srcPts[2][0] * warp_mat[0][2] + srcPts[2][1] * warp_mat[1][2] + srcPts[2][2] * warp_mat[2][2];

dstPts[3][0] = srcPts[3][0] * warp_mat[0][0] + srcPts[3][1] * warp_mat[1][0] + srcPts[3][2] * warp_mat[2][0];
dstPts[3][1] = srcPts[3][0] * warp_mat[0][1] + srcPts[3][1] * warp_mat[1][1] + srcPts[3][2] * warp_mat[2][1];
dstPts[3][2] = srcPts[3][0] * warp_mat[0][2] + srcPts[3][1] * warp_mat[1][2] + srcPts[3][2] * warp_mat[2][2];


dstPts[0][0] = dstPts[0][0] / dstPts[0][2];
dstPts[0][1] = dstPts[0][1] / dstPts[0][2];
dstPts[0][2] = dstPts[0][2] / dstPts[0][2];

dstPts[1][0] = dstPts[1][0] / dstPts[1][2];
dstPts[1][1] = dstPts[1][1] / dstPts[1][2];
dstPts[1][2] = dstPts[1][2] / dstPts[1][2];

dstPts[2][0] = dstPts[2][0] / dstPts[2][2];
dstPts[2][1] = dstPts[2][1] / dstPts[2][2];
dstPts[2][2] = dstPts[2][2] / dstPts[2][2];

dstPts[3][0] = dstPts[3][0] / dstPts[3][2];
dstPts[3][1] = dstPts[3][1] / dstPts[3][2];
dstPts[3][2] = dstPts[3][2] / dstPts[3][2];



srcPts2 = np.array([[srcPts[0][0],srcPts[0][1]],\
                   [srcPts[1][0],srcPts[1][1]],\
                   [srcPts[2][0],srcPts[2][1]],\
                   [srcPts[3][0],srcPts[3][1]]], dtype='float32')

dstPts2 = np.array([[dstPts[0][0],dstPts[0][1]],\
                   [dstPts[1][0],dstPts[1][1]],\
                   [dstPts[2][0],dstPts[2][1]],\
                   [dstPts[3][0],dstPts[3][1]]], dtype='float32')


transMatrix = cv.getPerspectiveTransform(srcPts2, dstPts2)


dst = cv.warpPerspective(imgFile,transMatrix,(4128,2322) ,borderMode = cv.BORDER_CONSTANT,borderValue = 0)

【问题讨论】:

    标签: python image opencv matrix pitch


    【解决方案1】:

    在代码的开头,您通过投影四个点来计算扭曲矩阵,然后使用 getPerspectiveTransform() 找出变换矩阵。这应该可行,但它比必要的复杂。如果知道roll、pitch和yaw角度,就可以直接计算变换矩阵。看看http://image2measure.net/files/calib3Dto2D.cpp 中的函数 BirdsEyeView()。它正是这样做的。
    我不得不换行
    Mat R = RX * RY * RZ;
    Mat R = RZ * RX * RY; 为了使它正确的转换。

    f 是以像素为单位的焦距。
    如果 rh 是图像的水平分辨率,oh 是相机的水平打开角度
    f = (rh/2)/tan(oh/ 2)
    如果您不想缩放图像,请为 Distance 选择相同的值,大于 f 的值可以放大图像,小于的值可以缩小图像。

    【讨论】:

      【解决方案2】:

      代码 BirdsEyeView() 对我有用,但我不知道为什么要交换 Roll 和 Pitch 角度。当我更改“alpha”时,图像会在音调上扭曲,当我更改“beta”时,图像会在滚动中扭曲。所以,我改变了我的旋转矩阵,如下所示。

      另外,RY 有一个信号错误。您可以通过以下方式查看 Ry:http://en.wikipedia.org/wiki/Rotation_matrix 我认为这就是为什么 Adrian 将乘法顺序从 R = RX * RY * RZ 更改为 R = RZ * RX * RY 的原因。

      我使用的旋转矩阵:

          Mat RX = (Mat_<double>(4, 4) <<
              1,          0,           0, 0,
              0, cos(beta), -sin(beta), 0,
              0, sin(beta),  cos(beta), 0,
              0,          0,           0, 1);
      
          Mat RY = (Mat_<double>(4, 4) <<
               cos(alpha), 0,  sin(alpha), 0,
                        0, 1,           0, 0,
              -sin(alpha), 0,  cos(alpha), 0,
                        0, 0,           0, 1);
      
          Mat RZ = (Mat_<double>(4, 4) <<
              cos(gamma), -sin(gamma), 0, 0,
              sin(gamma),  cos(gamma), 0, 0,
              0,          0,           1, 0,
              0,          0,           0, 1);
      

      问候

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-02-18
        • 1970-01-01
        • 1970-01-01
        • 2012-08-02
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多