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>

  • 相关阅读:
    zoj3814
    cf249D
    codeforces 461C
    uva 11584
    Codeforces Round #247 (Div. 2) C D
    AOAPC I: Beginning Algorithm Contests (Rujia Liu) Volume 6. Mathematical Concepts and Methods
    AOAPC I: Beginning Algorithm Contests -- Training Guide (Rujia Liu) Chapter 3. Data Structures Fundamental Data Structures
    Codeforces Round #257 (Div. 2)
    DAY 16 PYTHON入门
    DAY 15 PYTHON入门
  • 原文地址:https://www.cnblogs.com/Toring/p/6628285.html
Copyright © 2011-2022 走看看