最近發現網上關於 estimateRigidTransform 的詳細說明很少,因此這里做一個詳細的解釋。希望對大家有用。
一、函數定義如下:
Mat estimateRigidTransform(InputArraysrc,InputArraydst,boolfullAffine)
前兩個參數,可以是 :src=srcImage (變換之前的圖片Mat) dst=transImage(變換之后的圖片Mat)
也可以: src=array(變換之前的關鍵點Array) dst=array(變換之后的關鍵點Array)
第三個參數: 1(全仿射變換,包括:rotation, translation, scaling,shearing,reflection)
0(帶有約束的仿射變換)
默認參數1:全仿射變換。
fullAffine 與 partialAaffine 主要區別是:變換矩陣中后者可以是剛體變換。(不是必須,體會可以的含義)
也就可以后者沒有尺度縮放。
二、直觀感受:
paritcalAffine 的變換矩陣必須是如下類型:
旋轉矩陣對角線元素的 絕對值 肯定相等。
假設我們的矩陣
|a11|=|a22| 同時|a21|=|a22|.真是基本條件。
fullAffine 的rotate矩陣可以是:
旋轉矩陣可以沒有任何數值上的約束。aii之間無數值上的約束。
三、fullAffine原理及變換公式
如果我們有一個點變換之前是[x,y,1],變換后是[x',y',1] 則fullAffine表示如下:
展開后表示
如果我們想求這【a-f】 6個變量需要有6個方程,也就是3組點。但是比三個點多呢?
比如:20個點。那就是用最小方差。
四、partial affine的原理及變換公式
1.尺度變換
2.旋轉矩陣
1、2結合后
注意:這里的tx 指的是x方向的transpose (平移),ty同理。
解這個T需要四個方程:也就是兩組點。同樣,點多的情況下用最小方差原理。計算最優變換。
1 #ifndef _HEAD_H_ 2 #define _HEAD_H_ 3 4 #include 5 6 /* definitions of Macros */ 7 8 #define PI 3.141592 9 #define MAX_COUNT 30 10 cv::Mat preTransGray, curTransGray; 11 cv::Mat preRotaGray , curRotaGray; 12 std::vector transPoints[2], rotaPoints[2],knowPoint[2]; std::vector status; std::vectorerr; 13 14 void testOpticalFlowEstimation() 15 { 16 std::cout << "optical flow methon for estimating the transform form reference scan " << "to reference scan ..." << std::endl; double refPose_x = 250, refPose_y = 250; // Init rectangle center 17 cv::Mat trans_src_image = cv::imread("./testImage/squareRef.png"); // resolution: 500*500 and the rectangle center is (250,250) 18 cv::Mat trans_dst_image = cv::imread("./testImage/squareCur.png"); // resolution: 500*500 and the rectangle center is (260,240) 19 cv::Mat rota_src_image = cv::imread("./testImage/rotateRectRef.png"); 20 cv::Mat rota_dst_image = cv::imread("./testImage/rotateRectCur.png"); 21 cv::Mat contra_image = cv::imread("./testImage/contrastRef_Rotate.png"); 22 cvtColor(trans_src_image,preTransGray, cv::COLOR_BGR2GRAY); 23 cvtColor(trans_dst_image,curTransGray, cv::COLOR_BGR2GRAY); 24 cvtColor(rota_src_image,preRotaGray, cv::COLOR_BGR2GRAY); 25 cvtColor(rota_dst_image,curRotaGray, cv::COLOR_BGR2GRAY); 26 cv::TermCriteria termcrit(cv::TermCriteria::COUNT + cv::TermCriteria::EPS, 20 ,0.01); 27 cv::Size subPixWinSize(10,10), winSize(31,31); 28 goodFeaturesToTrack(preTransGray,transPoints[0],MAX_COUNT,0.01,10); // 29 find corners goodFeaturesToTrack(preRotaGray,rotaPoints[0],MAX_COUNT,0.01,10); // find corners /*subpiexl detection*/ // 30 cornerSubPix(curGray,points[0],subPixWinSize,cv::Size(-1,-1),termcrit); 31 cornerSubPix(preTransGray,transPoints[0],subPixWinSize,cv::Size(-1,-1),termcrit); 32 cornerSubPix(preRotaGray,rotaPoints[0],subPixWinSize,cv::Size(-1,-1),termcrit); /*PryLK method calculate optical flow*/ // 33 calcOpticalFlowPyrLK(preGray,curGray,points[0],points[1],status,err,winSize,5,termcrit,0,0.01); 34 calcOpticalFlowPyrLK(preTransGray,curTransGray,transPoints[0],transPoints[1],status,err,winSize,3,termcrit,0,0.01); 35 calcOpticalFlowPyrLK(preRotaGray,curRotaGray,rotaPoints[0],rotaPoints[1],status,err,winSize,3,termcrit,0,0.01); // Notice the last para in estimateRigidTransform func 36 37 // if you choose 0 : partAffine , indicate you will perform a rigid transform // choose 1 : fullAffine , indicate you will perform a non-rigid transfrom 38 cv::Mat transEstimate = estimateRigidTransform(transPoints[0],transPoints[1],0); 39 cv::Mat rotaEstimate = estimateRigidTransform(rotaPoints[0],rotaPoints[1],0); 40 #if 0 41 This program silce tests some points rigid transform Note :that we already know the Points position before & after transform 42 #endif 43 cv::Point2f a(230,220),b(270,220),c(270,280),d(230,280); 44 cv::Point2f Ta(220,270),Tb(220,230),Tc(280,230),Td(280,270); 45 knowPoint[0].push_back(a), knowPoint[1].push_back(Ta); 46 knowPoint[0].push_back(b), knowPoint[1].push_back(Tb); 47 knowPoint[0].push_back(c), knowPoint[1].push_back(Tc); 48 knowPoint[0].push_back(d), knowPoint[1].push_back(Td); 49 cv::Mat pointEstimate = estimateRigidTransform(knowPoint[0],knowPoint[1],0); 50 std::cout << "pointEstimate : \n" << pointEstimate << std::endl; std::cout << "transEstimate : \n" << transEstimate << std::endl; std::cout << 51 "rotaEstimate : \n" << rotaEstimate << std::endl; std::cout << "Test: before transform the center is " << refPose_x <<" "<< refPose_y << std::endl; refPose_x = transEstimate.at 52 (0)* refPose_x + transEstimate.at 53 (1)* refPose_y + transEstimate.at 54 (2); refPose_y = transEstimate.at 55 (3)* refPose_x + transEstimate.at 56 (4)* refPose_y + transEstimate.at 57 (5); 58 bool displayKeypoints = false; 59 if(displayKeypoints) 60 { 61 for(auto c:transPoints[0]) 62 { 63 std::cout << c << std::endl; circle(preTransGray,c,2,cv::Scalar(0,15,255),-1); 64 } 65 std::cout << "========================== " << std::endl; 66 for(auto c:transPoints[1]) 67 { 68 std::cout << c << std::endl; circle(curTransGray,c,2,cv::Scalar(0,97,25),-1); 69 } 70 } 71 cv::imshow("preGray",preTransGray); 72 cv::waitKey(0); 73 cv::imshow("vertGray",curTransGray); 74 cv::waitKey(0); 75 std::cout << "Test after transform the center is " << refPose_x << " "<< refPose_y << std::endl; 76 } 77 78 #endif