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

时间:2016-04-28 08:21:03

标签: opencv rotation translation

我有一段用于旋转和翻译图像的代码:

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度,那么第一个&#34; out&#34;变量将为空,因为所有数据都超出范围。有没有办法一次性完成?为了避免丢失我的数据和黑色图像。

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

致以最诚挚的问候,

1 个答案:

答案 0 :(得分:1)

以下是如何通过简单乘法组合2个单应性以及如何从3x3单应性中提取仿射变换的示例。

int main(int argc, char* argv[])
{
    cv::Mat input = cv::imread("C:/StackOverflow/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;
}

在此示例中,首先旋转图像并将其平移到左侧,然后再向右移动。如果两个变换在彼此之后执行,则显着的图像区域将丢失。相反,如果它们通过同步乘法组合,则就像在一个步骤中完成整个操作而不会在中间步骤中丢失图像部分。

输入:

enter image description here

如果图像首先用H1转换,稍后转换为H2:

enter image description here

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

enter image description here

这种单应组合的一个典型应用是首先将图像中心转换为原点,然后旋转,然后转换回原始位置。这具有如同图像围绕其重心旋转的效果。