重磅干貨,第一時間送達 經(jīng)過幾個月的努力,,小白終于完成了市面上第一本OpenCV 4入門書籍《從零學(xué)習(xí)OpenCV 4》,。為了更讓小伙伴更早的了解最新版的OpenCV 4,小白與出版社溝通,,提前在公眾號上連載部分內(nèi)容,,請持續(xù)關(guān)注小白。 本小節(jié)將介紹圖像的另一種變換——透視變換,。透視變換是按照物體成像投影規(guī)律進行變換,,即將物體重新投影到新的成像平面,示意圖如圖3-24所示,。透視變換常用于機器人視覺導(dǎo)航研究中,,由于相機視場與地面存在傾斜角使得物體成像產(chǎn)生畸變,,通常通過透視變換實現(xiàn)對物體圖像的校正。透視變換中,,透視前的圖像和透視后的圖像之間的變換關(guān)系可以用一個3×3的矩陣變換矩陣表示,,該矩陣可以通過兩張圖像中四個對應(yīng)點的坐標求取,因此透視變換又稱作“四點變換”,。與仿射變換一樣,,OpenCV 4中提供了根據(jù)四個對應(yīng)點求取變換矩陣的getPerspectiveTransform()函數(shù)和進行透視變換的warpPerspective()函數(shù),接下來將介紹這兩個函數(shù)的使用方法,,兩個函數(shù)的函數(shù)原型在代碼清單3-35和代碼清單3-36中給出,。圖3-24 透視變換原理示意圖 代碼清單3-35 getPerspectiveTransform()函數(shù)原型 1. Mat cv::getPerspectiveTransform (const Point2f src[], 2. const Point2f dst[], 3. int solveMethod = DECOMP_LU 4. ) 該函數(shù)兩個輸入量都是存放浮點坐標的數(shù)組,,在生成數(shù)組的時候像素點的輸入順序無關(guān),,但是需要注意像素點的對應(yīng)關(guān)系,函數(shù)的返回值是一個3×3的變換矩陣,。函數(shù)中最后一個參數(shù)是根據(jù)四個對應(yīng)點坐標計算透視變換矩陣方法的選擇標志,,其可以選擇的參數(shù)標志在表3-6中給出,默認情況下選擇的是最佳主軸元素的高斯消元法DECOMP_LU,。 表3-6 getPerspectiveTransform()函數(shù)計算方法標志 標志參數(shù) | 簡記 | 作用 | DECOMP_LU | 0 | 最佳主軸元素的高斯消元法 | DECOMP_SVD | 1 | 奇異值分解(SVD)方法 | DECOMP_EIG | 2 | 特征值分解法 | DECOMP_CHOLESKY | 3 | Cholesky分解法 | DECOMP_QR | 4 | QR分解法 | DECOMP_NORMAL | 16 | 使用正規(guī)方程公式,,可以去前面的標志一起使用 |
代碼清單3-36 warpPerspective()函數(shù)原型 1. void cv::warpPerspective(InputArray src, 2. OutputArray dst, 3. InputArray M, 4. Size dsize, 5. int flags = INTER_LINEAR, 6. int borderMode = BORDER_CONSTANT, 7. const Scalar & borderValue = Scalar() 8. ) src:輸入圖像。 dst:透視變換后輸出圖像,,與src數(shù)據(jù)類型相同,,但是尺寸與dsize相同。 M:3×3的變換矩陣,。 dsize:輸出圖像的尺寸,。 flags:插值方法標志。 borderMode:像素邊界外推方法的標志,。 borderValue:填充邊界使用的數(shù)值,,默認情況下為0
該函數(shù)所有參數(shù)含義都與warpAffine()函數(shù)的參數(shù)含義相同,這里不再進行贅述,。為了說明該函數(shù)在實際應(yīng)用中的作用,,在代碼清單3-37中給出了將相機視線不垂直于二維碼平面拍攝的圖像經(jīng)過透視變換變成相機視線垂直于二維碼平面拍攝的圖像。在圖3-25中給出了相機拍攝到的二維碼圖像和經(jīng)過程序透視變換后的圖像,。為了尋找透視變換關(guān)系,,我們需要尋找拍攝圖像中二維碼四個角點的像素坐標和透視變換后角點對應(yīng)的理想坐標。本程序中,,我們事先通過Image Watch插件查看了拍攝圖像二維碼四個角點的坐標,,并希望透視變換后二維碼可以充滿全部的圖像,,因此我們在程序中手動輸入四對對應(yīng)點的像素坐標。但是在實際工程中,,二維碼的角點坐標可以通過角點檢測的方式獲取,,具體方式我們將在后面介紹。 代碼清單3-37 myWarpPerspective.cpp二維碼圖像透視變換 1. #include <opencv2\opencv.hpp> 2. #include <iostream> 3. 4. using namespace cv; 5. using namespace std; 6. 7. int main() 8. { 9. Mat img = imread("noobcvqr.png"); 10. if (img.empty()) 11. { 12. cout << "請確認圖像文件名稱是否正確" << endl; 13. return -1; 14. } 15. 16. Point2f src_points[4]; 17. Point2f dst_points[4]; 18. //通過Image Watch查看的二維碼四個角點坐標 19. src_points[0] = Point2f(94.0, 374.0); 20. src_points[1] = Point2f(507.0, 380.0); 21. src_points[2] = Point2f(1.0, 623.0); 22. src_points[3] = Point2f(627.0, 627.0); 23. //期望透視變換后二維碼四個角點的坐標 24. dst_points[0] = Point2f(0.0, 0.0); 25. dst_points[1] = Point2f(627.0, 0.0); 26. dst_points[2] = Point2f(0.0, 627.0); 27. dst_points[3] = Point2f(627.0, 627.0); 28. Mat rotation, img_warp; 29. rotation = getPerspectiveTransform(src_points, dst_points); //計算透視變換矩陣 30. warpPerspective(img, img_warp, rotation, img.size()); //透視變換投影 31. imshow("img", img); 32. imshow("img_warp", img_warp); 33. waitKey(0); 34. return 0; 35. } 圖3-25 myWarpPerspective.cpp程序運行結(jié)果
|