zoukankan      html  css  js  c++  java
  • OpenCV图像旋转算法

    采用最近邻插值算法的实现代码为:
    <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>

  • 相关阅读:
    codeforces 616B Dinner with Emma
    codeforces 616A Comparing Two Long Integers
    codeforces 615C Running Track
    codeforces 612C Replace To Make Regular Bracket Sequence
    codeforces 612B HDD is Outdated Technology
    重写父类中的成员属性
    子类继承父类
    访问修饰符
    方法的参数
    实例化类
  • 原文地址:https://www.cnblogs.com/Toring/p/6628285.html
Copyright © 2011-2022 走看看