posetracker.cpp
Go to the documentation of this file.
1 #include <opencv2/calib3d/calib3d.hpp>
2 #include "posetracker.h"
3 #ifndef OPENCV_VERSION_3
4 #include "levmarq.h"
5 #endif
6 #include "ippe.h"
7 
8 namespace aruco{
9 
10 cv::Mat impl__aruco_getRTMatrix(const cv::Mat &_rvec,const cv::Mat &_tvec){
11  if (_rvec.empty())return cv::Mat();
12  cv::Mat Matrix=cv::Mat::eye ( 4,4,CV_32FC1 );
13  cv::Mat R33=cv::Mat ( Matrix,cv::Rect ( 0,0,3,3 ) );
14  cv::Rodrigues ( _rvec,R33 );
15  for ( int i=0; i<3; i++ ) Matrix.at<float> ( i,3 ) =_tvec.ptr<float> ( 0 ) [i];
16  return Matrix;
17 
18 }
19 void impl__aruco_getRTfromMatrix44 ( const cv::Mat &M, cv::Mat &R,cv::Mat &T ) {
20 
21  assert ( M.cols==M.rows && M.cols==4 );
22  assert ( M.type() ==CV_32F || M.type() ==CV_64F );
23 //extract the rotation part
24  cv::Mat r33=cv::Mat ( M,cv::Rect ( 0,0,3,3 ) );
25  cv::SVD svd ( r33 );
26  cv::Mat Rpure=svd.u*svd.vt;
27  cv::Rodrigues ( Rpure,R );
28  T.create ( 1,3,M.type() );
29  if ( M.type() ==CV_32F )
30  for ( int i=0; i<3; i++ )
31  T.ptr<float> ( 0 ) [i]=M.at<float> ( i,3 );
32  else
33  for ( int i=0; i<3; i++ )
34  T.ptr<double> ( 0 ) [i]=M.at<double> ( i,3 );
35 }
36 #ifndef OPENCV_VERSION_3
37 
38 template<typename T>
39 double __aruco_solve_pnp(const std::vector<cv::Point3f> & p3d,const std::vector<cv::Point2f> & p2d,const cv::Mat &cam_matrix,const cv::Mat &dist,cv::Mat &r_io,cv::Mat &t_io){
40 
41  assert(r_io.type()==CV_32F);
42  assert(t_io.type()==CV_32F);
43  assert(t_io.total()==r_io.total());
44  assert(t_io.total()==3);
45  auto toSol=[](const cv::Mat &r,const cv::Mat &t){
46  typename LevMarq<T>::eVector sol(6);
47  for(int i=0;i<3;i++){
48  sol(i)=r.ptr<float>(0)[i];
49  sol(i+3)=t.ptr<float>(0)[i];
50  }
51  return sol;
52  };
53  auto fromSol=[](const typename LevMarq<T>::eVector &sol,cv::Mat &r,cv::Mat &t){
54  r.create(1,3,CV_32F);
55  t.create(1,3,CV_32F);
56  for(int i=0;i<3;i++){
57  r.ptr<float>(0)[i]=sol(i);
58  t.ptr<float>(0)[i]=sol(i+3);
59  }
60  };
61 
62  cv::Mat Jacb;
63  auto err_f= [&](const typename LevMarq<T>::eVector &sol,typename LevMarq<T>::eVector &err){
64  std::vector<cv::Point2f> p2d_rej;
65  cv::Mat r,t;
66  fromSol(sol,r,t);
67  cv::projectPoints(p3d,r,t,cam_matrix,dist,p2d_rej,Jacb);
68  err.resize(p3d.size()*2);
69  int err_idx=0;
70  for(size_t i=0;i<p3d.size();i++){
71  err(err_idx++)=p2d_rej[i].x-p2d[i].x;
72  err(err_idx++)=p2d_rej[i].y-p2d[i].y;
73  }
74  };
75  auto jac_f=[&](const typename LevMarq<T>::eVector &sol,Eigen::Matrix<T,Eigen::Dynamic,Eigen::Dynamic> &J){
76  (void)(sol);
77  J.resize(p3d.size()*2,6);
78  for(size_t i=0;i<p3d.size()*2;i++){
79  double *jacb=Jacb.ptr<double>(i);
80  for(int j=0;j<6;j++) J(i,j)=jacb[j];
81  }
82  };
83 
84  LevMarq<T> solver;
85  solver.setParams(100,0.01,0.01);
86  // solver.verbose()=true;
87  typename LevMarq<T>::eVector sol=toSol(r_io,t_io);
88  auto err=solver.solve(sol,err_f,jac_f);
89 
90  fromSol(sol,r_io,t_io);
91  return err;
92 
93 }
94 
95 double __aruco_solve_pnp(const std::vector<cv::Point3f> & p3d,const std::vector<cv::Point2f> & p2d,const cv::Mat &cam_matrix,const cv::Mat &dist,cv::Mat &r_io,cv::Mat &t_io){
96 #ifdef DOUBLE_PRECISION_PNP
97  return __aruco_solve_pnp<double>(p3d,p2d,cam_matrix,dist,r_io,t_io);
98 #else
99  return __aruco_solve_pnp<float>(p3d,p2d,cam_matrix,dist,r_io,t_io);
100 #endif
101 }
102 
103 #endif
104 bool MarkerPoseTracker::estimatePose( Marker &m,const CameraParameters &_cam_params,float _msize,float minerrorRatio){
105 
106 
107  if (_rvec.empty()){//if no previous data, use from scratch
108  cv::Mat rv,tv;
109  auto solutions=IPPE::solvePnP_(Marker::get3DPoints(_msize),m,_cam_params.CameraMatrix,_cam_params.Distorsion);
110  double errorRatio=solutions[1].second/solutions[0].second;
111  if (errorRatio<minerrorRatio) return false;//is te error ratio big enough
112  cv::solvePnP(Marker::get3DPoints(_msize),m,_cam_params.CameraMatrix,_cam_params.Distorsion,rv,tv);
113  rv.convertTo(_rvec,CV_32F);
114  tv.convertTo(_tvec,CV_32F);
115  impl__aruco_getRTfromMatrix44(solutions[0].first,rv,tv);
116  }
117  else{
118 #ifdef OPENCV_VERSION_3
119  cv::solvePnP(Marker::get3DPoints(_msize),m,_cam_params.CameraMatrix,_cam_params.Distorsion,_rvec,_tvec,true);
120 #else //solve Pnp does not work properly in OpenCV2
121  __aruco_solve_pnp(Marker::get3DPoints(_msize),m,_cam_params.CameraMatrix,_cam_params.Distorsion,_rvec,_tvec);
122 #endif
123 
124  }
125 
126  _rvec.copyTo(m.Rvec);
127  _tvec.copyTo(m.Tvec);
128  m.ssize=_msize;
129  return true;
130 }
131 
132 
133 
134 
136  _isValid=false;
137 }
138 
139 void MarkerMapPoseTracker::setParams(const CameraParameters &cam_params,const MarkerMap &msconf, float markerSize)throw(cv::Exception)
140 {
141 
142  _msconf=msconf;
143  _cam_params=cam_params;
144  if (!cam_params.isValid())
145  throw cv::Exception(9001, "Invalid camera parameters", "MarkerMapPoseTracker::setParams", __FILE__, __LINE__);
146  if (_msconf.mInfoType==MarkerMap::PIX && markerSize<=0)
147  throw cv::Exception(9001, "You should indicate the markersize sice the MarkerMap is in pixels", "MarkerMapPoseTracker::setParams", __FILE__, __LINE__);
148  if (_msconf.mInfoType==MarkerMap::NONE)
149  throw cv::Exception(9001, "Invlaid MarkerMap", "MarkerMapPoseTracker::setParams", __FILE__, __LINE__);
150  if (_msconf.mInfoType==MarkerMap::PIX)
151  _msconf=_msconf.convertToMeters(markerSize);
152 
153  _isValid=true;
154 
155  //create a map for fast access to elements
156  _map_mm.clear();
157  for(auto m:msconf)
158  _map_mm.insert(make_pair(m.id,m));
159 }
160 
161 bool MarkerMapPoseTracker::estimatePose(const vector<Marker> &v_m){
162 
163 
164  vector<cv::Point2f> p2d;
165  vector<cv::Point3f> p3d;
166  for(auto marker:v_m){
167  if ( _map_mm.find(marker.id)!=_map_mm.end()){//is the marker part of the map?
168  for(auto p:marker) p2d.push_back(p);
169  for(auto p:_map_mm[marker.id]) p3d.push_back(p);
170  }
171  }
172 
173  if (p2d.size()==0){//no points in the vector
174  _rvec=cv::Mat();_tvec=cv::Mat();return false;
175  }
176  else{
177  if(_rvec.empty()){//requires ransac since past pose is unknown
178  cv::Mat rv,tv;
179  cv::solvePnPRansac(p3d,p2d,_cam_params.CameraMatrix,_cam_params.Distorsion,rv,tv);
180 
181 
182  assert(tv.type()==CV_64F);
183  if (_rvec.rows==1) {
184  rv.convertTo(_rvec,CV_32F);
185  tv.convertTo(_tvec,CV_32F);
186  }
187  else{
188 
189  _rvec.create(1,3,CV_32F);
190  _tvec.create(1,3,CV_32F);
191  for(int i=0;i<3;i++){
192  _rvec.ptr<float>(0)[i]=rv.at<double>(i,0);
193  _tvec.ptr<float>(0)[i]=tv.at<double>(i,0);
194  }
195  }
196  }
197 
198 #ifdef OPENCV_VERSION_3
199  cv::solvePnP(p3d,p2d,_cam_params.CameraMatrix,_cam_params.Distorsion,_rvec,_tvec,true);
200 
201 #else //SolvePnP does not work properly in opencv 2
202  __aruco_solve_pnp(p3d,p2d,_cam_params.CameraMatrix,_cam_params.Distorsion,_rvec,_tvec);
203 
204 #endif
205 
206  return true;
207  }
208 }
209 
212 }
213 
214 
217 }
218 }
cv::Mat getRTMatrix() const
std::vector< cv::Mat > solvePnP(const std::vector< cv::Point3f > &objPoints, const std::vector< cv::Point2f > &imgPoints, cv::InputArray cameraMatrix, cv::InputArray distCoeffs)
Definition: ippe.cpp:55
void impl__aruco_getRTfromMatrix44(const cv::Mat &M, cv::Mat &R, cv::Mat &T)
Definition: posetracker.cpp:19
static vector< cv::Point3f > get3DPoints(float msize)
Definition: marker.cpp:285
double __aruco_solve_pnp(const std::vector< cv::Point3f > &p3d, const std::vector< cv::Point2f > &p2d, const cv::Mat &cam_matrix, const cv::Mat &dist, cv::Mat &r_io, cv::Mat &t_io)
Definition: posetracker.cpp:39
bool estimatePose(Marker &m, const CameraParameters &cam_params, float markerSize, float minErrorRatio=4)
estimatePose
cv::Mat Rvec
Definition: marker.h:49
cv::Mat getRTMatrix() const
bool estimatePose(const vector< Marker > &v_m)
void setParams(int maxIters, double minError, double min_step_error_diff=0, double tau=1, double der_epsilon=1e-3)
setParams
Definition: levmarq.h:160
void setParams(const CameraParameters &cam_params, const MarkerMap &msconf, float markerSize=-1)
cv::Mat impl__aruco_getRTMatrix(const cv::Mat &_rvec, const cv::Mat &_tvec)
Definition: posetracker.cpp:10
This class represents a marker. It is a vector of the fours corners ot the marker.
Definition: marker.h:42
Parameters of the camera.
float ssize
Definition: marker.h:47
std::vector< std::pair< cv::Mat, double > > solvePnP_(const std::vector< cv::Point3f > &objPoints, const std::vector< cv::Point2f > &imgPoints, cv::InputArray cameraMatrix, cv::InputArray distCoeffs)
Definition: ippe.cpp:67
cv::Mat Tvec
Definition: marker.h:49
double solve(eVector &z, F_z_x, F_z_J)
solve non linear minimization problem ||F(z)||, where F(z)=f(z) f(z)^t
Definition: levmarq.h:270
This class defines a set of markers whose locations are attached to a common reference system...
Definition: markermap.h:71


tuw_aruco
Author(s): Lukas Pfeifhofer
autogenerated on Mon Jun 10 2019 15:40:55