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 C. No to Palindromes!
    codeforces D. Pashmak and Parmida's problem
    codeforces C. Little Pony and Expected Maximum
    codeforces D. Count Good Substrings
    codeforces C. Jzzhu and Chocolate
    codeforces C. DZY Loves Sequences
    codeforces D. Multiplication Table
    codeforces C. Painting Fence
    hdu 5067 Harry And Dig Machine
    POJ 1159 Palindrome
  • 原文地址:https://www.cnblogs.com/Toring/p/6628285.html
Copyright © 2011-2022 走看看