opencv圖像的仿射變換與透視變換矩陣


 

       仿射變換(affine transform)與透視變換(perspective transform)在圖像還原、圖像局部變化處理方面有重要意義。通常,在2D平面中,

仿射變換的應用較多,而在3D平面中,透視變換又有了自己的一席之地。兩種變換原理相似,結果也類似,可針對不同的場合使用適當的變換。

仿射變換和透視變換的數學原理不需深究,其計算方法為坐標向量和變換矩陣的乘積,換言之就是矩陣運算。在應用層面,

仿射變換是圖像基於3個固定頂點的變換,如圖所示:

 

 

       圖中紅點即為固定頂點,在變換先后固定頂點的像素值不變,圖像整體則根據變換規則進行變換

同理,透視變換是圖像基於4個固定頂點的變換,如圖所示:

 

 

 在OpenCV中,仿射變換和透視變換均有封裝好的函數,分別為:

void warpAffine(InputArray src, OutputArray dst, InputArray M, Size dsize, int flags=INTER_LINEAR, int borderMode=BORDER_CONSTANT, const Scalar& borderValue=Scalar())
void warpPerspective(InputArray src, OutputArray dst, InputArray M, Size dsize, int flags=INTER_LINEAR, int borderMode=BORDER_CONSTANT, const Scalar& borderValue=Scalar())

兩種變換函數形式完全相同,因此以仿射變換函數為例:

void warpAffine(InputArray src, OutputArray dst, InputArray M, Size dsize, int flags=INTER_LINEAR, int borderMode=BORDER_CONSTANT, const Scalar& borderValue=Scalar())

參數InputArray src:輸入變換前圖像

參數OutputArray dst:輸出變換后圖像,需要初始化一個空矩陣用來保存結果,不用設定矩陣尺寸

參數InputArray M:變換矩陣,用另一個函數getAffineTransform()計算

參數Size dsize:設置輸出圖像大小

參數int flags=INTER_LINEAR:設置插值方式,默認方式為線性插值

后兩個參數不常用,在此不贅述

關於生成變換矩陣InputArray M的函數getAffineTransform():

Mat getAffineTransform(const Point2f* src, const Point2f* dst)

參數const Point2f* src:原圖的三個固定頂點

參數const Point2f* dst:目標圖像的三個固定頂點

返回值:Mat型變換矩陣,可直接用於warpAffine()函數

注意,頂點數組長度超過3個,則會自動以前3個為變換頂點;數組可用Point2f[]或Point2f*表示

示例代碼如下:

 1     //讀取原圖
 2     Mat I = imread("..//img.jpg");
 3     //設置空矩陣用於保存目標圖像
 4     Mat dst;
 5     //設置原圖變換頂點
 6     Point2f AffinePoints0[3] = { Point2f(100, 50), Point2f(100, 390), Point2f(600, 50) };
 7     //設置目標圖像變換頂點
 8     Point2f AffinePoints1[3] = { Point2f(200, 100), Point2f(200, 330), Point2f(500, 50) };
 9     //計算變換矩陣
10     Mat Trans = getAffineTransform(AffinePoints0, AffinePoints1);
11     //矩陣仿射變換
12     warpAffine(I, dst, Trans, Size(I.cols, I.rows));
13     //分別顯示變換先后圖像進行對比
14     imshow("src", I);
15     imshow("dst", dst);
16     waitKey();

同理,透視變換與仿射變換函數類似:

void warpPerspective(InputArray src, OutputArray dst, InputArray M, Size dsize, int flags=INTER_LINEAR, int borderMode=BORDER_CONSTANT, const Scalar& borderValue=Scalar())

生成變換矩陣函數為:

Mat getPerspectiveTransform(const Point2f* src, const Point2f* dst)

注意,透視變換頂點為4個

兩種變換完整代碼及結果比較:

 1 #include <iostream>
 2 #include <opencv.hpp>
 3 using namespace std;
 4 using namespace cv;
 5 
 6 Mat AffineTrans(Mat src, Point2f* scrPoints, Point2f* dstPoints)
 7 {
 8     Mat dst;
 9     Mat Trans = getAffineTransform(scrPoints, dstPoints);
10     warpAffine(src, dst, Trans, Size(src.cols, src.rows), CV_INTER_CUBIC);
11     return dst;
12 }
13 
14 Mat PerspectiveTrans(Mat src, Point2f* scrPoints, Point2f* dstPoints)
15 {
16     Mat dst;
17     Mat Trans = getPerspectiveTransform(scrPoints, dstPoints);
18     warpPerspective(src, dst, Trans, Size(src.cols, src.rows), CV_INTER_CUBIC);
19     return dst;
20 }
21 
22 void main()
23 {
24     Mat I = imread("..//img.jpg");    //700*438
25 
26     Point2f AffinePoints0[4] = { Point2f(100, 50), Point2f(100, 390), Point2f(600, 50), Point2f(600, 390) };
27     Point2f AffinePoints1[4] = { Point2f(200, 100), Point2f(200, 330), Point2f(500, 50), Point2f(600, 390) };
28     Mat dst_affine = AffineTrans(I, AffinePoints0, AffinePoints1);
29     Mat dst_perspective = PerspectiveTrans(I, AffinePoints0, AffinePoints1);
30 
31     for (int i = 0; i < 4; i++)
32     {
33         circle(I, AffinePoints0[i], 2, Scalar(0, 0, 255), 2);
34         circle(dst_affine, AffinePoints1[i], 2, Scalar(0, 0, 255), 2);
35         circle(dst_perspective, AffinePoints1[i], 2, Scalar(0, 0, 255), 2);
36     }
37 
38     imshow("origin", I);
39     imshow("affine", dst_affine);
40     imshow("perspective", dst_perspective);
41     waitKey();
42 }

結果如圖:

                          

        可以看出,仿射變換以3個點為基准點,即使數組長度為4也僅取前3個點作為基准點;透視變換以4個點為基准點,

兩種變換結果不相同。應根據實際情況判斷使用哪種變換方式更佳。

 

 

 

 

 

 

 

 

 

 

 

博客轉自:https://www.cnblogs.com/wyuzl/p/7745106.html  轉自:https://zhuanlan.zhihu.com/p/24591720


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM