一次在 opencv 中结合旋转和平移

Combine rotation and translation in opencv, in one pass

我有一段旋转和平移图片的代码:

Point2f pt(0, in.rows);
double angle = atan(trans.c / trans.b) * 180 / M_PI;
Mat r = getRotationMatrix2D(pt, -angle, 1.0);
warpAffine(in, out, r, in.size(), interpolation); /* rotation */

Mat t = (Mat_<double>(2, 3) << 1, 0, trans.a, 0, 1, -trans.d);
warpAffine(out, out, t, in.size(), interpolation); /* translation */

问题是我分两次执行此操作。因此,如果我有一个 90 度的角度,第一个 "out" 变量将为空,因为所有数据都超出范围。有没有办法一次性完成?为了避免丢失我的数据和黑色图像。

我认为最好的办法是将 r 和 t 组合在一个矩阵中,但我有点迷茫。

此致,

这里有一个例子,说明如何通过简单的乘法组合 2 个单应性,以及如何从 3x3 单应性中提取仿射变换。

int main(int argc, char* argv[])
{
    cv::Mat input = cv::imread("C:/Whosebug/Input/Lenna.png");

    // create to 3x3 identity homography matrices
    cv::Mat homography1 = cv::Mat::eye(3, 3, CV_64FC1);
    cv::Mat homography2 = cv::Mat::eye(3, 3, CV_64FC1);

    double alpha1 = -13; // degrees
    double t1_x = -86; // pixel
    double t1_y = -86; // pixel

    double alpha2 = 21; // degrees
    double t2_x = 86; // pixel
    double t2_y = 86; // pixel

    // hope there is no error in the signs:
    // combine homography1
    homography1.at<double>(0, 0) = cos(CV_PI*alpha1 / 180);
    homography1.at<double>(0, 1) = -sin(CV_PI*alpha1 / 180);
    homography1.at<double>(1, 0) = sin(CV_PI*alpha1 / 180);
    homography1.at<double>(1, 1) = cos(CV_PI*alpha1 / 180);
    homography1.at<double>(0, 2) = t1_x;
    homography1.at<double>(1, 2) = t1_y;

    // compose homography2
    homography2.at<double>(0, 0) = cos(CV_PI*alpha2 / 180);
    homography2.at<double>(0, 1) = -sin(CV_PI*alpha2 / 180);
    homography2.at<double>(1, 0) = sin(CV_PI*alpha2 / 180);
    homography2.at<double>(1, 1) = cos(CV_PI*alpha2 / 180);
    homography2.at<double>(0, 2) = t2_x;
    homography2.at<double>(1, 2) = t2_y;

    cv::Mat affine1 = homography1(cv::Rect(0, 0, 3, 2));
    cv::Mat affine2 = homography2(cv::Rect(0, 0, 3, 2));

    cv::Mat dst1;
    cv::Mat dst2;

    cv::warpAffine(input, dst1, affine1, input.size());
    cv::warpAffine(input, dst2, affine2, input.size());


    cv::Mat combined_homog = homography1*homography2;
    cv::Mat combined_affine = combined_homog(cv::Rect(0, 0, 3, 2));

    cv::Mat dst_combined;

    cv::warpAffine(input, dst_combined, combined_affine, input.size());

    cv::imshow("input", input);
    cv::imshow("dst1", dst1);
    cv::imshow("dst2", dst2);

    cv::imshow("combined", dst_combined);

    cv::waitKey(0);
    return 0;
}

在此示例中,图像首先旋转和平移到左侧,然后再向右移动。如果两个变换依次执行,则会丢失重要的图像区域。相反,如果将它们通过单应性乘法组合起来,就好像在一步中完成了完整的操作,而不会在中间步骤中丢失图像部分。

输入:

如果图像首先用 H1 变换,然后用 H2 变换:

如果直接用H1*H2的组合变换图像:

这种单应性组合的一个典型应用是先将图像中心平移到原点,然后旋转,再平移回原点。这具有图像围绕其重心旋转的效果。