OpenCV 函數 estimateRigidTransform 使用心得


最近發現網上關於 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

 


免責聲明!

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



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