ObjectDetectorMethod.cpp
Go to the documentation of this file.
00001 
00034 #include <opencv/cv.h>
00035 #include <vector>
00036 #include "ObjectDetectorMethod.h"
00037 #include "ObjectModel.h"
00038 #include "CameraBridge.h"
00039 
00040 #include "DUtilsCV.h"
00041 #include "DVision.h"
00042 #include "epnp.h"
00043 #include "NonLinearLS.h"
00044 #include <iostream>
00045 
00046 using namespace std;
00047 
00048 typedef DVision::PMVS::PLYFile::PLYPoint PLYPoint;
00049 
00050 // ---------------------------------------------------------------------------
00051 
00052 void ObjectDetectorMethod::calculatePose(const ObjectModel::Face &face,
00053   const std::vector<int> &face_indices, const DVision::SurfSet &scene_surfset,
00054   const std::vector<int> &scene_indices, const CameraBridge &camera,
00055   cv::Mat &cTo) const
00056 {
00057   const unsigned int N = face_indices.size();
00058   const cv::Mat &A = camera.GetIntrinsicParameters();
00059 
00060   epnp PnP;
00061   PnP.set_maximum_number_of_correspondences(N);
00062   PnP.set_internal_parameters(
00063     A.at<float>(0, 2), A.at<float>(1, 2), A.at<float>(0, 0), A.at<float>(1, 1));
00064 
00065   PnP.reset_correspondences();
00066 
00067   for(unsigned int i = 0; i < N; ++i)
00068   {
00069     const PLYPoint &p3d = face.plypoints[ face_indices[i] ];
00070     const cv::KeyPoint &kp = scene_surfset.keys[ scene_indices[i] ];
00071     PnP.add_correspondence(p3d.x, p3d.y, p3d.z, kp.pt.x, kp.pt.y);
00072   }
00073 
00074   double cRo_r[3][3], cto_r[3];
00075   PnP.compute_pose(cRo_r, cto_r);
00076 
00077 
00078   //Optimize pose
00079   OptimizationData dat;
00080   const cv::Mat &K=camera.GetIntrinsicParameters();
00081   const cv::Mat &dis=camera.GetDistortionParameters();
00082   dat.cal[0]=K.at<float>(0, 2);
00083   dat.cal[1]=K.at<float>(1, 2);
00084   dat.cal[2]=K.at<float>(0, 0);
00085   dat.cal[3]=K.at<float>(1, 1);
00086   dat.cal[4]=0.0;//dis.at<float>(0,0);
00087   dat.cal[5]=0.0;//dis.at<float>(0,1);
00088   dat.cam(0,0)=cRo_r[0][0]; dat.cam(0,1)=cRo_r[0][1]; dat.cam(0,2)=cRo_r[0][2];
00089   dat.cam(1,0)=cRo_r[1][0]; dat.cam(1,1)=cRo_r[1][1]; dat.cam(1,2)=cRo_r[1][2];
00090   dat.cam(2,0)=cRo_r[2][0]; dat.cam(2,1)=cRo_r[2][1]; dat.cam(2,2)=cRo_r[2][2];
00091 
00092   dat.cam(3,0)=0; dat.cam(3,1)=0; dat.cam(3,2)=0; dat.cam(3,3)=1;
00093   dat.cam(0,3)=cto_r[0];
00094   dat.cam(1,3)=cto_r[1];
00095   dat.cam(2,3)=cto_r[2];
00096 
00097   Vector2 pto2;
00098   Vector3 pto3;
00099   for(unsigned int i = 0; i < N; ++i)
00100   {
00101     const PLYPoint &p3d = face.plypoints[ face_indices[i] ];
00102     pto3[0]=p3d.x;
00103     pto3[1]=p3d.y;
00104     pto3[2]=p3d.z;
00105     dat.pto3D.push_back(pto3);
00106     const cv::KeyPoint &kp = scene_surfset.keys[ scene_indices[i] ];
00107     pto2[0]=kp.pt.x;
00108     pto2[1]=kp.pt.y;
00109     dat.pto2D.push_back(pto2);
00110   }
00111 
00112 
00113   //cerr<<"Tcm=["<<dat.cam<<"];\n";
00114   poseOptimization(dat);
00115 
00116   cRo_r[0][0]=dat.cam(0,0); cRo_r[0][1]=dat.cam(0,1); cRo_r[0][2]=dat.cam(0,2);
00117   cRo_r[1][0]=dat.cam(1,0); cRo_r[1][1]=dat.cam(1,1); cRo_r[1][2]=dat.cam(1,2);
00118   cRo_r[2][0]=dat.cam(2,0); cRo_r[2][1]=dat.cam(2,1); cRo_r[2][2]=dat.cam(2,2);
00119   cto_r[0]=dat.cam(0,3);cto_r[1]=dat.cam(1,3);cto_r[2]=dat.cam(2,3);
00120 
00121 
00122   cv::Mat cRo(3, 3, CV_64F, cRo_r);
00123   cv::Mat cto(3, 1, CV_64F, cto_r);
00124 
00125   cTo = DUtilsCV::Transformations::composeRt(cRo, cto);
00126 
00127   /* // CV version
00128   const unsigned int N = face_indices.size();
00129   cv::Mat objectPoints(N, 3, CV_32F);
00130   cv::Mat scenePoints(N, 2, CV_32F);
00131 
00132   for(unsigned int i = 0; i < N; ++i)
00133   {
00134     const PLYPoint &p3d = face.plypoints[ face_indices[i] ];
00135     const cv::KeyPoint &k2d = scene_surfset.keys[ scene_indices[i] ];
00136 
00137     objectPoints.at<float>(i, 0) = p3d.x;
00138     objectPoints.at<float>(i, 1) = p3d.y;
00139     objectPoints.at<float>(i, 2) = p3d.z;
00140 
00141     scenePoints.at<float>(i, 0) = k2d.pt.x;
00142     scenePoints.at<float>(i, 1) = k2d.pt.y;
00143   }
00144 
00145   cv::Mat cRo, cto;
00146   cv::solvePnP(objectPoints, scenePoints, camera.GetIntrinsicParameters(),
00147     cv::Mat::zeros(4,1, CV_32F), cRo, cto); // no distortion
00148 
00149   cTo = DUtilsCV::Transformations::composeRt(cRo, cto);
00150   */
00151 }
00152 
00153 // ---------------------------------------------------------------------------
00154 
00155 void ObjectDetectorMethod::convertPose(const cv::Mat &T,
00156   geometry_msgs::Pose &pose) const
00157 {
00158   if(T.type() == CV_64F)
00159   {
00160     pose.position.x = T.at<double>(0, 3) / T.at<double>(3, 3);
00161     pose.position.y = T.at<double>(1, 3) / T.at<double>(3, 3);
00162     pose.position.z = T.at<double>(2, 3) / T.at<double>(3, 3);
00163   }
00164   else
00165   {
00166     pose.position.x = T.at<float>(0, 3) / T.at<float>(3, 3);
00167     pose.position.y = T.at<float>(1, 3) / T.at<float>(3, 3);
00168     pose.position.z = T.at<float>(2, 3) / T.at<float>(3, 3);
00169   }
00170 
00171   // rot to quaternion (matlab)
00172   geometry_msgs::Quaternion &q = pose.orientation;
00173 
00174   double a[3][3]; // a contains the traspose of the rotation of T...
00175 
00176   if(T.type() == CV_64F)
00177   {
00178     for(int i = 0; i < 3; ++i)
00179       for(int j = 0; j < 3; ++j)
00180         a[i][j] = T.at<double>(j,i);
00181   }
00182   else
00183   {
00184     for(int i = 0; i < 3; ++i)
00185       for(int j = 0; j < 3; ++j)
00186         a[i][j] = T.at<float>(j,i);
00187   }
00188 
00189   double trace= a[0][0] + a[1][1] + a[2][2];
00190 
00191   if (trace > 0){
00192     double sqtrp1 = sqrt( trace + 1.0 );
00193 
00194     q.w = 0.5*sqtrp1;
00195     q.x = (a[1][2] - a[2][1])/(2.0*sqtrp1);
00196     q.y = (a[2][0] - a[0][2])/(2.0*sqtrp1);
00197     q.z = (a[0][1] - a[1][0])/(2.0*sqtrp1);
00198   }else{
00199     if ( (a[1][1] > a[0][0]) && (a[1][1] > a[2][2])){
00200       double sqdip1 = sqrt(a[1][1] - a[0][0] - a[2][2] + 1.0 );
00201 
00202       q.y = 0.5*sqdip1;
00203 
00204       if ( sqdip1 != 0 ) sqdip1 = 0.5/sqdip1;
00205 
00206       q.w = (a[2][0] - a[0][2])*sqdip1;
00207       q.x = (a[0][1] + a[1][0])*sqdip1;
00208       q.z = (a[1][2] + a[2][1])*sqdip1;
00209     }else if (a[2][2] > a[0][0]){
00210       double sqdip1 = sqrt(a[2][2] - a[0][0] - a[1][1] + 1.0 );
00211 
00212       q.z = 0.5*sqdip1;
00213 
00214       if ( sqdip1 != 0 ) sqdip1 = 0.5/sqdip1;
00215 
00216       q.w = (a[0][1] - a[1][0])*sqdip1;
00217       q.x = (a[2][0] + a[0][2])*sqdip1;
00218       q.y = (a[1][2] + a[2][1])*sqdip1;
00219     }else{
00220       double sqdip1 = sqrt(a[0][0] - a[1][1] - a[2][2] + 1.0 );
00221 
00222       q.x = 0.5*sqdip1;
00223 
00224       if ( sqdip1 != 0 ) sqdip1 = 0.5/sqdip1;
00225 
00226       q.w = (a[1][2] - a[2][1])*sqdip1;
00227       q.y = (a[0][1] + a[1][0])*sqdip1;
00228       q.z = (a[2][0] + a[0][2])*sqdip1;
00229     }
00230   }
00231 }
00232 
00233 // ---------------------------------------------------------------------------
00234 
00235 void ObjectDetectorMethod::convert3DPoints(const ObjectModel::Face &face,
00236   const std::vector<int> &indices,
00237   const cv::Mat &cTo,
00238   std::vector<geometry_msgs::Point> &points3d) const
00239 {
00240   assert(cTo.type() == CV_64F);
00241 
00242   cv::Mat oP(4, indices.size(), CV_64F);
00243 
00244   for(unsigned int i = 0; i < indices.size(); ++i)
00245   {
00246     const PLYPoint &ply = face.plypoints[indices[i]];
00247     oP.at<double>(0, i) = ply.x;
00248     oP.at<double>(1, i) = ply.y;
00249     oP.at<double>(2, i) = ply.z;
00250     oP.at<double>(3, i) = 1;
00251   }
00252 
00253   cv::Mat cP = cTo * oP;
00254   points3d.resize(indices.size());
00255 
00256   for(unsigned int i = 0; i < indices.size(); ++i)
00257   {
00258     points3d[i].x = cP.at<double>(0, i) / cP.at<double>(3, i);
00259     points3d[i].y = cP.at<double>(1, i) / cP.at<double>(3, i);
00260     points3d[i].z = cP.at<double>(2, i) / cP.at<double>(3, i);
00261 
00262   }
00263 
00264 }
00265 
00266 // ---------------------------------------------------------------------------
00267 
00268 void ObjectDetectorMethod::convert3DPoints(const ObjectModel::Face &face,
00269   const cv::Mat &cTo,
00270   std::vector<geometry_msgs::Point> &points3d) const
00271 {
00272   assert(cTo.type() == CV_64F);
00273 
00274   const unsigned int N = face.plypoints.size();
00275 
00276   cv::Mat oP(4, N, CV_64F);
00277 
00278   for(unsigned int i = 0; i < N; ++i)
00279   {
00280     const PLYPoint &ply = face.plypoints[i];
00281     oP.at<double>(0, i) = ply.x;
00282     oP.at<double>(1, i) = ply.y;
00283     oP.at<double>(2, i) = ply.z;
00284     oP.at<double>(3, i) = 1;
00285   }
00286 
00287   cv::Mat cP = cTo * oP;
00288 
00289   points3d.resize(N);
00290   for(unsigned int i = 0; i < N; ++i)
00291   {
00292     points3d[i].x = cP.at<double>(0, i) / cP.at<double>(3, i);
00293     points3d[i].y = cP.at<double>(1, i) / cP.at<double>(3, i);
00294     points3d[i].z = cP.at<double>(2, i) / cP.at<double>(3, i);
00295   }
00296 
00297 }
00298 
00299 // ---------------------------------------------------------------------------
00300 
00301 void ObjectDetectorMethod::get3DModelPoints(const ObjectModel::Face &face,
00302     std::vector<geometry_msgs::Point> &points3d) const
00303 {
00304   const unsigned int N = face.plypoints.size();
00305   points3d.resize(N);
00306 
00307   for(unsigned int i = 0; i < N; ++i)
00308   {
00309     const PLYPoint &ply = face.plypoints[i];
00310 
00311     points3d[i].x = ply.x;
00312     points3d[i].y = ply.y;
00313     points3d[i].z = ply.z;
00314   }
00315 }
00316 
00317 //---------------------------------------------------------------------------
00318 
00319 void ObjectDetectorMethod::get3DModelPoints(const ObjectModel::Face &face,
00320   const std::vector<int> &indices,
00321   std::vector<geometry_msgs::Point> &points3d) const
00322 {
00323   const unsigned int N =indices.size();
00324   points3d.resize(N);
00325 
00326   for(unsigned int i = 0; i < N ; ++i)
00327   {
00328     const PLYPoint &ply = face.plypoints[indices[i]];
00329     points3d[i].x = ply.x;
00330     points3d[i].y = ply.y;
00331     points3d[i].z = ply.z;
00332   }
00333 
00334 }
00335 
00336 // ---------------------------------------------------------------------------
00337 void ObjectDetectorMethod::getPointsOctave(const ObjectModel::Face &face,
00338     const std::vector<int> &indices,
00339     std::vector<int> &octave) const
00340 {
00341     const unsigned int N =indices.size();
00342     octave.clear();
00343     //octave.resize(N);
00344     for(unsigned int i = 0; i < N; ++i)
00345     {
00346        const cv::KeyPoint &kp = face.surf.keys[indices[i]];
00347        octave.push_back(kp.octave);
00348     }
00349 
00350 }
00351 // ---------------------------------------------------------------------------
00352 void ObjectDetectorMethod::getPointsOctave(const ObjectModel::Face &face,
00353     std::vector<int> &octave) const
00354 {
00355     for(unsigned int i = 0; i < face.surf.keys.size(); ++i)
00356     {
00357        const cv::KeyPoint &kp = face.surf.keys[i];
00358        octave.push_back(kp.octave);
00359     }
00360 
00361 }
00362 
00363 // ---------------------------------------------------------------------------
00364 
00365 void ObjectDetectorMethod::project2DPoints(const ObjectModel::Face &face,
00366   const cv::Mat &cTo, const CameraBridge &camera,
00367   std::vector<re_msgs::Pixel> &points2d) const
00368 {
00369   const unsigned int N = face.plypoints.size();
00370 
00371   cv::Mat oP(4, N, CV_64F);
00372 
00373   for(unsigned int i = 0; i < N; ++i)
00374   {
00375     const PLYPoint &ply = face.plypoints[i];
00376     oP.at<double>(0, i) = ply.x;
00377     oP.at<double>(1, i) = ply.y;
00378     oP.at<double>(2, i) = ply.z;
00379     oP.at<double>(3, i) = 1;
00380   }
00381 
00382   cv::Mat cP = cTo * oP;
00383 
00384   cv::Mat oP_4x3(oP.cols, 3, CV_32F);
00385   for(int c = 0; c < oP.cols; ++c)
00386     for(int r = 0; r < 3; ++r)
00387       oP_4x3.at<float>(c, r) = oP.at<double>(r, c) / oP.at<double>(3, c);
00388 
00389   cv::Mat cRo;
00390   cv::Mat cto(3, 1, CV_64F);
00391   DUtilsCV::Transformations::decomposeRt(cTo, cRo, cto);
00392 
00393   vector<cv::Point2f> cam_pixels;
00394   cv::projectPoints(oP_4x3, cRo, cto, camera.GetIntrinsicParameters(),
00395     cv::Mat::zeros(4,1,CV_32F), cam_pixels);
00396 
00397   // copy back
00398   points2d.resize(N);
00399   for(unsigned int i = 0; i < N; ++i)
00400   {
00401     points2d[i].x = cam_pixels[i].x;
00402     points2d[i].y = cam_pixels[i].y;
00403   }
00404 
00405 }
00406 // ---------------------------------------------------------------------------
00407 
00408 void ObjectDetectorMethod::project2DPoints(const ObjectModel::Face &face,
00409   const cv::Mat &cTo, const CameraBridge &camera,
00410   const std::vector<int> &indices,
00411   std::vector<re_msgs::Pixel> &points2d) const
00412 {
00413   const unsigned int N = indices.size();
00414 
00415   cv::Mat oP(4, N, CV_64F);
00416 
00417   for(unsigned int i = 0; i < N; ++i)
00418   {
00419     const PLYPoint &ply = face.plypoints[indices[i]];
00420     oP.at<double>(0, i) = ply.x;
00421     oP.at<double>(1, i) = ply.y;
00422     oP.at<double>(2, i) = ply.z;
00423     oP.at<double>(3, i) = 1;
00424   }
00425 
00426   cv::Mat cP = cTo * oP;
00427 
00428   cv::Mat oP_4x3(oP.cols, 3, CV_32F);
00429   for(int c = 0; c < oP.cols; ++c)
00430     for(int r = 0; r < 3; ++r)
00431       oP_4x3.at<float>(c, r) = oP.at<double>(r, c) / oP.at<double>(3, c);
00432 
00433   cv::Mat cRo;
00434   cv::Mat cto(3, 1, CV_64F);
00435   DUtilsCV::Transformations::decomposeRt(cTo, cRo, cto);
00436 
00437   vector<cv::Point2f> cam_pixels;
00438   cv::projectPoints(oP_4x3, cRo, cto, camera.GetIntrinsicParameters(),
00439     cv::Mat::zeros(4,1,CV_32F), cam_pixels);
00440 
00441   // copy back
00442   points2d.resize(N);
00443   for(unsigned int i = 0; i < N; ++i)
00444   {
00445     points2d[i].x = cam_pixels[i].x;
00446     points2d[i].y = cam_pixels[i].y;
00447   }
00448 
00449 }
00450 // ---------------------------------------------------------------------------
00451 
00452 void ObjectDetectorMethod::changeOrientation(const cv::Mat &cTo, cv::Mat &rTo)
00453   const
00454 {
00455   // rTo = rotz(-pi/2) * rotx(-pi/2) * cTo
00456   // --> rTo[0,:] =  cTo[2,:]
00457   //     rTo[1,:] = -cTo[0,:]
00458   //     rTo[2,:] = -cTo[1,:]
00459   //     rTo[3,:] =  cTo[3,:]
00460   if(cTo.type() == CV_32F)
00461   {
00462     rTo = (cv::Mat_<float>(4, 4) <<
00463       cTo.at<float>(2,0), cTo.at<float>(2,1), cTo.at<float>(2,2), cTo.at<float>(2,3),
00464       -cTo.at<float>(0,0), -cTo.at<float>(0,1), -cTo.at<float>(0,2), -cTo.at<float>(0,3),
00465       -cTo.at<float>(1,0), -cTo.at<float>(1,1), -cTo.at<float>(1,2), -cTo.at<float>(1,3),
00466       cTo.at<float>(3,0), cTo.at<float>(3,1), cTo.at<float>(3,2), cTo.at<float>(3,3));
00467   }
00468   else
00469   {
00470     rTo = (cv::Mat_<double>(4, 4) <<
00471       cTo.at<double>(2,0), cTo.at<double>(2,1), cTo.at<double>(2,2), cTo.at<double>(2,3),
00472      -cTo.at<double>(0,0), -cTo.at<double>(0,1), -cTo.at<double>(0,2), -cTo.at<double>(0,3),
00473      -cTo.at<double>(1,0), -cTo.at<double>(1,1), -cTo.at<double>(1,2), -cTo.at<double>(1,3),
00474       cTo.at<double>(3,0), cTo.at<double>(3,1), cTo.at<double>(3,2), cTo.at<double>(3,3));
00475   }
00476 }
00477 
00478 // ---------------------------------------------------------------------------
00479 
00480 


re_vision
Author(s): Dorian Galvez-Lopez
autogenerated on Sun Jan 5 2014 11:32:01