【OpenCV】OpenCV通过仿射变换实现图像旋转(自适应图像尺寸大小)

先看结果

       

 

仿射变换原理

一般通过一个2*3的矩阵对图像中每个位置(x,y)进行矩阵运算来得到一个新的位置(x',y'),具体公式如下:

                                           

每个对应点有两个对应的方程,因此只要找到三个位置对应的点就可以知道变换矩阵,在OpenCV中通过getAffineTransform函数可得。也可以直接给出中心点与角度,得到一个旋转变换矩阵,对应OpenCV中getRotationMatrix2D接口可得。一般进行旋转变换后有一个偏移,需要通过计算点的位置变换得到一个平移矩阵来对图像进行校正,在旋转矩阵的最后一列增加平移最后进行仿射变换。

需要了解旋转变换后窗口的尺寸变换:

                                        

代码

#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include <iostream>


using namespace std;
using namespace cv;

int main()
{
	Mat src = imread("image0.jpg", IMREAD_COLOR);
	cvtColor(src, src, COLOR_BGR2GRAY);
											
	if (src.empty() /*|| src == NULL*/)
	{
		cout << "读入的图像为空error" << endl;
		return -1;
	}
	imshow("原图灰度化", src);
//按角度旋转矩阵
	Mat res4(src.size(), src.depth(), Scalar(0));
	Point2f center;
	center.x = float(src.cols / 2.0 - 0.5);
	center.y = float(src.rows / 2.0 - 0.5);

	//计算二维旋转的仿射变换矩阵(也可以通过三点法计算仿射变换矩阵)
	//Mat getRotationMatrix2D( Point2f center, double angle, double scale );
	double degree = 45.;//角度为+表示逆时针
	//CV_EXPORTS_W void warpAffine( InputArray src, OutputArray dst,
                    //InputArray M, Size dsize,
					//int flags = INTER_LINEAR,
					//int borderMode = BORDER_CONSTANT,const Scalar& borderValue = Scalar());

	Mat M = getRotationMatrix2D(center, degree, 1);
	cout << M.size() << endl;
	//变换图像,并用黑色填充其余值  
	warpAffine(src, res4, M, src.size());
	imshow("直接旋转图像", res4);
														
	
	Point2f center2;
	center2.x = float(src.cols / 2.0 - 0.5);
	center2.y = float(src.rows / 2.0 - 0.5);
	double degree2 = 45.;

	double angle = degree2  * CV_PI / 180.; // 弧度    
	double a = sin(angle), b = cos(angle);
	int width = src.cols;
	int height = src.rows;
	int width_rotate = int(height * fabs(a) + width * fabs(b));
	int height_rotate = int(width * fabs(a) + height * fabs(b));

	Mat M1 = getRotationMatrix2D(center2, degree, 1.0);

	Point2f srcPoints1[3];
	Point2f dstPoints1[3];

	srcPoints1[0] = Point2i(0, 0);
	srcPoints1[1] = Point2i(0, src.rows);
	srcPoints1[2] = Point2i(src.cols, 0);

	dstPoints1[0] = Point2i((width_rotate - width)/2 , (height_rotate - height)/2);
	dstPoints1[1] = Point2i((width_rotate - width)/2 , src.rows + (height_rotate - height)/2);
	dstPoints1[2] = Point2i(src.cols + (width_rotate - width)/2, (height_rotate - height)/2);

	Mat M2 = getAffineTransform(srcPoints1, dstPoints1);
	
	M1.at<double>(0, 2) = M1.at<double>(0, 2) + M2.at<double>(0, 2);
	M1.at<double>(1, 2) = M1.at<double>(1, 2) + M2.at<double>(1, 2);

	//Mat src2(Size(width_rotate, height_rotate), CV_8UC1, Scalar(0));
	Mat res5(width_rotate, height_rotate, CV_8UC1, Scalar(0));
	
	//warpAffine(src, src2, M2, src.size());
	//imshow("平移", src2);
	warpAffine(src, res5, M1, Size(width_rotate, height_rotate));
	

	imshow("自适应旋转图像", res5);
	waitKey(0);
	return 0;
}

 

  • 3
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值