OpenCV中图像旋转(warpAffine)算法的实现过程 您所在的位置:网站首页 双三次插值算法讲解 OpenCV中图像旋转(warpAffine)算法的实现过程

OpenCV中图像旋转(warpAffine)算法的实现过程

2024-06-01 12:11| 来源: 网络整理| 查看: 265

在OpenCV中,目前并没有现成的函数直接用来实现图像旋转,它是用仿射变换函数cv::warpAffine来实现的,此函数目前支持4种插值算法,最近邻、双线性、双三次、兰索斯插值,如果传进去的参数为基于像素区域关系插值算法(INTER_AREA),则按双线性插值。

通常使用2*3矩阵来表示仿射变换:

          

 

其中,T相当于变换前的原始图像,x,y为变换后的图像坐标。

对于cv::getRotationMatrix2D函数的实现公式为:

 

其中scale为缩放因子(x、y方向保持一致),angle为旋转角度(弧长),centerx,centery为旋转中心。

以lena.jpg图像旋转45度为例:   

采用最近邻插值算法的实现代码为:

 

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 10; int Y = (Y0 + bdelta) >> 10; if ((unsigned)X < iWidth && (unsigned)Y < iHeight) { matDst1.at(y, x) = matSrc.at(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);

采用双线性插值算法的实现代码为:

 

 

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= iWidth - 1) { // fx = 0, sx = iWidth - 2; //} if (sx < 0 || sx >= iWidth) continue; short cbufx[2]; cbufx[0] = cv::saturate_cast((1.f - fx) * 2048); cbufx[1] = 2048 - cbufx[0]; for (int k=0; k> 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);

其它插值算法的实现代码与双线性类似,可参考 http://blog.csdn.net/fengbingchun/article/details/17335477

 

 

 

 

 



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有