OpenCV图像旋转算法

摘要:
采用最近邻插值算法的实现代码为:cv::MatmatSrc=cv::imread;ifreturn;constdoubledegree=45;doubleangle=degree*CV_PI/180.;doublealpha=cos;doublebeta=sin;intiWidth=matSrc.cols;intiHeight=matSrc.rows;intiNewWidth=cvRound;intiNewHeight=cvRound;doublem[6];m[0]=alpha;m[1]=beta;m[2]=*iWidth/2.-beta*iHeight/2.;m[3]=-m[1];m[4]=m[0];m[5]=beta*iWidth/2.+*iHeight/2.;cv::MatM=cv::Mat;cv::MatmatDst1=cv::Mat;doubleD=m[0]*m[4]-m[1]*m[3];D=D!
采用最近邻插值算法的实现代码为:
<span style="font-size:14px;">cv::Mat matSrc = cv::imread("lena.jpg", 2 | 4);

	if (matSrc.empty()) return;

	const double degree = 45;
	double angle = degree * CV_PI / 180.;
	double alpha = cos(angle);
	double beta = sin(angle);
	int iWidth = matSrc.cols;
	int iHeight = matSrc.rows;
	int iNewWidth = cvRound(iWidth * fabs(alpha) + iHeight * fabs(beta));
	int iNewHeight = cvRound(iHeight * fabs(alpha) + iWidth * fabs(beta));

	double m[6];
	m[0] = alpha;
	m[1] = beta;
	m[2] = (1 - alpha) * iWidth / 2. - beta * iHeight / 2.;
	m[3] = -m[1];
	m[4] = m[0];
	m[5] = beta * iWidth / 2. + (1 - alpha) * iHeight / 2.;

	cv::Mat M = cv::Mat(2, 3, CV_64F, m);
	cv::Mat matDst1 = cv::Mat(cv::Size(iNewWidth, iNewHeight), matSrc.type(), cv::Scalar::all(0));

	double D = m[0]*m[4] - m[1]*m[3];
	D = D != 0 ? 1./D : 0;
	double A11 = m[4]*D, A22 = m[0]*D;
	m[0] = A11; m[1] *= -D;
	m[3] *= -D; m[4] = A22;
	double b1 = -m[0]*m[2] - m[1]*m[5];
	double b2 = -m[3]*m[2] - m[4]*m[5];
	m[2] = b1; m[5] = b2;

	int round_delta = 512;//nearest
	for (int y=0; y<iNewHeight; ++y)
	{
		for (int x=0; x<iNewWidth; ++x)
		{
			//int tmpx = cvFloor(m[0] * x + m[1] * y + m[2]);
			//int tmpy = cvFloor(m[3] * x + m[4] * y + m[5]);
			int adelta = cv::saturate_cast<int>(m[0] * x * 1024);
			int bdelta = cv::saturate_cast<int>(m[3] * x * 1024);
			int X0 = cv::saturate_cast<int>((m[1] * y + m[2]) * 1024) + round_delta;
			int Y0 = cv::saturate_cast<int>((m[4] * y + m[5]) * 1024) + round_delta;
			int X = (X0 + adelta) >> 10;
			int Y = (Y0 + bdelta) >> 10;

			if ((unsigned)X < iWidth && (unsigned)Y < iHeight)
			{
				matDst1.at<cv::Vec3b>(y, x) = matSrc.at<cv::Vec3b>(Y, X);
			}
		}
	}
	cv::imwrite("rotate_nearest_1.jpg", matDst1);

	M = cv::getRotationMatrix2D(cv::Point2f(iWidth / 2., iHeight / 2.), degree, 1);

	cv::Mat matDst2;
	cv::warpAffine(matSrc, matDst2, M, cv::Size(iNewWidth, iNewHeight), 0, 0, 0);
	cv::imwrite("rotate_nearest_2.jpg", matDst2);</span>

