OpenCV使用warpAffine实现图像旋转(防止切边)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/YunLaowang/article/details/86539910
原理

使用warpAffine()进行图像旋转,是基于仿射变换的原理,通常2 × \times 3矩阵进行仿射变换:
对于二维矩阵:
X = [ x y ] X = \begin{bmatrix} x \\ y \\ \end{bmatrix}
进行如下变换:
T = A [ x y ] + B T =A\cdot\begin{bmatrix} x \\ y \\ \end{bmatrix} +B
等价于:
T = M [ x y 1 ] T = M\cdot\begin{bmatrix} x \\ y \\ 1 \end{bmatrix}
其中:

在已知 X X T T 的情况下,还需要使用如下函数获取变换矩阵 M M

//scale为缩放因子,angle为旋转角度(正:逆时针),(centerx,centery)为旋转中心
	getRotationMatrix2D(Point2f center, double angle, double scale)

矩阵 M M 定义:

防止切边
  • 为防止原图在旋转之后被切边,需要对getRotationMatrix2D得到的仿射变换矩阵 M M 进行一定的修改,具体是通过修改 M M 矩阵中的平移部分: b 00 b_{00} b 01 b_{01} 完成;
  • 思路:先计算out_img的图像尺寸(rotated_width和rotated_height),然后将旋转之后的图像中心由center平移至out_img中心。
  • 方法:见如下代码
// 防止切边,对平移矩阵B进行修改
rotate_matrix.at<double>(0, 2) += (rotated_width - src.cols) / 2;     
rotate_matrix.at<double>(1, 2) += (rotated_height - src.rows) / 2;  
完整代码
#include <iostream>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <vector>

using namespace std;
using namespace cv;

int main(int argc, char** argv)
{
	Mat src = imread("pic.jpg");
	if (src.empty())
	{
		cout << "The image is empty, please check it!" << endl;
		return 0;
	}
	Mat out_img;

	// 旋转角度
	double angle = 45.0;

	// 计算旋转后输出图形的尺寸
	int rotated_width = ceil(src.rows * fabs(sin(angle * CV_PI / 180)) + src.cols * fabs(cos(angle * CV_PI / 180)));
	int rotated_height = ceil(src.cols * fabs(sin(angle * CV_PI / 180)) + src.rows * fabs(cos(angle * CV_PI / 180)));
	
	// 计算仿射变换矩阵
	Point2f center(src.cols / 2, src.rows / 2);
	Mat rotate_matrix = getRotationMatrix2D(center, 45, 1.0);

	// 防止切边,对平移矩阵B进行修改
	rotate_matrix.at<double>(0, 2) += (rotated_width - src.cols) / 2; 
	rotate_matrix.at<double>(1, 2) += (rotated_height - src.rows) / 2; 

	// 应用仿射变换
	warpAffine(src, out_img, rotate_matrix, Size(rotated_width, rotated_height), INTER_LINEAR, 0, Scalar(255, 255, 255));
	imshow("case1r", out_img);

	waitKey();
	return 0;
}

结果:

参考链接:仿射变换

猜你喜欢

转载自blog.csdn.net/YunLaowang/article/details/86539910