00001
00025 #include "mapstitch.h"
00026 #include "math.h"
00027
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
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
00041 OrbFeatureDetector detector;
00042 OrbDescriptorExtractor dexc;
00043 BFMatcher dematc(NORM_HAMMING, false);
00044
00045
00046 detector.detect(image1, kpv1);
00047 detector.detect(image2, kpv2);
00048
00049
00050 dexc.compute(image1, kpv1, dscv1);
00051 dexc.compute(image2, kpv2, dscv2);
00052
00053
00054 if(kpv1.size() == 0|| kpv2.size() == 0)
00055 {
00056 ROS_WARN("No KPV");
00057 works = false;
00058 return;
00059 }
00060
00061 dematc.match(dscv1, dscv2, matches);
00062
00063
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
00097
00098
00099
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
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
00124
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
00160
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
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;
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 }
00190
00191 Mat thr1;
00192
00193 threshold(image1,thr1,0,255,THRESH_BINARY);
00194 erode(thr1,thr1,K,Point(-1,-1),1,BORDER_CONSTANT);
00195 vector< vector <Point> > contours1;
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
00203 }
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
00244
00245 Mat thr3,tmp1;
00246
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;
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 }
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
00299
00300 ROS_WARN("EudisOLD:%f\t near1Size:%lu:|works:%i",eudis,near1.size(),works);
00301
00302
00303
00304
00305
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
00323 StitchedMap::get_stitch()
00324 {
00325
00326 Mat image(image2.size(), image2.type());
00327 warpAffine(image2,image,H,image.size());
00328
00329
00330
00331
00332 return image;
00333 }
00334
00335
00336 StitchedMap::~StitchedMap() { }