contrib/gel/vmal/vmal_dense_matching.cxx
Go to the documentation of this file.
00001 #include "vmal_dense_matching.h"
00002 #include <vtol/vtol_edge_2d.h>
00003 #include <vmal/vmal_convert_vtol.h>
00004 #include <vmal/vmal_operators.h>
00005 #include <vnl/vnl_double_3.h>
00006 #include <vnl/vnl_int_3.h>
00007 #include <vnl/vnl_matrix.h>
00008 #include <vnl/vnl_inverse.h>
00009 #include <vil1/vil1_memory_image_of.h>
00010 #include <vil1/vil1_save.h>
00011 
00012 #include <vcl_cmath.h>
00013 
00014 vmal_dense_matching::vmal_dense_matching(const vnl_double_3x3 & H0,
00015                                          const vnl_double_3x3 & H1)
00016 {
00017   H0_=H0;
00018   H1_=H1;
00019 }
00020 
00021 vmal_dense_matching::~vmal_dense_matching()
00022 {
00023 }
00024 
00025 void vmal_dense_matching::set_fmatrix(const vnl_double_3x3 & F)
00026 {
00027   F_=F;
00028   type_=1; //1 for fundamental matrix
00029 }
00030 
00031 void vmal_dense_matching::set_hmatrix(const vnl_double_3x3 & H)
00032 {
00033   H_=H;
00034   type_=2; // 2 for homography
00035 }
00036 
00037 // Between two set of lines in 2 images that are matched, it compute the best lines
00038 // using the fundamental constraint.
00039 void vmal_dense_matching::refine_lines_using_F(vmal_multi_view_data_edge_sptr mvd_edge,
00040                                                vmal_multi_view_data_edge_sptr res)
00041 {
00042   // We assume that the lines have been sorted. It means that, for example, the
00043   // first end-point of the first segment correspond to the first end-point of
00044   // the second segment.
00045   if (type_==1)
00046   {
00047     if (mvd_edge->get_nb_views()>1)
00048     {
00049       vnl_double_3* lines0_p;
00050       vnl_double_3* lines0_q;
00051       vnl_double_3* lines1_p;
00052       vnl_double_3* lines1_q;
00053 
00054       vcl_vector<vtol_edge_2d_sptr> tmp_lines0;
00055       vcl_vector<vtol_edge_2d_sptr> tmp_lines1;
00056 
00057       mvd_edge->get(0,1,tmp_lines0,tmp_lines1);
00058       int numlines=tmp_lines0.size();
00059 
00060       convert_lines_double_3(tmp_lines0, lines0_p, lines0_q);
00061       convert_lines_double_3(tmp_lines1, lines1_p, lines1_q);
00062       double threshold=0.1745;//0.08727;
00063 
00064       for (int i=0;i<numlines;i++)
00065       {
00066         //compute the 4 epipolars lines, each linked to an end-point of
00067         //the 2 segments
00068         vnl_double_3 epi_line1p=F_*lines0_p[i];
00069         vnl_double_3 epi_line1q=F_*lines0_q[i];
00070         vnl_double_3 epi_line0p=(F_.transpose()*lines1_p[i]);
00071         vnl_double_3 epi_line0q=(F_.transpose()*lines1_q[i]);
00072 
00073         //variables to represent the end-points
00074         vnl_double_3 pt0p=lines0_p[i];
00075         vnl_double_3 pt0q=lines0_q[i];
00076         vnl_double_3 pt1p=lines1_p[i];
00077         vnl_double_3 pt1q=lines1_q[i];
00078 
00079         vnl_double_3 inter1p;
00080         vnl_double_3 inter1q;
00081 
00082         double alpha,beta;
00083 
00084         if (vmal_operators::line_cross_seg(lines1_p[i], lines1_q[i], epi_line1p, inter1p,alpha))
00085           if (vmal_operators::line_cross_seg(lines1_p[i], lines1_q[i], epi_line1q, inter1q,beta))
00086           {
00087             //1 case: the first segment is "included" in the second segment
00088             vmal_operators::line_cross_seg(lines0_p[i], lines0_q[i], epi_line0p, pt0p,alpha);
00089             vmal_operators::line_cross_seg(lines0_p[i], lines0_q[i], epi_line0q, pt0q,beta);
00090           }
00091           else
00092           {
00093             //2 case: the segments share a part.
00094             vmal_operators::line_cross_seg(lines0_p[i], lines0_q[i], epi_line0p, pt0p, alpha);
00095             pt1q=inter1q;
00096           }
00097         else
00098           if (vmal_operators::line_cross_seg(lines1_p[i], lines1_q[i], epi_line1q, inter1q, beta))
00099           {
00100             //3 case:  the segments share a part.
00101             vmal_operators::line_cross_seg(lines0_p[i], lines0_q[i], epi_line0q, pt0q, beta);
00102             pt1p=inter1p;
00103           }
00104           else
00105           {
00106             //4 case: the second segment is "included" in the first
00107             pt1p=inter1p;
00108             pt1q=inter1q;
00109           }
00110 
00111         if (alpha>threshold && beta>threshold)
00112         {
00113           res->new_track();
00114           vtol_edge_2d_sptr out0=new vtol_edge_2d(pt0p[0],pt0p[1],pt0q[0],pt0q[1]);
00115           vtol_edge_2d_sptr out1=new vtol_edge_2d(pt1p[0],pt1p[1],pt1q[0],pt1q[1]);
00116           res->set(0,out0);
00117           res->set(1,out1);
00118           res->close_track();
00119         }
00120       }
00121     }
00122   }
00123   else
00124     vcl_cerr<<"Error: you must set the Fundamental matrix to use this method.\n";
00125 }
00126 
00127 // Between two set of lines in 2 images that are matched, it compute the best lines
00128 // using the homography
00129 void vmal_dense_matching::refine_lines_using_H(vmal_multi_view_data_edge_sptr mvd_edge,
00130                                                vmal_multi_view_data_edge_sptr res)
00131 {
00132   //the second segment.
00133   if (type_==2)
00134   {
00135     if (mvd_edge->get_nb_views()>1)
00136     {
00137       vnl_double_3* lines0_p;
00138       vnl_double_3* lines0_q;
00139       vnl_double_3* lines1_p;
00140       vnl_double_3* lines1_q;
00141 
00142       vcl_vector<vtol_edge_2d_sptr> tmp_lines0;
00143       vcl_vector<vtol_edge_2d_sptr> tmp_lines1;
00144 
00145       mvd_edge->get(0,1,tmp_lines0,tmp_lines1);
00146       int numlines=tmp_lines0.size();
00147 
00148       convert_lines_double_3(tmp_lines0, lines0_p, lines0_q);
00149       convert_lines_double_3(tmp_lines1, lines1_p, lines1_q);
00150 
00151       vnl_double_3x3 HI=vnl_inverse(H_);
00152       for (int i=0;i<numlines;i++)
00153       {
00154         vnl_double_3 pt0p=lines0_p[i];
00155         vnl_double_3 pt0q=lines0_q[i];
00156         vnl_double_3 pt1p=lines1_p[i];
00157         vnl_double_3 pt1q=lines1_q[i];
00158 
00159         vnl_double_3 h_lines1_p=H_*lines0_p[i];
00160         vnl_double_3 h_lines1_q=H_*lines0_q[i];
00161         vnl_double_3 h_lines0_p=HI*lines1_p[i];
00162         vnl_double_3 h_lines0_q=HI*lines1_q[i];
00163 
00164         vnl_double_3 inter1p;
00165         vnl_double_3 inter1q;
00166 
00167         if (vmal_operators::project_point(h_lines1_p,lines1_p[i],lines1_q[i],inter1p))
00168         {
00169           if (vmal_operators::project_point(h_lines1_q,lines1_p[i],lines1_q[i],inter1q))
00170           {
00171             //Case 1
00172             vmal_operators::project_point(h_lines0_p,lines0_p[i],lines0_q[i],pt0p);
00173             vmal_operators::project_point(h_lines0_q,lines0_p[i],lines0_q[i],pt0q);
00174           }
00175           else
00176           {
00177             //Case 2
00178             vmal_operators::project_point(h_lines0_p,lines0_p[i],lines0_q[i],pt0p);
00179             pt1q=inter1q;
00180           }
00181         }
00182         else
00183         {
00184           if (vmal_operators::project_point(h_lines1_q,lines1_p[i],lines1_q[i],inter1q))
00185           {
00186             //Case 3
00187             pt1p=inter1p;
00188             vmal_operators::project_point(h_lines0_q,lines0_p[i],lines0_q[i],pt0q);
00189           }
00190           else
00191           {
00192             //Case 4
00193             pt1p=inter1p;
00194             pt1q=inter1q;
00195           }
00196         }
00197 
00198         res->new_track();
00199         vtol_edge_2d_sptr out0=new vtol_edge_2d(pt0p[0],pt0p[1],pt0q[0],pt0q[1]);
00200         vtol_edge_2d_sptr out1=new vtol_edge_2d(pt1p[0],pt1p[1],pt1q[0],pt1q[1]);
00201         res->set(0,out0);
00202         res->set(1,out1);
00203         res->close_track();
00204       }
00205     }
00206   }
00207   else
00208     vcl_cerr<<"Error: you must set the Homography matrix to use this method.\n";
00209 }
00210 
00211 
00212 void vmal_dense_matching::disparity_map(vmal_multi_view_data_edge_sptr mvd_edge,
00213                                         int h,int w)
00214 {
00215   vnl_double_3* lines0_p;
00216   vnl_double_3* lines0_q;
00217   vnl_double_3* lines1_p;
00218   vnl_double_3* lines1_q;
00219 
00220   int disparity, min_disparity=0,max_disparity=0;
00221 
00222   vcl_vector<vtol_edge_2d_sptr> tmp_lines0;
00223   vcl_vector<vtol_edge_2d_sptr> tmp_lines1;
00224 
00225   mvd_edge->get(0,1,tmp_lines0,tmp_lines1);
00226   int numlines=tmp_lines0.size();
00227 
00228   convert_lines_double_3(tmp_lines0, lines0_p, lines0_q);
00229   convert_lines_double_3(tmp_lines1, lines1_p, lines1_q);
00230 
00231   vnl_double_3x3 IH0=vnl_inverse(H0_);
00232 
00233   vnl_double_3 int_line0p;
00234   vnl_double_3 int_line0q;
00235   vnl_double_3 int_line1p;
00236   vnl_double_3 int_line1q;
00237 
00238   vnl_double_3 point0;
00239   vnl_double_3 point1;
00240   vnl_double_3 t_point0, t_point1;
00241   vnl_int_3 int_t_point0, int_t_point1;
00242 
00243   double a0,b0,a1,b1;
00244   double delta0x,delta0y,delta1x,delta1y;
00245 
00246   vnl_matrix<int> map(w,h);
00247   map.fill(0);
00248 
00249   for (int i=0;i<numlines;i++)
00250   {
00251     int_line0p[0]=vmal_round(lines0_p[i][0]);
00252     int_line0p[1]=vmal_round(lines0_p[i][1]);
00253     int_line0p[2]=1.0;
00254     int_line0q[0]=vmal_round(lines0_q[i][0]);
00255     int_line0q[1]=vmal_round(lines0_q[i][1]);
00256     int_line0q[2]=1.0;
00257 
00258     int_line1p[0]=vmal_round(lines1_p[i][0]);
00259     int_line1p[1]=vmal_round(lines1_p[i][1]);
00260     int_line1p[2]=1.0;
00261     int_line1q[0]=vmal_round(lines1_q[i][0]);
00262     int_line1q[1]=vmal_round(lines1_q[i][1]);
00263     int_line1q[2]=1.0;
00264 
00265     double num0=int_line0p[0]-int_line0q[0];
00266     double num1=int_line1p[0]-int_line1q[0];
00267 
00268     a0=(int_line0p[1]-int_line0q[1])/num0;
00269     a1=(int_line1p[1]-int_line1q[1])/num1;
00270     b0=int_line0p[1]-a0*int_line0p[0];
00271     b1=int_line1p[1]-a1*int_line1p[0];
00272 
00273     if ((int_line0q[0]-int_line0p[0])>0)
00274       delta0x=0.5;
00275     else
00276       delta0x=-0.5;
00277     if ((int_line0q[1]-int_line0p[1])>0)
00278       delta0y=0.5;
00279     else
00280       delta0y=-0.5;
00281 
00282     if ((int_line1q[0]-int_line1p[0])>0)
00283       delta1x=0.5;
00284     else
00285       delta1x=-0.5;
00286     if ((int_line1q[1]-int_line1p[1])>0)
00287       delta1y=0.5;
00288     else
00289       delta1y=-0.5;
00290 
00291     point0=int_line0p;
00292     point1=int_line1p;
00293 
00294     while (point0!=int_line0q)
00295     {
00296       if (num0!=0.0)
00297         if (vcl_fabs(((point0[0]+delta0x)*a0+b0)-point0[1])<=0.5)
00298           point0[0]+=delta0x*2;
00299         else
00300           point0[1]+=delta0y*2;
00301       else
00302         point0[1]+=delta0y*2;
00303 
00304       if (num1!=0.0) {
00305         if (vcl_fabs(((point1[0]+delta1x)*a1+b1)-point1[1])<=0.5)
00306           point1[0]+=delta1x*2;
00307         else
00308           point1[1]+=delta1y*2;
00309       }
00310       else
00311         point1[1]+=delta1y*2;
00312 
00313       t_point0=H0_*point0;
00314       t_point1=H1_*point1;
00315       int_t_point0[0]=(int)vmal_round(t_point0[0]/t_point0[2]);
00316       int_t_point0[1]=(int)vmal_round(t_point0[1]/t_point0[2]);
00317       int_t_point1[0]=(int)vmal_round(t_point1[0]/t_point1[2]);
00318       int_t_point1[1]=(int)vmal_round(t_point1[1]/t_point1[2]);
00319 
00320       //disparity=vmal_round_int(int_t_point1[1]-int_t_point0[1]);
00321       disparity=1;
00322       map(vmal_round_int(point0[0]),vmal_round_int(point0[1]))=disparity;
00323       if (disparity<min_disparity)
00324         min_disparity=disparity;
00325       if (disparity>max_disparity)
00326         max_disparity=disparity;
00327     }
00328   }
00329   vcl_cerr<<"Disparity min: "<<min_disparity<<'\n'
00330           <<"Disparity max: "<<max_disparity<<'\n';
00331 
00332   //Save the matrix in a pgn image
00333   max_disparity-=min_disparity;
00334   unsigned char* buf=new unsigned char[w*h];
00335   for (int i=0; i<h; i++)
00336   {
00337     for (int j=0; j<w; j++)
00338     {
00339       int value=vmal_round_int((map(j,i)-min_disparity)*255/max_disparity);
00340       buf[i*w+j]=(unsigned char)value;
00341     }
00342   }
00343   vil1_memory_image_of<vxl_byte> ima(buf, w, h);
00344   vil1_save(ima, "lolo.pgm");
00345   delete [] buf;
00346 }
00347 
00348 
00349 double vmal_round(double a)
00350 {
00351   return (a>0) ? double(int(a+0.5)) : double(int(a-0.5));
00352 }
00353 
00354 int vmal_round_int(double a)
00355 {
00356   return (a>0) ? int(a+0.5) : int(a-0.5);
00357 }