OpenCV-图像旋转及仿射变换实现

图像旋转:

自己用OpenCV实现了绕图像中心旋转

代码实现:

//旋转
cv::Mat angleRotate(cv::Mat &image, int angle)
{
	double alpha = angle * CV_PI / 180;
	double rotateMat[3][3] = {
		{cos(alpha),-sin(alpha),0},
		{sin(alpha),cos(alpha),0},
		{0,0,1}
	};
	int row = image.rows, col = image.cols;
	double a1 = col * rotateMat[0][0];
	double b1 = col * rotateMat[1][0];
	double a2 = col * rotateMat[0][0] + row * rotateMat[0][1];
	double b2 = col * rotateMat[1][0] + row * rotateMat[1][1];
	double a3 = row * rotateMat[0][1];
	double b3 = row * rotateMat[1][1];
	double kxmi = std::min(std::min(std::min(0.0, a1), a2), a3);
	double kxma = std::max(std::max(std::max(0.0, a1), a2), a3);
	double kymi = std::min(std::min(std::min(0.0, b1), b2), b3);
	double kyma = std::max(std::max(std::max(0.0, b1), b2), b3);

	int col1 = abs(kxma - kxmi), row1 = abs(kyma - kymi);
	cv::Mat result(row1, col1, image.type(), cv::Scalar::all(0));
	for (int i = 0; i < row1; i++)
	{
		for (int j = 0; j < col1; j++)
		{
			int x = (j + kxmi)*rotateMat[0][0] - (i + kymi)*rotateMat[0][1];
			int y = -(j + kxmi)*rotateMat[1][0] + (i + kymi)*rotateMat[1][1];
			if (x >= 0 && x < col&&y >= 0 && y < row)
			{
				result.at(i, j) = image.at(y, x);
			}
		}
	}
	return result;
}


仿射变换:

图像的仿射变换是指在空间直角坐标系中将一个二维坐标转换到另外一个二维坐标,仿射变换是一种线性变换。仿射变换来表示:旋转 (线性变换),平移 (向量加),缩放操作 (线性变换)。通常使用 2 \times 3 矩阵来表示仿射变换。在使用OpenCV进行仿射变换时,会先计算一个仿射变换矩阵,获取仿射变换矩。

使用OpenCV函数getAffineTransform能求出仿射变换矩:

Mat getAffineTransform(InputArray src, InputArray dst)  

src:源图像的三个点

dst:输出图像的三个点

返回的就是描述仿射变换的2*3矩阵


将求得的仿射变换矩应用到源图像

void warpAffine(InputArray src, OutputArray dst, InputArray M, Size dsize) 

src:输入图像

dst:为变换后图像,类型与src一致

M:变换矩阵

dsize:输出图像的大小


通过getRotationMatrix2D函数可以计算二维旋转的仿射变换矩阵
Mat getRotationMatrix2D(Point2f center, double angle, double scale)

第一个参数,Point2f类型的center,表示源图像的旋转中心

第二个参数,double类型的angle,旋转角度。角度为正值表示向逆时针旋转

第三个参数,double类型的scale,缩放系数


cv::Mat cv::getRotationMatrix2D(cv::Point2f center, double angle, double scale)
{
	//角度转换
	angle *= CV_PI / 180;
	//计算旋转矩阵角度
	double alpha = cos(angle) * scale;
	double beta = sin(angle) * scale;
	cv::Mat M(2, 3, CV_64F);
	double *m = (double*)M.data;
	//构造旋转矩阵
	m[0] = alpha;
	m[1] = beta;
	m[2] = (1 - alpha) * center.x - beta * center.y;
	m[3] = -beta;
	m[4] = alpha;
	m[5] = beta * center.x + (1 - alpha) * center.y;
	return M;
}

代码实现:

#include 
#include 
#include 

int main()
{
	cv::Mat image = cv::imread("1.jpg");
	if (image.empty()) return -1;
	cv::imshow("image", image);
	int row = image.rows, col = image.cols;
	cv::Point2f srcPoint[3];
	cv::Point2f resPoint[3];
	srcPoint[0] = cv::Point2f(0, 0);
	srcPoint[1] = cv::Point2f(col - 1, 0);
	srcPoint[2] = cv::Point2f(0, row - 1);
	resPoint[0] = cv::Point2f(col * 0, row*0.33);
	resPoint[1] = cv::Point2f(col*0.85, row*0.25);
	resPoint[2] = cv::Point2f(col*0.15, row*0.7);
	cv::Mat warpMat(cv::Size(2, 3), CV_32F);
	cv::Mat resultimage10 = cv::Mat::zeros(row, col, image.type());
	warpMat = cv::getAffineTransform(srcPoint, resPoint);
	cv::warpAffine(image, resultimage10, warpMat, resultimage10.size());
	cv::namedWindow("resultimage10");
	cv::imshow("resultimage10", resultimage10);
	cv::Point2f centerPoint = cv::Point2f(col / 2, row / 2);
	double scale = 0.6, angle = -20;
	//获取仿射变换矩阵,centerPoint为旋转中心,angle为旋转角度,scale为缩放因子
	warpMat = cv::getRotationMatrix2D(centerPoint, angle, scale);
	cv::Mat resultimage11 = cv::Mat::zeros(row, col, image.type());
	cv::warpAffine(image, resultimage11, warpMat, resultimage11.size());
	cv::namedWindow("resultimage11");
	cv::imshow("resultimage11", resultimage11);
	cv::waitKey(0);
	return 0;
}

运行结果:

OpenCV-图像旋转及仿射变换实现_第1张图片

你可能感兴趣的:(----opencv学习)