Recognizer3D.cpp
Go to the documentation of this file.
00001 
00002 #include <ros/ros.h>
00003 #include <opencv2/core/core.hpp>
00004 
00005 #include <blort/Recognizer3D/Recognizer3D.h>
00006 #include <blort/Recognizer3D/SDraw.hh>
00007 #include <blort/Recognizer3D/cvgeometry.h>
00008 #include <blort/TomGine/tgModelLoader.h>
00009 #include <blort/TomGine/tgCollission.h>
00010 #include <blort/blort/pal_util.h>
00011 
00012 using namespace blortRecognizer;
00013 
00014 CameraParameter::CameraParameter(const sensor_msgs::CameraInfo &cam_info)
00015 {
00016   w = cam_info.width;
00017   h = cam_info.height;
00018   fx =cam_info.K.at(0);
00019   cx = cam_info.K.at(2);
00020   fy = cam_info.K.at(4);
00021   cy = cam_info.K.at(5);
00022   if (!cam_info.D.empty())
00023   {
00024     k1 = cam_info.D.at(0);
00025     k2 = cam_info.D.at(1);
00026     k3 = cam_info.D.at(4);
00027     p1 = cam_info.D.at(2);
00028     p2 = cam_info.D.at(3);
00029   }
00030   else
00031   {
00032     k1 = 0.0;
00033     k2 = 0.0;
00034     k3 = 0.0;
00035     p1 = 0.0;
00036     p2 = 0.0;
00037   }
00038 }
00039 
00040 void Recognizer3D::Convert(P::PoseCv& p1, TomGine::tgPose& p2){
00041 
00042   mat3 cR;
00043   vec3 ct;
00044 
00045   cR[0] = cvmGet(p1.R,0,0); cR[3] = cvmGet(p1.R,0,1); cR[6] = cvmGet(p1.R,0,2);
00046   cR[1] = cvmGet(p1.R,1,0); cR[4] = cvmGet(p1.R,1,1); cR[7] = cvmGet(p1.R,1,2);
00047   cR[2] = cvmGet(p1.R,2,0); cR[5] = cvmGet(p1.R,2,1); cR[8] = cvmGet(p1.R,2,2);
00048 
00049   ct.x = cvmGet(p1.t,0,0);
00050   ct.y = cvmGet(p1.t,1,0);
00051   ct.z = cvmGet(p1.t,2,0);
00052 
00053   p2.SetPose(cR,ct);
00054 }
00055 
00056 Recognizer3D::Recognizer3D(const blortRecognizer::CameraParameter& camParam,
00057                            std::string config_root, bool display, bool training)
00058 {
00059   do_undistort = true;
00060   this->config_root = config_root;
00061   pIntrinsicDistort = cvCreateMat(3,3, CV_64FC1);
00062   pDistortion = cvCreateMat(1,4, CV_64FC1);
00063   C = cvCreateMat(3,3, CV_32F);
00064 
00065   m_cp = camParam;
00066 
00067   cvmSet(pIntrinsicDistort, 0, 0, camParam.fx);
00068   cvmSet(pIntrinsicDistort, 0, 1, 0.);
00069   cvmSet(pIntrinsicDistort, 0, 2, camParam.cx);
00070   cvmSet(pIntrinsicDistort, 1, 0, 0.);
00071   cvmSet(pIntrinsicDistort, 1, 1, camParam.fy);
00072   cvmSet(pIntrinsicDistort, 1, 2, camParam.cy);
00073   cvmSet(pIntrinsicDistort, 2, 0, 0.);
00074   cvmSet(pIntrinsicDistort, 2, 1, 0.);
00075   cvmSet(pIntrinsicDistort, 2, 2, 1.);
00076 
00077   cvmSet(pDistortion, 0, 0, camParam.k1);
00078   cvmSet(pDistortion, 0, 1, camParam.k2);
00079   cvmSet(pDistortion, 0, 2, camParam.k3);
00080   cvmSet(pDistortion, 0, 3, 0.0);
00081 
00082   //camera matrix for undistorted images
00083   cvmSet(C, 0, 0, camParam.fx);
00084   cvmSet(C, 0, 1, 0.);
00085   cvmSet(C, 0, 2, camParam.cx);
00086   cvmSet(C, 1, 0, 0.);
00087   cvmSet(C, 1, 1, camParam.fy);
00088   cvmSet(C, 1, 2, camParam.cy);
00089   cvmSet(C, 2, 0, 0.);
00090   cvmSet(C, 2, 1, 0.);
00091   cvmSet(C, 2, 2, 1.);
00092 
00093   m_detect.SetCameraParameter(C);
00094 
00095   pMapX  = cvCreateMat (camParam.h,  camParam.w, CV_32FC1 );
00096   pMapY  = cvCreateMat (camParam.h,  camParam.w, CV_32FC1 );
00097   cvInitUndistortMapExact(pIntrinsicDistort, pDistortion, pMapX,  pMapY);
00098 
00099   m_gauss_kernel = 5;
00100   m_gauss_dev = 1.5;
00101 
00102   m_display = display;
00103 
00104   m_model_loaded = false;
00105   if(training)
00106   {
00107     initTrainingModel();
00108   }
00109 
00110   //    // create and initialize opencv-based 3D detector core
00111   //    cv_detect = cv::Ptr<pal_blort::CvDetect3D>(new pal_blort::CvDetect3D("FAST","SIFT","FlannBased"));
00112   //    cv_detect->setCameraMatrix(cv::Mat(pIntrinsicDistort, true));
00113   //    cv::Mat dist_coeffs(1, 5, CV_32FC1);
00114   //    dist_coeffs.at<float>(0,0) = camParam.k1;
00115   //    dist_coeffs.at<float>(0,1) = camParam.k2;
00116   //    dist_coeffs.at<float>(0,2) = camParam.p1;
00117   //    dist_coeffs.at<float>(0,3) = camParam.p2;
00118   //    dist_coeffs.at<float>(0,4) = camParam.k3;
00119   //    cv_detect->setDistCoeffs(dist_coeffs);
00120 }
00121 
00122 Recognizer3D::~Recognizer3D()
00123 {
00124   cvReleaseMat(&pIntrinsicDistort);
00125   cvReleaseMat(&pDistortion);
00126   cvReleaseMat(&C);
00127   cvReleaseMat(&pMapX);
00128   cvReleaseMat(&pMapY);
00129 }
00130 
00131 void Recognizer3D::setCameraParameter(const blortRecognizer::CameraParameter& camParam)
00132 {
00133   m_cp = camParam;
00134 
00135   cvmSet(pIntrinsicDistort, 0, 0, camParam.fx);
00136   cvmSet(pIntrinsicDistort, 0, 1, 0.);
00137   cvmSet(pIntrinsicDistort, 0, 2, camParam.cx);
00138   cvmSet(pIntrinsicDistort, 1, 0, 0.);
00139   cvmSet(pIntrinsicDistort, 1, 1, camParam.fy);
00140   cvmSet(pIntrinsicDistort, 1, 2, camParam.cy);
00141   cvmSet(pIntrinsicDistort, 2, 0, 0.);
00142   cvmSet(pIntrinsicDistort, 2, 1, 0.);
00143   cvmSet(pIntrinsicDistort, 2, 2, 1.);
00144 
00145   cvmSet(pDistortion, 0, 0, camParam.k1);
00146   cvmSet(pDistortion, 0, 1, camParam.k2);
00147   cvmSet(pDistortion, 0, 2, camParam.k3);
00148   cvmSet(pDistortion, 0, 3, 0.0);
00149 
00150   //camera matrix for undistorted images
00151   cvmSet(C, 0, 0, camParam.fx);
00152   cvmSet(C, 0, 1, 0.);
00153   cvmSet(C, 0, 2, camParam.cx);
00154   cvmSet(C, 1, 0, 0.);
00155   cvmSet(C, 1, 1, camParam.fy);
00156   cvmSet(C, 1, 2, camParam.cy);
00157   cvmSet(C, 2, 0, 0.);
00158   cvmSet(C, 2, 1, 0.);
00159   cvmSet(C, 2, 2, 1.);
00160 
00161   m_detect.SetCameraParameter(C);
00162 
00163   pMapX  = cvCreateMat (camParam.h,  camParam.w, CV_32FC1 );
00164   pMapY  = cvCreateMat (camParam.h,  camParam.w, CV_32FC1 );
00165   cvInitUndistortMapExact(pIntrinsicDistort, pDistortion, pMapX,  pMapY);
00166 }
00167 
00168 bool Recognizer3D::recognize(IplImage* tFrame, std::map<std::string, boost::shared_ptr<TomGine::tgPose> > & poses,
00169                              std::map<std::string, double> & confs)
00170 {
00171   // this select map should be a member containing the list of names, or the list of names should be a member
00172   std::map<std::string, bool> select;
00173   return recognize(tFrame, poses, confs, select);
00174 }
00175 
00176 bool Recognizer3D::recognize(IplImage* tFrame, std::map<std::string, boost::shared_ptr<TomGine::tgPose> > & poses,
00177                              std::map<std::string, double> & confs, const std::map<std::string, bool> & select)
00178 {
00179   P::PoseCv cvPose;
00180   bool detected = false;
00181 
00182   if(!m_model_loaded || m_sift_models[0]->codebook.Empty())
00183   {
00184     ROS_DEBUG("[Recognizer3D::recognize] Warning: no sift points in codebook of object (did you load the model before?) -- Possible GPU library error.");
00185     return false;
00186   }
00187 
00188   IplImage* tImg = 0;
00189   IplImage* grey = 0;
00190 
00191   tImg = cvCreateImage( cvGetSize ( tFrame ), 8, 3 );
00192   grey = cvCreateImage( cvGetSize ( tFrame ), 8, 1 );
00193 
00194   // undistort
00195   double ticksBefore = cv::getTickCount();
00196   if(do_undistort)
00197   {
00198     cvRemap(tFrame, tImg, pMapX, pMapY);
00199   }else{
00200     cvCopy(tFrame, tImg);
00201   }
00202   ROS_INFO("Recognizer3D::recognize: undistort time: %.01f ms", 1000*(cv::getTickCount() - ticksBefore)/cv::getTickFrequency());
00203 
00204 
00205   // convert to gray scale image
00206   cvConvertImage(tImg, grey);
00207 
00208   // extract sifts from current image
00209   ticksBefore = cv::getTickCount();
00210   sift.Operate(grey, m_image_keys);
00211   ROS_INFO("Recognizer3D::recognize: extract sift time: %.01f ms", 1000*(cv::getTickCount() - ticksBefore)/cv::getTickFrequency());
00212 
00213   m_detect.SetDebugImage(tImg);
00214 
00215   if(m_display)
00216   {
00217     sift.Draw(tImg, m_image_keys);
00218   }
00219 
00220   //EXPERIMENTAL
00221   //cv_detect->detect(cv::Mat(grey, true), m_sift_model);
00222   ticksBefore = cv::getTickCount();
00223   for(size_t i = 0; i < m_sift_models.size(); ++i)
00224   {
00225     bool detectResult = false;
00226     // if there are objects selected, handle only those, if not, look for all
00227     if((select.count(m_sift_models[i]->file_name) && select.at(m_sift_models[i]->file_name)) || select.empty()) // ABSOLUTE FILENAME FULLPATH
00228     {
00229       ROS_ERROR_STREAM("Recognizer3D::recognize: filename: " << m_sift_models[i]->file_name);
00230       detectResult = m_detect.Detect(m_image_keys, *m_sift_models[i]);
00231 
00232       if(detectResult)
00233       {
00234         if(m_sift_models[i]->conf > 0.03)
00235         {
00236           confs[m_sift_models[i]->file_name] = m_sift_models[i]->conf;
00237           if(m_display)
00238           {
00239             // object contours & features drawn with green
00240             P::SDraw::DrawPoly(tImg, m_sift_models[i]->contour.v, CV_RGB(0,255,0),2);
00241             m_detect.DrawInlier(tImg, CV_RGB(0,255,0));
00242           }
00243           CopyPoseCv(m_sift_models[i]->pose, cvPose);
00244           Convert(cvPose, *poses[m_sift_models[i]->file_name]);
00245           ROS_DEBUG("[Recognizer3D::recognize] object found (conf: %f)\n", m_sift_models[i]->conf);
00246           detected = true;
00247         }
00248         else
00249         {
00250           if(m_display)
00251             // pose estimage object contours drawn with purple
00252             P::SDraw::DrawPoly(tImg, m_sift_models[i]->contour.v, CV_RGB(128,0,128),2);
00253 
00254           ROS_DEBUG("[Recognizer3D::recognize] No object (conf: %f)\n", m_sift_models[i]->conf);
00255         }
00256       }
00257       else
00258       {
00259         confs[m_sift_models[i]->file_name] = m_sift_models[i]->conf;
00260 
00261         if(m_display)
00262           P::SDraw::DrawPoly(tImg, m_sift_models[i]->contour.v, CV_RGB(128,0,128),2);
00263 
00264         ROS_DEBUG("[Recognizer3D::recognize] No object (conf: %f)\n", m_sift_models[i]->conf);
00265       }
00266     }
00267   }
00268   ROS_ERROR("Recognizer3D::recognize: %.01f ms\n", 1000*(cv::getTickCount() - ticksBefore)/cv::getTickFrequency());
00269 
00270   if(m_display)
00271   {
00272     display_image = cv::Mat(tImg, true);
00273   }
00274 
00275   cvReleaseImage(&tImg);
00276   cvReleaseImage(&grey);
00277 
00278   //EXPERIMENTAL
00279   //debug_image = cv_detect->getImage();
00280 
00281   return detected;
00282 }
00283 
00284 bool Recognizer3D::learnSifts(IplImage* tFrame, const TomGine::tgModel& m1, const TomGine::tgPose& pose)
00285 {       
00286   P::Array<P::KeypointDescriptor*> m_tmp_keys;
00287 
00288   mat3 R, Rt;
00289   vec3 t;
00290   TomGine::tgModel m2 = m1;
00291   m_lastsiftexlist.clear();
00292 
00293   // Transform model vertices to camera coordinats
00294   pose.GetPose(R,t);
00295   Rt = R.transpose();
00296   for(unsigned int i=0; i<m2.m_vertices.size(); i++)
00297   {
00298     m2.m_vertices[i].pos = (R * m2.m_vertices[i].pos) + t;
00299     m2.m_vertices[i].normal = R * m2.m_vertices[i].normal;
00300   }
00301 
00302   IplImage* tImg = 0;
00303   IplImage* grey = 0;
00304   float dcpfx = 1/m_cp.fx;
00305   float dcpfy = 1/m_cp.fy;
00306 
00307   tImg = cvCreateImage ( cvGetSize ( tFrame ), 8, 3 );
00308   grey = cvCreateImage ( cvGetSize ( tFrame ), 8, 1 );
00309 
00310   // undistort
00311   cvRemap(tFrame, tImg, pMapX, pMapY );
00312 
00313   // convert to gray scale image
00314   cvConvertImage(tImg, grey);
00315 
00316   //EXPERIMENTAL:
00317   //    cv::Mat descriptors;
00318   //    std::vector<cv::KeyPoint> keypoints;
00319   //    cv_detect->extract(cv::Mat(grey, true), descriptors, keypoints);
00320   //
00321   //    pal_blort::CvDetect3D::cvKeypoints2BlortKeyPoints(
00322   //            descriptors, keypoints, m_image_keys);
00323   // END OF EXPERIMENTAL
00324 
00325   sift.Operate(grey, m_image_keys);
00326 
00327   for(unsigned int i=0; i<m_image_keys.Size(); i++)
00328   {
00329     vec3 point, normal;
00330     std::vector<vec3> pl;               // point list
00331     std::vector<vec3> nl;               // normal list
00332     std::vector<double> zl; // z-value list (depth)
00333     float u,v,x,y;
00334 
00335     u = (float)m_image_keys[i]->p.x;
00336     v = (float)m_image_keys[i]->p.y;
00337     x = (u-m_cp.cx) * dcpfx;
00338     y = (v-m_cp.cy) * dcpfy;
00339 
00340     // Create ray from pixel
00341     TomGine::tgRay ray;
00342     ray.start = vec3(0.0f,0.0f,0.0f);
00343     ray.dir =  vec3(x,y,1.0f);
00344     ray.dir.normalize();
00345 
00346     if( TomGine::tgCollission::IntersectRayModel(pl, nl, zl, ray, m2)
00347         && !pl.empty()
00348         && !zl.empty())
00349     {
00350       // determine nearest intersection point
00351       unsigned int idx_min = 0;
00352       float z_min = zl[0];
00353       for(unsigned int idx=0; idx<zl.size(); idx++){
00354         if(zl[idx] < z_min){
00355           idx_min = idx;
00356           z_min = zl[idx];
00357         }
00358       }
00359 
00360       if(z_min > 0.0f){
00361         // Transform to object space
00362         point = (Rt * (pl[idx_min] - t));
00363         normal = (Rt * nl[idx_min]);
00364         vec3 r = (Rt * ray.dir) * zl[idx_min];
00365 
00366         Siftex s;
00367         s.pos = point;
00368         s.normal = normal;
00369         s.viewray = r;
00370 
00371         normal.normalize();
00372         r.normalize();
00373 
00374         if( (r * normal) < -0.1f)
00375         {
00376           // Save sift
00377           m_siftexlist.push_back(s);
00378           m_lastsiftexlist.push_back(s);
00379           m_image_keys[i]->SetPos(point.x, point.y, point.z);
00380           m_tmp_keys.PushBack(m_image_keys[i]);
00381         }
00382       }
00383     }
00384 
00385   }
00386 
00387   if(m_tmp_keys.Size() > 0)
00388   {
00389     m_sift_model_learner.AddToModel(m_tmp_keys, *m_sift_models[0]);
00390     ROS_INFO("[Recognizer3D::learnSifts] added %d sifts to model\n", m_tmp_keys.Size());
00391     m_model_loaded = true;
00392   }
00393 
00394   if(m_display){
00395     display_image = cv::Mat(tImg, true);
00396   }
00397 
00398   cvReleaseImage(&tImg);
00399   cvReleaseImage(&grey);
00400 
00401   return true;
00402 }
00403 
00404 bool Recognizer3D::loadModelFromFile(const std::string sift_file)
00405 {
00406   ROS_INFO("[Recognizer3D::loadModelFromFile] loading sift model from '%s'\n", sift_file.c_str());
00407   m_sift_models.push_back(boost::shared_ptr<P::Object3D>(new P::Object3D()));
00408   m_model_loaded = m_sift_model_learner.LoadModel(blort_ros::addRoot(sift_file, config_root), *m_sift_models.back());
00409   //EXPERIMENTAL
00410   //cv_detect->addCodeBook(m_sift_model);
00411   return true;
00412 }
00413 
00414 void Recognizer3D::initTrainingModel()
00415 {
00416   ROS_INFO("[Recognizer3D::initTrainingModel() creating an empty model for training");
00417   m_sift_models.push_back(boost::shared_ptr<P::Object3D>(new P::Object3D()));
00418 }
00419 
00420 bool Recognizer3D::saveModelToFile(const char* sift_file)
00421 {
00422   ROS_INFO("[Recognizer3D::saveModelToFile] saving sift model to '%s'\n", sift_file);
00423   m_sift_model_learner.SaveModel(blort_ros::addRoot(sift_file, config_root).c_str(), *m_sift_models[0]);
00424   return true;
00425 }
00426 
00427 void Recognizer3D::setNNThreshold(double nn_threshold)
00428 {
00429   m_detect.setNNThreshold(nn_threshold);
00430 }
00431 
00432 void Recognizer3D::setRansacNPointsToMatch(unsigned int n)
00433 {
00434   m_detect.setNPointsToMatch(n);
00435 }


blort
Author(s): Thomas Mörwald , Michael Zillich , Andreas Richtsfeld , Johann Prankl , Markus Vincze , Bence Magyar
autogenerated on Wed Aug 26 2015 15:24:12