怎么在OpenCV中利用C++ 实现一个图片旋转效果
创始人
2024-12-26 09:02:00
0次

图片旋转,本质上是对旋转后的图片中每个像素点计算在原图的位置。然后照搬过来就好。

图形图像课上一般会介绍旋转变换矩阵,其中 t 为需要旋转的角度,[x'; y']是变换后坐标(其中分号表示上下关系):

怎么在OpenCV中利用C++ 实现一个图片旋转效果

即表示为:[x'; y'] = [cos(t) sin(t); -sin(t) cos(t)][x; y]

因为我个人兴趣爱好(放P就是老师逼的。。。),不允许使用 OpenCV 封装好的旋转函数。只能自己实现,我开始的想法是:先求变换矩阵逆矩阵,然后将一张全黑图中每个点一一对应插值到原图中。

结果发现转换后图片全黑了……

后来发现原点设置不对。用OpenCV中的 Mat格式存储(或二维数组)的图片, 原点在左上角 。但是想要实现的 旋转原点在图片中心 。

同时, Mat格式存储(或二维数组)的 坐标系中 y轴正方向向下 。这样人类视觉上的顺时针旋转,在二维数组的坐标系中是逆时针旋转。

最重要的一点,也是二维数组操作中极易忽略的一点: 数组操作的是 数组下标 ,不是坐标系(数组的行数 rows 是矩形的宽 width ,列数 cols 是矩形的长 length ) 。比如坐标系(此时为了更贴近数组布局,我们 假设 y 轴坐标系是向下的 )中,矩形顶点是:

怎么在OpenCV中利用C++ 实现一个图片旋转效果

但是在数组中,因为是行优先,所以四个点的下标取值为:

怎么在OpenCV中利用C++ 实现一个图片旋转效果

有没有发现,两种坐标是相反的!

总结下来,我们的图片旋转需要注意以下几点:

  1. 变换后图片中的每个像素点(i; j),需要平移到相对旋转中心的新坐标,即(i - Mat.rows/2; j - Mat.cols/2)。计算完成之后,需要再次 还原 到相对左上角原点的旧坐标;

  2. 本来需要 变换后图片 乘以 原图 变换矩阵的 逆矩阵 对应到原图中坐标。但是因为y轴方向向下,所以 变换后图片 乘以 原图 变换矩阵(无需逆矩阵) 即可对应到原图中坐标(顺时针旋转50度,还原操作是逆时针旋转50度);

  3. 矩阵下标与原图变换矩阵相乘之前,需要将矩阵 下标两值互换 。相乘之后,需要 再次互换下标值 还原成矩阵下标。

因此对于一个经过旋转 t 度之后 数组下标 为[m‘, n']的像素值,还原成原图中的 数组下标 [m; n]计算为:

[cos(t) -sin(t); sin(t) cos(t)] ([m'; n'] - [Mat.rows/2; Mat.cols/2]) = [m; n] -  [Mat.rows/2; Mat.cols/2]

源代码附上:

Mat nearestNeighRotate(cv::Mat img, float angle)
{
	int len = (int)(sqrtf(pow(img.rows, 2) + pow(img.cols, 2)) + 0.5);

	Mat retMat = Mat::zeros(len, len, CV_8UC3);
	float anglePI = angle * CV_PI / 180;
	int xSm, ySm;

	for(int i = 0; i < retMat.rows; i++)
		for(int j = 0; j < retMat.cols; j++)
		{
			xSm = (int)((i-retMat.rows/2)*cos(anglePI) - (j-retMat.cols/2)*sin(anglePI) + 0.5);
			ySm = (int)((i-retMat.rows/2)*sin(anglePI) + (j-retMat.cols/2)*cos(anglePI) + 0.5);
			xSm += img.rows / 2;
			ySm += img.cols / 2;

			if(xSm >= img.rows || ySm >= img.cols || xSm <= 0 || ySm <= 0){
				retMat.at(i, j) = Vec3b(0, 0);
			}
			else{
				retMat.at(i, j) = img.at(xSm, ySm);
			}
		}

	return retMat;
}

好,我们来测试看看:

int main() 
{ 
	Mat img = imread("../HelloWorld.png");
	retImg = nearestNeighRotate(img, -20.f);
	namedWindow("nearNeigh", CV_WINDOW_AUTOSIZE);
	imshow("nearNeigh", retImg);

	waitKey(); 
	cvDestroyAllWindows();
	return 0; 
}

相关内容

热门资讯

空调连续工作多久需要停机休息 空调连续工作的时间取决于多个因素,包括空调的型号、功率、使用环境和维护情况等。一般来说,空调可以连续...
空调哪个符号是除湿的 空调除湿功能通常用一个水滴形状的符号表示。不同品牌和型号的空调遥控器可能会有所差异,但一般来说,除湿...
格力空调多长时间加一次氟利昂 1、一般情况下,空调对氟利昂的使用量是非常小的,所以在空调使用了四年左右的时候再考虑加也没问题。2、...
空调用多长时间需要加氟一次 一般情况下是五年。当出现以下这几种情况时,空调才需要加氟。1、空调的室内机和室外机各有两个接口,当接...
格调生活·C标思享荟:卡萨帝在... 9月12日的郑州龙湖金融岛,夜风轻拂,灯光璀璨。“C标时刻共传奇——卡萨帝思享荟暨20周年品牌盛典郑...
品牌价值破千亿、高端份额持续领... 9月12日,“C标时刻共传奇——卡萨帝思享荟暨20周年品牌盛典郑州站”在郑州龙湖金融岛举办。2026...
空调主板坏了修800还是换新的 空调主板坏了是修还是换新,需要考虑多个因素,以下是一些建议:1. 维修成本:如果维修费用较低,比如 ...
空调开多久需要休息多长时间 问题:空调开多久需要休息多长时间回答:1、在使用空调的过程中,一般空调开7~8个小时左右需要休息2~...
中央空调多长时间清洗一次 1、一般空调开机前清洗一次即可,空调开机中间时段再清洗一次,空调关机时清洗一次,这样比较合理。2、空...
中央空调氟利昂多久加一次 看空调制热和制冷程度,很多人的观点认为氟利昂必须一年放一次,其实这个观点是错误的,理解上面有点偏差,...