一杯清酒邀明月
天下本无事,庸人扰之而烦耳。

最近发现网上关于 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

 

posted on 2021-07-20 15:25  一杯清酒邀明月  阅读(3034)  评论(0编辑  收藏  举报