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


blort
Author(s): Michael Zillich, Thomas Mörwald, Johann Prankl, Andreas Richtsfeld, Bence Magyar (ROS version)
autogenerated on Thu Jan 2 2014 11:38:25