一、知識點
1、void warpAffine(InputArray src,?
? ? ? ? ? ? ? ? ? OutputArray dst,?
?? ??? ??? ??? ? ?InputArray M,?
?? ??? ??? ??? ? ?Size dsize,?
?? ??? ??? ??? ? ?int flags = INTER_LINEAR,?
?? ??? ??? ??? ? ?int borderMode = BORDER_CONSTANT,?
?? ??? ??? ??? ? ?const Scalar & borderValue = Scalar());
(1)、對圖像應用仿射變換(旋轉、平移、縮放)。
(2)、參數說明:
? ? src: 輸入圖像。
? ? dst: 輸出圖像,大小為dsize,數據類型與src相同。
?? ?M: 2 * 3轉換矩陣(兩行三列)。
?? ?dsize: 輸出圖像的大小。
?? ?flags: 插值方法,InterpolationFlags枚舉值。可和WARP_INVERSE_MAP組合,意味著M是逆變換(dst-->src)。
?? ?borderMode: 邊界模式,像素外推方法,BorderTypes枚舉值。
?? ?borderValue: 邊界值。 當borderMode為BORDER_CONSTANT時,borderValue為邊界的像素顏色。
(3)、仿射變換公式:
dst(x,y) = src(M11x + M12y + M13, M21x + M22y + M23)| M11 M12 M13 | ? ? | x || ? ? ? ? ? ? | ?* ?| y || M21 M22 M23 | ? ? | 1 |
2、在OpenCV中,旋轉矩陣M為:
| cosθ ? sinθ ? 0 || ? ? ? ? ? ? ? ? || -sinθ ?cosθ ? 0 |
3、在OpenCV中,平移矩陣M為:
| 1 ? 0 ? dx || ? ? ? ? ? ?|| 0 ? 1 ? dy |
4、但是2、3的矩陣只相對于原點變換,實際工作中,經常是2、3的結合。?
? 對于繞任意點的旋轉矩陣,OpenCV中提供getRotationMatrix2D()獲取。
5、Mat getRotationMatrix2D(Point2f center, double angle, double scale);
? (1)、計算2D旋轉的仿射矩陣,可以用來對圖像進行旋轉。
? (2)、參數說明:
? ? ? center: 源圖像的旋轉中心點,即源圖像要圍繞此點旋轉。
?? ? ?angle: 旋轉的角度,以度為單位,正值逆時針旋轉,負值順時針旋轉。
?? ? ?scale: 縮放因子。 1.0不改變大小,0.5縮小一半,2.0放大一倍。
? (3)、原點在源圖像的左上角。
?? ?
6、旋轉后新的圖像大小計算:
? nw = w * cosθ + h * sinθ;nh = h * cosθ + w * sinθ;
二、示例代碼
#include <iostream>
#include <opencv2/opencv.hpp>int main()
{//1.獲取源圖像cv::Mat src = cv::imread("../images/9.png");if (src.empty()){std::cout << "load src image error..." << std::endl;return -1;}cv::imshow("源圖像", src);//2.獲取源圖像寬、高int w = src.cols;int h = src.rows;//3.獲取圍繞源圖像中心點,逆時針旋轉45度,不縮放的矩陣cv::Mat M = cv::getRotationMatrix2D(cv::Point2f(w / 2, h / 2), 45, 1.0);//4.仿射變換,但是旋轉后圖像四角被截斷,并且有黑色背景cv::Mat dst1;cv::warpAffine(src, dst1, M, cv::Size(w, h));cv::imshow("繞中心點逆時針旋轉45度", dst1);//5.改變旋轉后圖像大小,源圖像四角不被截斷double cosTheta = cv::abs(M.at<double>(0, 0));double sinTheta = cv::abs(M.at<double>(0, 1));int nw = w * cosTheta + h * sinTheta;int nh = h * cosTheta + w * sinTheta;M.at<double>(0, 2) += (nw / 2.0 - w / 2.0);M.at<double>(1, 2) += (nh / 2.0 - h / 2.0);cv::Mat dst2;cv::warpAffine(src, dst2, M, cv::Size(nw, nh));cv::imshow("改變大小,源圖像四角不被截斷", dst2);//6.填充背景cv::Scalar backColor(src.at<cv::Vec3b>(0, 0)[0], src.at<cv::Vec3b>(0, 0)[1], src.at<cv::Vec3b>(0, 0)[2]);cv::Mat dst3;cv::warpAffine(src, dst3, M, cv::Size(nw, nh), cv::INTER_LINEAR, 0, backColor);cv::imshow("填充背景", dst3);cv::waitKey(0);return 0;
}
輸出結果: