一般通过一个2*3的矩阵对图像中每个位置(x,y)进行矩阵运算来得到一个新的位置(x',y'),具体公式如下:
每个对应点有两个对应的方程,因此只要找到三个位置对应的点就可以知道变换矩阵,在OpenCV中通过getAffineTransform函数可得。也可以直接给出中心点与角度,得到一个旋转变换矩阵,对应OpenCV中getRotationMatrix2D接口可得。一般进行旋转变换后有一个偏移,需要通过计算点的位置变换得到一个平移矩阵来对图像进行校正,在旋转矩阵的最后一列增加平移最后进行仿射变换。
需要了解旋转变换后窗口的尺寸变换:
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include
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(0, 2) = M1.at(0, 2) + M2.at(0, 2);
M1.at(1, 2) = M1.at(1, 2) + M2.at(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;
}