采用双线性插值算法的实现代码为:
<span style="font-size:14px;">cv::Mat matSrc = cv::imread("lena.jpg", 2 | 4);

	if (matSrc.empty()) return;

	const double degree = 45;
	double angle = degree * CV_PI / 180.;
	double alpha = cos(angle);
	double beta = sin(angle);
	int iWidth = matSrc.cols;
	int iHeight = matSrc.rows;
	int iNewWidth = cvRound(iWidth * fabs(alpha) + iHeight * fabs(beta));
	int iNewHeight = cvRound(iHeight * fabs(alpha) + iWidth * fabs(beta));

	double m[6];
	m[0] = alpha;
	m[1] = beta;
	m[2] = (1 - alpha) * iWidth / 2. - beta * iHeight / 2.;
	m[3] = -m[1];
	m[4] = m[0];
	m[5] = beta * iWidth / 2. + (1 - alpha) * iHeight / 2.;

	cv::Mat M = cv::Mat(2, 3, CV_64F, m);
	cv::Mat matDst1 = cv::Mat(cv::Size(iNewWidth, iNewHeight), matSrc.type(), cv::Scalar::all(0));

	double D = m[0]*m[4] - m[1]*m[3];
	D = D != 0 ? 1./D : 0;
	double A11 = m[4]*D, A22 = m[0]*D;
	m[0] = A11; m[1] *= -D;
	m[3] *= -D; m[4] = A22;
	double b1 = -m[0]*m[2] - m[1]*m[5];
	double b2 = -m[3]*m[2] - m[4]*m[5];
	m[2] = b1; m[5] = b2;

	for (int y=0; y<iNewHeight; ++y)
	{
		for (int x=0; x<iNewWidth; ++x)
		{
			//int tmpx = cvFloor(m[0] * x + m[1] * y + m[2]);
			//int tmpy = cvFloor(m[3] * x + m[4] * y + m[5]);
			float fx = m[0] * x + m[1] * y + m[2];
			float fy = m[3] * x + m[4] * y + m[5];

			int sy  = cvFloor(fy);
			fy -= sy;
			//sy = std::min(sy, iHeight-2);
			//sy = std::max(0, sy);
			if (sy < 0 || sy >= iHeight) continue;

			short cbufy[2];
			cbufy[0] = cv::saturate_cast<short>((1.f - fy) * 2048);
			cbufy[1] = 2048 - cbufy[0];

			int sx = cvFloor(fx);
			fx -= sx;
			//if (sx < 0) {
			//	fx = 0, sx = 0;
			//}
			//if (sx >= iWidth - 1) {
			//	fx = 0, sx = iWidth - 2;
			//}
			if (sx < 0 || sx >= iWidth) continue;

			short cbufx[2];
			cbufx[0] = cv::saturate_cast<short>((1.f - fx) * 2048);
			cbufx[1] = 2048 - cbufx[0];

			for (int k=0; k<matSrc.channels(); ++k)
			{
				if (sy == iHeight - 1 || sx == iWidth - 1) {
					continue;
				} else {
					matDst1.at<cv::Vec3b>(y, x)[k] = (matSrc.at<cv::Vec3b>(sy, sx)[k] * cbufx[0] * cbufy[0] +
						matSrc.at<cv::Vec3b>(sy+1, sx)[k] * cbufx[0] * cbufy[1] +
						matSrc.at<cv::Vec3b>(sy, sx+1)[k] * cbufx[1] * cbufy[0] +
						matSrc.at<cv::Vec3b>(sy+1, sx+1)[k] * cbufx[1] * cbufy[1]) >> 22;
				}
			}
		}
	}
	cv::imwrite("rotate_bilinear_1.jpg", matDst1);

	M = cv::getRotationMatrix2D(cv::Point2f(iWidth / 2., iHeight / 2.), degree, 1);

	cv::Mat matDst2;
	cv::warpAffine(matSrc, matDst2, M, cv::Size(iNewWidth, iNewHeight), 1, 0, 0);
	cv::imwrite("rotate_bilinear_2.jpg", matDst2);</span>

免责声明:文章转载自《OpenCV图像旋转算法》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇ThinkPHP中M方法与D方法有什么区别程序员修炼之道 从小工到专家读书笔记下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

OpenCV实现人脸识别

// 总结:OpenCV实现人脸识别// 2016.2.12 by Huangtao//  主要有以下步骤:1、人脸检测2、人脸预处理3、从收集的人脸训练机器学习算法4、人脸识别5、收尾工作 =================================================人脸检测算法:===========================...

Boost库简介

Boost库由C++标准委员会库工作组成员发起,其中有些内容有望成为下一代C++标准库内容。在C++社区中影响甚大,是不折不扣的“准”标准库。 字符串和文本处理库 Conversion库:对C++类型转换的增强,提供更强的类型安全转换、更高效的类型安全保护、进行范围检查的数值转换和词法转换。 Format库:实现类似printf的格式化对象,可以把参数格式化...

ORBSLAM2 初体验 —— 配置安装

转载请注明出处,谢谢原创作者:MingruiYU原创链接:https://www.cnblogs.com/MingruiYu/p/12286752.html ORB-SLAM2作为目前应用最广泛的视觉SLAM系统,其经典和重要程度毋庸置疑。ORB-SLAM2的github文档中,提供了详尽的ORB-SLAM2配置教程,上手应该是比较容易的。本文将跟随其g...

FP Tree算法原理总结

 在Apriori算法原理总结中,我们对Apriori算法的原理做了总结。作为一个挖掘频繁项集的算法,Apriori算法需要多次扫描数据,I/O是很大的瓶颈。为了解决这个问题,FP Tree算法(也称FP Growth算法)采用了一些技巧,无论多少数据,只需要扫描两次数据集,因此提高了算法运行的效率。下面我们就对FP Tree算法做一个总结。 1. FP...

MD5加密和RSA加密

1.MD5加密    MD5(单向散列算法)的全称是Message-Digest Algorithm 5(信息-摘要算法),MD5算法的使用不需要支付任何版权费用。      MD5的功能:       ①.输入任意长度的信息,经过处理,输出为128位的信息(数字指纹);      ②.不同的输入得到的不同的结果(唯一性);      ③.根据128位的输...

区块链共识算法 PBFT(拜占庭容错)、PAXOS、RAFT简述

共识算法 区块链中最重要的便是共识算法,比特币使用的是POS(Proof of Work,工作量证明),以太币使用的是POS(Proof of Stake,股权证明)使得算理便的不怎么重要了,而今POS的变体DPOS(Delegated Proof of Stake,股份授权证明)进一步削减算力的浪费,同时也加强了区块链的安全性。 不过,对于不需要货币体系...