mapstitch.cpp
Go to the documentation of this file.
00001 
00025 #include "mapstitch.h"
00026 #include "math.h"
00027 //#include "highgui.h"
00028 
00029 
00030 
00031 
00032 StitchedMap::StitchedMap(Mat &img1, Mat &img2, int max_trans, int max_rotation, float max_pairwise_distance, cv::Mat oldTransform)
00033 {
00034   // load images, TODO: check that they're grayscale
00035   image1 = img1.clone();
00036   image2 = img2.clone();
00037   if(image1.size != image2.size)
00038       cv::resize(image2,image2,image1.size());
00039   works = true;
00040   // create feature detector set.
00041   OrbFeatureDetector detector;
00042   OrbDescriptorExtractor dexc;
00043   BFMatcher dematc(NORM_HAMMING, false);
00044 
00045   // 1. extract keypoint          s
00046   detector.detect(image1, kpv1);
00047   detector.detect(image2, kpv2);
00048 
00049   // 2. extract descriptors
00050   dexc.compute(image1, kpv1, dscv1);
00051   dexc.compute(image2, kpv2, dscv2);
00052 
00053   // 3. match keypoints
00054   if(kpv1.size() == 0|| kpv2.size() == 0)
00055   {
00056       ROS_WARN("No KPV");
00057       works = false;
00058       return;
00059   }
00060 //  ROS_INFO("Kpv1:%i entries\t Kpv2:%i entries",kpv1.size(),kpv2.size());
00061   dematc.match(dscv1, dscv2, matches);
00062 
00063   // 4. find matching point pairs with same distance in both images
00064   for (size_t i=0; i<matches.size(); i++) {
00065     KeyPoint a1 = kpv1[matches[i].queryIdx],
00066              b1 = kpv2[matches[i].trainIdx];
00067 
00068     if (matches[i].distance > 30)
00069       continue;
00070 
00071     for (size_t j=0; j<matches.size(); j++) {
00072       KeyPoint a2 = kpv1[matches[j].queryIdx],
00073                b2 = kpv2[matches[j].trainIdx];
00074 
00075       if (matches[j].distance > 30)
00076         continue;
00077 
00078       if ( fabs(norm(a1.pt-a2.pt) - norm(b1.pt-b2.pt)) > max_pairwise_distance ||
00079            fabs(norm(a1.pt-a2.pt) - norm(b1.pt-b2.pt)) == 0)
00080         continue;
00081 
00082 
00083       coord1.push_back(a1.pt);
00084       coord1.push_back(a2.pt);
00085       coord2.push_back(b1.pt);
00086       coord2.push_back(b2.pt);
00087 
00088 
00089       fil1.push_back(a1);
00090       fil1.push_back(a2);
00091       fil2.push_back(b1);
00092       fil2.push_back(b2);
00093     }
00094   }
00095 
00096    // cv::imwrite("img1.pgm",image1);
00097    // cv::imwrite("img2.pgm",image2);
00098   // 5. find homography
00099  // ROS_INFO("Found %i matches",matches.size());
00100   if(coord1.size() < 1)
00101   {
00102       ROS_WARN("Problem by transforming map,this migth just an start up problem \n Coord1:%lu",coord1.size());
00103       works = false;
00104       return;
00105   }
00106 
00107   ROS_DEBUG("Compute estimateRigid");
00108   H = estimateRigidTransform(coord2, coord1,false);
00109   if(H.empty())
00110   {
00111       ROS_WARN("H contain no data, cannot find valid transformation");
00112       works = false;
00113       return;
00114   }
00115   //ROS_DEBUG("H: size:%lu|empty:%i",H.size,H.empty());
00116 
00117   rotation = 180./M_PI*atan2(H.at<double>(0,1),H.at<double>(1,1));
00118   transx   = H.at<double>(0,2);
00119   transy   = H.at<double>(1,2);
00120   scalex   = sqrt(pow(H.at<double>(0,0),2)+pow(H.at<double>(0,1),2));
00121   scaley   = sqrt(pow(H.at<double>(1,0),2)+pow(H.at<double>(1,1),2));
00122   ROS_DEBUG("H: transx:%f|transy%f|scalex:%f,scaley:%f|rotation:%f",transx,transy,scalex,scaley,rotation);
00123   //first_x_trans = transx;
00124   //first_y_trans = transy;
00125   float scale_change = 0.05;
00126 
00127   if(scalex > 1 + scale_change || scaley > 1 + scale_change)
00128   {
00129       ROS_WARN("Map should not scale change is to lagre");
00130       works = false;
00131       return;
00132   }
00133   if(scalex < 1 - scale_change|| scaley < 1 - scale_change)
00134   {
00135       ROS_WARN("Map should not scale change is to small");
00136       works = false;
00137       return;
00138   }
00139   if(max_trans != -1)
00140   {
00141       if(transx > max_trans || transy > max_trans)
00142       {
00143           ROS_WARN("Map should not trans so strong");
00144           works = false;
00145           return;
00146       }
00147   }
00148   if(max_rotation != -1)
00149   {
00150       if(rotation > max_rotation || rotation < -1 * max_rotation)
00151       {
00152           ROS_WARN("Map should not rotate so strong");
00153           works = false;
00154           return;
00155       }
00156   }
00157   cur_trans = H;
00158   ROS_DEBUG("Finished estimateRigid");
00159   //evaluade transformation
00160   //evaluate
00161   if(works)
00162   {
00163       Mat tmp (image2.size(),image2.type());
00164       Mat thr;
00165 
00166       Mat image(image2.size(), image2.type());
00167       warpAffine(image2,image,H,image.size());
00168       addWeighted(image,.5,image1,.5,0.0,image);
00169 
00170       warpAffine(image2,tmp,H,image2.size());
00171       addWeighted(tmp,.5,image1,.5,0.0,image);
00172       //cvtColor(image1,tmp,CV_BGR2GRAY);
00173       threshold(tmp,thr,0,255,THRESH_BINARY);
00174       Mat K=(Mat_<uchar>(5,5)<<   0,  0,  1,  0,  0,\
00175                                      0,  0,  1,  0,  0,\
00176                                      1,  1,  1,  1,  1,\
00177                                      0,  0,  1,  0,  0,\
00178                                      0,  0,  1,  0,  0);
00179 
00180       erode(thr,thr,K,Point(-1,-1),1,BORDER_CONSTANT);
00181          vector< vector <Point> > contours; // Vector for storing contour
00182          vector< Vec4i > hierarchy;
00183          findContours( thr, contours, hierarchy,CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE );
00184          for( int i = 0; i< contours.size(); i++ )
00185          {
00186             Rect r= boundingRect(contours[i]);
00187             rects2.push_back(r);
00188             rectangle(tmp,Point(r.x,r.y), Point(r.x+r.width,r.y+r.height), Scalar(0,0,255),2,8,0);
00189           }//Opened contour
00190 
00191          Mat thr1;
00192          //cvtColor(image1,tmp,CV_BGR2GRAY);
00193          threshold(image1,thr1,0,255,THRESH_BINARY);
00194          erode(thr1,thr1,K,Point(-1,-1),1,BORDER_CONSTANT);
00195             vector< vector <Point> > contours1; // Vector for storing contour
00196             vector< Vec4i > hierarchy1;
00197             findContours( thr1, contours1, hierarchy1,CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE );
00198 
00199             for( int i = 0; i< contours1.size(); i++ ){
00200              Rect r= boundingRect(contours1[i]);
00201              rects1.push_back(r);
00202              //rectangle(image1,Point(r.x,r.y), Point(r.x+r.width,r.y+r.height), Scalar(0,0,255),2,8,0);
00203              }//Opened contour
00204          vector<Rect> near1,near2;
00205          int offset = 5;
00206          for(int i = 0; i < rects1.size(); i++)
00207          {
00208              Rect ri = rects1.at(i);
00209              if(ri.x == 1 && ri.y == 1)
00210                  continue;
00211              for(int j = 0; j < rects2.size();j++)
00212              {
00213                  Rect rj = rects2.at(j);
00214                  if(ri.x < rj.x + offset && ri.x > rj.x -offset)
00215                  {
00216                      if(ri.y < rj.y + offset && ri.y > rj.y -offset)
00217                      {
00218                          near1.push_back(ri);
00219                          near2.push_back(rj);
00220                      }
00221                  }
00222              }
00223          }
00224          double eudis = 0;
00225          double disX,disY;
00226          for(int i = 0; i < near1.size(); i++)
00227          {
00228              Rect ri = near1.at(i);
00229              Rect rj = near2.at(i);
00230              disX = ri.x - rj.x;
00231              disY = ri.y - rj.y;
00232              if(disX < 0)
00233                  disX = disX * (-1);
00234              if(disY < 0)
00235                  disY = disY * (-1);
00236              eudis += sqrt((disX*disX)+(disY*disY));
00237          }
00238          if(near1.size() < 2)
00239              eudis = -1;
00240          else
00241              eudis = eudis / near1.size();
00242          ROS_DEBUG("EudisNew:%f\t near1Size:%lu:\toldTran:%i",eudis,near1.size(),oldTransform.empty());
00243          //calc EudisOld
00244 
00245          Mat thr3,tmp1;
00246          //cvtColor(image1,tmp,CV_BGR2GRAY);
00247          if(oldTransform.empty())
00248              return;
00249          warpAffine(image2,tmp1,oldTransform,image2.size());
00250          threshold(tmp1,thr3,0,255,THRESH_BINARY);
00251 
00252          erode(thr3,thr3,K,Point(-1,-1),1,BORDER_CONSTANT);
00253             vector< vector <Point> > contours3; // Vector for storing contour
00254             vector< Vec4i > hierarchy3;
00255             findContours( thr3, contours3, hierarchy3,CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE );
00256 
00257             for( int i = 0; i< contours3.size(); i++ ){
00258              Rect r= boundingRect(contours3[i]);
00259              rects3.push_back(r);
00260             }//Opened contour
00261             near1.clear();
00262             near2.clear();
00263             for(int i = 0; i < rects1.size(); i++)
00264             {
00265                 Rect ri = rects1.at(i);
00266                 if(ri.x == 1 && ri.y == 1)
00267                     continue;
00268                 for(int j = 0; j < rects3.size();j++)
00269                 {
00270                     Rect rj = rects3.at(j);
00271                     if(ri.x < rj.x + offset && ri.x > rj.x -offset)
00272                     {
00273                         if(ri.y < rj.y + offset && ri.y > rj.y -offset)
00274                         {
00275                             near1.push_back(ri);
00276                             near2.push_back(rj);
00277                         }
00278                     }
00279                 }
00280             }
00281             double eudisOLD = 0;
00282             for(int i = 0; i < near1.size(); i++)
00283             {
00284                 Rect ri = near1.at(i);
00285                 Rect rj = near2.at(i);
00286                 disX = ri.x - rj.x;
00287                 disY = ri.y - rj.y;
00288                 if(disX < 0)
00289                     disX = disX * (-1);
00290                 if(disY < 0)
00291                     disY = disY * (-1);
00292                 eudisOLD += sqrt((disX*disX)+(disY*disY));
00293             }
00294             if(near1.size() < 2)
00295                 eudis = -1;
00296             else
00297                 eudisOLD = eudisOLD / near1.size();
00298             //if(eudisOLD < eudis)
00299                // works = false;
00300             ROS_WARN("EudisOLD:%f\t near1Size:%lu:|works:%i",eudis,near1.size(),works);
00301             //calc EudisOld
00302          /*  for(int i = 0; i < rects1.size(); i++)
00303            {
00304                Rect r = rects1.at(i);
00305                rectangle(image1,Point(r.x,r.y), Point(r.x+r.width,r.y+r.height), Scalar(0,0,255),2,8,0);
00306             }*/
00307 
00308   }
00309   return;
00310 }
00311 
00312 Mat
00313 StitchedMap::get_debug()
00314 {
00315   Mat out;
00316   drawKeypoints(image1, kpv1, image1, Scalar(255,0,0));
00317   drawKeypoints(image2, kpv2, image2, Scalar(255,0,0));
00318   drawMatches(image1,fil1, image2,fil2, matches,out,Scalar::all(-1),Scalar::all(-1));
00319   return out;
00320 }
00321 
00322 Mat // return the stitched maps
00323 StitchedMap::get_stitch()
00324 {
00325   // create storage for new image and get transformations
00326   Mat image(image2.size(), image2.type());
00327   warpAffine(image2,image,H,image.size());
00328 
00329   // blend image1 onto the transformed image2
00330   //addWeighted(image,.5,image1,.5,0.0,image);
00331 
00332   return image;
00333 }
00334 
00335 
00336 StitchedMap::~StitchedMap() { }


map_merger
Author(s): Peter Kohout , Torsten Andre
autogenerated on Thu Jun 6 2019 20:59:50