一次在 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的组合变换图像:
这种单应性组合的一个典型应用是先将图像中心平移到原点,然后旋转,再平移回原点。这具有图像围绕其重心旋转的效果。
我有一段旋转和平移图片的代码:
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的组合变换图像:
这种单应性组合的一个典型应用是先将图像中心平移到原点,然后旋转,再平移回原点。这具有图像围绕其重心旋转的效果。