Affine And Perspective Transform(仿射變換和透視變換)
阿新 • • 發佈:2022-04-05
相關函式
Affine Transform 仿射變換
仿射變換將長方形影象轉化為平行四邊形。
void cv::warpAffine( cv::InputArray src, // Input image cv::OutputArray dst, // Result image cv::InputArray M, // 2-by-3 transform mtx cv::Size dsize, // Destination image size int flags = cv::INTER_LINEAR, // Interpolation, inverse int borderMode = cv::BORDER_CONSTANT, // Pixel extrapolation const cv::Scalar& borderValue = cv::Scalar() // For constant borders );
其中,cv::InputArray M(2x3的轉換矩陣M)通過如下函式獲得
// 方法1 :通過人工設定**3個**原圖上的點 和 對應對映到目標影象的點,求得轉換矩陣。 cv::Mat cv::getAffineTransform( // Return 2-by-3 matrix const cv::Point2f* src, // Coordinates *three* of vertices const cv::Point2f* dst // Target coords, three vertices ); //方法2 :設定旋轉中心,旋轉角度,縮放來求轉換矩陣 cv::Mat cv::getRotationMatrix2D( // Return 2-by-3 matrix cv::Point2f center // Center of rotation double angle, // Angle of rotation double scale // Rescale after rotation );
通過人工設定3個原圖上的點 和 對應對映到目標影象的點,求得轉換矩陣。該轉換矩陣用以轉換整幅影象。
轉換公式為:
\[dst(x,y) = src(M_{00}x+M_{01}y+M_{02},M_{10}x+M_{11}y+M_{12}) \]Perspective Transform 透視變換
可以將長方形影象轉化為任意形狀。
void cv::warpPerspective( cv::InputArray src, // Input image cv::OutputArray dst, // Result image cv::InputArray M, // 3-by-3 transform mtx cv::Size dsize, // Destination image size int flags = cv::INTER_LINEAR, // Interpolation, inverse int borderMode = cv::BORDER_CONSTANT, // Extrapolation method const cv::Scalar& borderValue = cv::Scalar() // For constant borders );
求轉化矩陣的函式,原始影象需要選4個點 對映到目標影象
cv::Mat cv::getPerspectiveTransform( // Return 3-by-3 matrix
const cv::Point2f* src, // Coordinates of *four* vertices
const cv::Point2f* dst // Target coords, four vertices
);
公式為:
\[dst(x,y) = src\big( \frac{M_{00}x+M_{01}y+M_{02}}{M_{20}x+M_{21}y+M_{22}} , \frac{M_{10}x+M_{11}y+M_{12}}{M_{20}x+M_{21}y+M_{22}}\big) \]仿射變換和透視變換
流程圖
source code
//learning OpenCV3 11-1 / 11-2
/*
*執行首先出現的圖片是仿射變換
* 按任意鍵執行透視變換
* 再按任意鍵退出
*/
#include <opencv2/imgcodecs.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>
#include <iostream>
using namespace std;
using namespace cv;
int main(int argc,char** argv)
{
if (argc != 2) {
cout << "vs在除錯-屬性除錯-除錯-命令引數 輸入影象路徑"
<< "Clion在編輯執行/除錯對話方塊-配置編輯-程式實參 輸入影象路徑" << endl;
}
//1、仿射變換
Mat imgOrg = imread(argv[1]), imgDis;
const Point2f srcThreePoints[3] = {
Point2f(0,0), //左上
Point2f(imgOrg.cols-1,0), //右上
Point2f(0,imgOrg.rows-1) //左下
};
const Point2f disThreePoints[3] = {
cv::Point2f(imgOrg.cols * 0.f, imgOrg.rows * 0.33f),
cv::Point2f(imgOrg.cols * 0.85f, imgOrg.rows * 0.25f),
cv::Point2f(imgOrg.cols * 0.15f, imgOrg.rows * 0.7f)
};
Mat m = getAffineTransform(srcThreePoints, disThreePoints);
warpAffine(imgOrg, imgDis, m, imgOrg.size());
imshow("imgOrg", imgOrg);
imshow("imgDis", imgDis);
for (int i{ 0 }; ; i++) {
Point2f center(imgOrg.cols * 0.5, imgOrg.rows * 0.5);
double angle = i * 3 % 360;
double scale = (cos((angle - 60) * CV_PI / 180) + 1.05) * 0.8;
Mat M = getRotationMatrix2D(center, angle, scale), imgDisRotate;
warpAffine(imgOrg,imgDisRotate,M,imgOrg.size());
imshow("imgDisRotate", imgDisRotate);
if (waitKey(30) >= 0) { break; }
}
//2、透視變換
Point2f srcFourPoints[4] = {
cv::Point2f(0, 0), // src Top left
cv::Point2f(imgOrg.cols - 1, 0), // src Top right
cv::Point2f(imgOrg.cols - 1, imgOrg.rows - 1), // src Bottom right
cv::Point2f(0, imgOrg.rows - 1) // src Bottom left
};
cv::Point2f dstFourQuad[] = {
cv::Point2f(imgOrg.cols * 0.05f, imgOrg.rows * 0.33f),
cv::Point2f(imgOrg.cols * 0.9f, imgOrg.rows * 0.25f),
cv::Point2f(imgOrg.cols * 0.8f, imgOrg.rows * 0.9f),
cv::Point2f(imgOrg.cols * 0.2f, imgOrg.rows * 0.7f)
};
Mat m1 = getPerspectiveTransform(srcFourPoints, dstFourQuad),imgPerspective;
warpPerspective(imgOrg, imgPerspective, m1,imgOrg.size());
imshow("Perspective", imgPerspective);
waitKey();
destroyAllWindows();
return 0;
}