【问题标题】:Combine rotation and translation in opencv, in one pass一次性在opencv中结合旋转和平移
【发布时间】:2016-04-28 20:29:51
【问题描述】:

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

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 组合在一个矩阵中,但我有点迷茫。

最好的问候,

【问题讨论】:

  • 你可以简单地多玩单应性。仿射变换必须扩展到 3x3 才能通过添加第三行来做到这一点: 0 0 1 然后你可以简单地乘以 Hcombined = H1 * H2;但请注意以正确的顺序相乘。
  • 好的,谢谢。我如何简单地使用 opencv 将第三行添加到 r ?然后我不确定了解什么是H1,什么是H2。 H1 是添加了第 3 行的旋转矩阵? H2是平移矩阵?
  • 我会发布一个代码示例

标签: opencv rotation translation


【解决方案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;
}

在此示例中,图像首先旋转并平移到左侧,然后再平移到右侧。如果两个变换相继执行,重要的图像区域将会丢失。取而代之的是,如果它们通过单边乘法组合起来,就像在一个步骤中完成了完整的操作,而不会在中间步骤中丢失图像部分。

输入:

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

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

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

【讨论】:

  • 哦,谢谢,这对我很有帮助,我必须尽快对其进行测试。我还有两个问题。阿尔法的单位是什么? -13 表示 90 度,对不起,它一定是 ovious。我不知道你是否看过,但我的翻译数据是针对(0,in.rows)的旋转中心,即左下角。它应该改变我认为的矩阵。
  • 或者我可以先从 (0, in.rows) 转移
  • 对不起,单位是度。它是 -13 度,而不是 90 度。首先我尝试了 90 度,但我想稍微改变一下,并没有改变评论。对不起。
  • 没问题!!!谢谢你。如果我想添加比例。我在旋转矩阵中将比例乘以 cos 和 sin。我说的对吗?
  • 更好地为尺度创建另一个单应性并将单应性相乘!也许这与将比例因子仅乘以两个 cos 项相同,但我不确定。
猜你喜欢
  • 2012-04-12
  • 1970-01-01
  • 1970-01-01
  • 2011-10-14
  • 1970-01-01
  • 1970-01-01
  • 2011-10-24
  • 2012-11-29
  • 1970-01-01
相关资源
最近更新 更多