OpenCV旋转图像而没有裁剪澄清

时间:2017-02-07 16:38:17

标签: c++ opencv geometry

我想扩展这个话题,提到用户Lars Schillingmann提出的这个问题和接受的答案:

Rotate an image without cropping in OpenCV in C++

我已经对添加两个"手册"的数学/几何学表示怀疑。偏移到矩阵"腐烂"这将在接受的答案(下面报告的答案代码)的评论中用作warpAffine(...)函数的输入:

#include "opencv2/opencv.hpp"

int main()
{
cv::Mat src = cv::imread("im.png", CV_LOAD_IMAGE_UNCHANGED);
double angle = -45;

// get rotation matrix for rotating the image around its center
cv::Point2f center(src.cols/2.0, src.rows/2.0);
cv::Mat rot = cv::getRotationMatrix2D(center, angle, 1.0);
// determine bounding rectangle
cv::Rect bbox = cv::RotatedRect(center,src.size(), angle).boundingRect();
// adjust transformation matrix
rot.at<double>(0,2) += bbox.width/2.0 - center.x;
rot.at<double>(1,2) += bbox.height/2.0 - center.y;

cv::Mat dst;
cv::warpAffine(src, dst, rot, bbox.size());
cv::imwrite("rotated_im.png", dst);

return 0;
}

我对从cv :: getRotationMatrix2D(...)获得的rotationMatrix毫无疑问,这显然是正确的。

(开始参考其他人试图理解数学&#34;隐藏&#34;在此功能中,你可以跳过这个)

如果您分解opencv docs here中报告的结果矩阵的定义,您可以看到它是以下操作的结果:

1)通过Tx = -rotationCenter.x和Ty = -rotationCenter.y翻译原始图像(图像被翻译以获得给定的旋转中心到位置(0,0))(TransformationMatrix M1 - 仅翻译)

2)按照给定角度旋转已翻译的图像(并按给定因子缩放图像)(TransformationMatrix M2 - 仅旋转+缩放)

3)通过Tx = + rotationCenter.x和Ty = + rotationCenter.y将旋转后的图像平移,从而反转应用M1完成的平移。 (TransformationMatrix M3 - 仅翻译)

按给定的顺序乘以这3个矩阵(M1 * M2 * M3,你得到的是从getRotationMatrix2D得到的相同矩阵。

(其他人试图理解数学的最终参考资料&#34;隐藏&#34;在此函数内)

接受的答案然后找到rotateRect的boundingRect()以获得具有旋转的原始图像的正确尺寸的目标图像,然后在以下两行中手动添加两个偏移,这是我要求澄清的操作:

rot.at<double>(0,2) += bbox.width/2.0 - center.x;
rot.at<double>(1,2) += bbox.height/2.0 - center.y;

在向作者询问接受的答案后,我按照link(也在接受的答案中提到)来理解基础数学。该博客中给出的解释对我来说似乎没问题,但源代码(该博客文章中给出的Python示例,我需要C ++实现)似乎与接受的答案中的C ++代码有所不同。

首先计算目标图像尺寸并将目标图像中心的getRotationMatrix2d(...)作为旋转中心点,然后手动将两个偏移添加到生成的rot_mat中,但偏移量以不同的方式计算。

我将Python函数移植到C ++(下面列出的代码,我的函数也计算反转矩阵以供将来使用,忽略该部分)并在执行时获得一致的结果。我也测试了上面的代码,它似乎也给出了一个连贯的结果。

Mat rotate_about_center(Mat src, float angle, float scale, Mat& invertMat) {

    // math behind this transformation is explained here:
    // http://john.freml.in/opencv-rotation (with python code example)
    int w = src.cols;
    int h = src.rows;

    float rangle = angle * CV_PI/180.0;
    // now calculate new image width and height
    int nw = (abs(sin(rangle)*h) + abs(cos(rangle)*w))*scale;
    int nh = (abs(cos(rangle)*h) + abs(sin(rangle)*w))*scale;
    //  ask OpenCV for the rotation matrix
    Mat rot_mat = getRotationMatrix2D(Point(nw*0.5, nh*0.5), angle, scale);

    cout <<"rot_mat:\n"<< rot_mat <<endl;
    // calculate the move from the old center to the new center combined
    // with the rotation
    Mat m =  Mat(Size(3,1), CV_64FC1);
    m.at<double>(0,0)=(nw-w)*0.5;
    m.at<double>(0,1)=(nh-h)*0.5;
    m.at<double>(0,2)=0.0;
    transpose(m,m);
    cout <<"m:\n"<< m <<endl;

    Mat rot_move = rot_mat * m;
    // the move only affects the translation, so update the translation
    // part of the transform
    rot_mat.at<double>(0,2) += rot_move.at<double>(0,0);
    rot_mat.at<double>(1,2) += rot_move.at<double>(0,1);
    Mat dst;
    warpAffine(src, dst , rot_mat, Size(nw, nh));
    invertAffineTransform(rot_mat, invertMat);
    return dst;
}

如果这两个代码段相同,有人可以解释一下吗?如果它们是等价的,你能否解释为什么是等价的?

0 个答案:

没有答案