日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

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

發布時間:2023/11/27 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 OpenCV中图像旋转(warpAffine)算法的实现过程 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

在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;//nearestfor (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);

采用雙線性插值算法的實現代碼為:

?

?

	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);


其它插值算法的實現代碼與雙線性類似,可參考?http://blog.csdn.net/fengbingchun/article/details/17335477

?

?

?

?

?

總結

以上是生活随笔為你收集整理的OpenCV中图像旋转(warpAffine)算法的实现过程的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

歡迎分享!

轉載請說明來源于"生活随笔",并保留原作者的名字。

本文地址:OpenCV中图像旋转(warpAffine)算法的实现过程