OpenCV常用影象拼接方法(二):基於模板匹配拼接
阿新 • • 發佈:2020-08-09
OpenCV常用影象拼接方法將分為四個部分與大家共享,這裡是第二種方法,歡迎關注後續,此處子系統與素材連結位於文章末尾。
OpenCV常用影象拼接方法(二):基於模板匹配的影象拼接。基於模板的影象拼接特徵和適用範圍:影象有重合區域,且待分割影象之間無明顯尺度變化和畸變。常用例項:兩個相鄰相機水平拍攝影象拼接。優點:簡單,快速(相比於SIFT特徵匹配拼接)。
這裡沒有找到更好的例項圖片,所以仍使用上一篇文章中的圖片,擷取如下兩部分ROI作為待拆分影象。
待拼接圖①:
待拼接圖②:
思路:在圖①中擷取部分公共區域ROI作為模板,利用模板在圖②中匹配,得到最佳匹配位置後計算X和Y方向需要平移的距離,將圖②對應的拼接到大圖。如下,模板為青色區域:
部分程式碼和效果如下:
// Image_Stitch_With_Matchtemplate.cpp // 環境VS2017 + OpenCV4.4.0 // 功能:基於模板匹配的影象拼接 // 特點:影象有重合區域,且待拼接影象之間無明顯尺度變換和畸變 #include "pch.h" #include <iostream> #include <opencv2/opencv.hpp> using namespace std; using namespace cv; int main() { Mat imgL = imread("A.jpg"); Mat imgR = imread("B.jpg"); double start = getTickCount(); Mat grayL, grayR; cvtColor(imgL, grayL, COLOR_BGR2GRAY); cvtColor(imgR, grayR, COLOR_BGR2GRAY); Rect rectCut = Rect(372, 122, 128, 360); Rect rectMatched = Rect(0, 0, imgR.cols / 2, imgR.rows); Mat imgTemp = grayL(Rect(rectCut)); Mat imgMatched = grayR(Rect(rectMatched)); int width = imgMatched.cols - imgTemp.cols + 1; int height = imgMatched.rows - imgTemp.rows + 1; Mat matchResult(height, width, CV_32FC1); matchTemplate(imgMatched, imgTemp, matchResult, TM_CCORR_NORMED); normalize(matchResult, matchResult, 0, 1, NORM_MINMAX, -1); //歸一化到0--1範圍 double minValue, maxValue; Point minLoc, maxLoc; minMaxLoc(matchResult, &minValue, &maxValue, &minLoc, &maxLoc); Mat dstImg(imgL.rows, imgR.cols + rectCut.x - maxLoc.x, CV_8UC3, Scalar::all(0)); Mat roiLeft = dstImg(Rect(0, 0, imgL.cols, imgL.rows)); imgL.copyTo(roiLeft); Mat debugImg = imgR.clone(); rectangle(debugImg, Rect(maxLoc.x, maxLoc.y, imgTemp.cols, imgTemp.rows), Scalar(0, 255, 0), 2, 8); imwrite("match.jpg", debugImg); Mat roiMatched = imgR(Rect(maxLoc.x, maxLoc.y - rectCut.y, imgR.cols - maxLoc.x, imgR.rows - 1 - (maxLoc.y - rectCut.y))); Mat roiRight = dstImg(Rect(rectCut.x, 0, roiMatched.cols, roiMatched.rows)); roiMatched.copyTo(roiRight); double end = getTickCount(); double useTime = (end - start) / getTickFrequency(); cout << "use-time : " << useTime << "s" << endl; imwrite("dst.jpg", dstImg); cout << "Done!" << endl; return 0; }
匹配結果:
拼接結果:
本次耗時如下圖:(工業相機1200W圖片拼接大約200ms):