00001
00002
00003
00004
00005
00006 #include <vcl_cassert.h>
00007 #include <vul/vul_arg.h>
00008 #include <vimt/vimt_image_2d_of.h>
00009 #include <vimt/vimt_gaussian_pyramid_builder_2d.h>
00010 #include <vimt/vimt_image_pyramid.h>
00011 #include <vil/algo/vil_corners.h>
00012 #include <vil/algo/vil_find_peaks.h>
00013 #include <vil/vil_load.h>
00014 #include <vil/vil_save.h>
00015 #include <vil/vil_fill.h>
00016 #include <vil/vil_crop.h>
00017 #include <vil/vil_math.h>
00018 #include <vil/vil_convert.h>
00019 #include <vgl/vgl_point_2d.h>
00020 #include <vgl/vgl_vector_2d.h>
00021 #include <mbl/mbl_index_sort.h>
00022 #include <fhs/fhs_searcher.h>
00023 #include <vimt/algo/vimt_normalised_correlation_2d.h>
00024 #include <mbl/mbl_minimum_spanning_tree.h>
00025 #include <mbl/mbl_draw_line.h>
00026
00027 void print_usage()
00028 {
00029 vcl_cout<<"find_matches -i1 image1.jpg -i2 image2.jpg -L 2\n"
00030 <<"Loads in image1 and image2.\n"
00031 <<"Locates a set of interesting features (corners) on level L of image1.\n"
00032 <<"Constructs a model of their relative positions.\n"
00033 <<"Uses normalised correlation and this model to locate\n"
00034 <<"equivalent points on the same level of the second image."<<vcl_endl;
00035 vul_arg_display_usage_and_exit();
00036 }
00037
00038
00039
00040 void draw_tree(vil_image_view<vxl_byte>& image,
00041 const vcl_vector<vgl_point_2d<double> >& pts,
00042 const vcl_vector<vcl_pair<int,int> >& pairs)
00043 {
00044
00045 for (unsigned i=0;i<pairs.size();++i)
00046 mbl_draw_line(image,
00047 pts[pairs[i].first],
00048 pts[pairs[i].second],vxl_byte(255));
00049
00050
00051
00052 for (unsigned i=0;i<pts.size();++i)
00053 {
00054 vil_fill_disk(image,pts[i].x(),pts[i].y(),4,vxl_byte(255));
00055 }
00056 }
00057
00058 int main( int argc, char* argv[] )
00059 {
00060 vul_arg<vcl_string> image1_path("-i1","Input image 1");
00061 vul_arg<vcl_string> image2_path("-i2","Input image 2");
00062 vul_arg<vcl_string> output_image1_path("-o1","Output image 1","output1.png");
00063 vul_arg<vcl_string> output_image2_path("-o2","Output image 1","output2.png");
00064 vul_arg<unsigned> level("-L","Image pyramid level to work on",2);
00065 vul_arg<unsigned> nc("-n","Number of points to select",10);
00066 vul_arg<unsigned> w("-w","Half width of filters",7);
00067 vul_arg<double> f("-f","Relative strength of intensity vs shape",0.1);
00068
00069 vul_arg_parse(argc, argv);
00070
00071 if (image1_path()=="" || image2_path()=="")
00072 {
00073 print_usage();
00074 return 0;
00075 }
00076
00077
00078
00079
00080
00081 vimt_image_2d_of<vxl_byte> image1,image2;
00082 image1.image() = vil_load(image1_path().c_str());
00083 if (image1.image().size()==0)
00084 {
00085 vcl_cerr<<"Unable to read in image from "<<image1_path()<<vcl_endl;
00086 return 1;
00087 }
00088 image2.image() = vil_load(image2_path().c_str());
00089 if (image2.image().size()==0)
00090 {
00091 vcl_cerr<<"Unable to read in image from "<<image2_path()<<vcl_endl;
00092 return 1;
00093 }
00094
00095
00096
00097
00098 vimt_gaussian_pyramid_builder_2d<vxl_byte> pyr_builder;
00099 vimt_image_pyramid image_pyr1,image_pyr2;
00100 pyr_builder.build(image_pyr1,image1);
00101 pyr_builder.build(image_pyr2,image2);
00102
00103 const vimt_image_2d_of<vxl_byte>& image1_L = static_cast<const vimt_image_2d_of<vxl_byte>&>(image_pyr1(level()));
00104 const vimt_image_2d_of<vxl_byte>& image2_L = static_cast<const vimt_image_2d_of<vxl_byte>&>(image_pyr2(level()));
00105
00106
00107
00108
00109
00110 vimt_image_2d_of<float> corner_im;
00111 corner_im.set_world2im(image1_L.world2im());
00112 vil_corners(image1_L.image(),corner_im.image());
00113
00114 vcl_vector<unsigned> pi,pj;
00115 float threshold = 4.0f;
00116 vil_find_peaks_3x3(pi,pj,corner_im.image(),threshold);
00117
00118
00119 unsigned n = pi.size();
00120 vcl_vector<float> corner_str(n);
00121 for (unsigned i=0;i<n;++i)
00122 corner_str[i] = corner_im.image()(pi[i],pj[i]);
00123
00124
00125 vcl_vector<unsigned> index;
00126 mbl_index_sort(corner_str,index);
00127
00128 unsigned n_c = vcl_min(nc(),n);
00129 vcl_vector<vgl_point_2d<int> > im_pts(n_c);
00130 vcl_vector<vgl_point_2d<double> > w_pts(n_c);
00131 vimt_transform_2d im2w = image1_L.world2im().inverse();
00132 for (unsigned i=0;i<n_c;++i)
00133 {
00134 im_pts[i] = vgl_point_2d<int>(pi[index[n-1-i]],pj[index[n-1-i]]);
00135 w_pts[i] = im2w(pi[index[n-1-i]],pj[index[n-1-i]]);
00136 }
00137
00138
00139
00140
00141
00142 vcl_vector<vil_image_view<float> > patch(n_c);
00143 vcl_vector<vgl_point_2d<double> > patch_ref(n_c);
00144 int ni = image1.image().ni();
00145 int nj = image1.image().nj();
00146 for (unsigned i=0;i<n_c;++i)
00147 {
00148
00149 int ilo = vcl_max(0,int(im_pts[i].x()-w()));
00150 int ihi = vcl_min(ni-1,int(im_pts[i].x()+w()));
00151 int jlo = vcl_max(0,int(im_pts[i].y()-w()));
00152 int jhi = vcl_min(nj-1,int(im_pts[i].y()+w()));
00153
00154
00155 int kx = im_pts[i].x()-ilo;
00156 int ky = im_pts[i].y()-jlo;
00157 patch_ref[i] =vgl_point_2d<double>(kx,ky);
00158 vil_convert_cast(vil_crop(image1_L.image(),ilo,1+ihi-ilo, jlo,1+jhi-jlo),
00159 patch[i]);
00160 vil_math_normalise(patch[i]);
00161 }
00162
00163
00164 vcl_vector<vcl_pair<int,int> > pairs;
00165 mbl_minimum_spanning_tree(w_pts,pairs);
00166
00167 assert(pairs.size()==n_c-1);
00168
00169
00170 draw_tree(image1.image(),w_pts,pairs);
00171
00172 if (vil_save(image1.image(),output_image1_path().c_str()))
00173 {
00174 vcl_cout<<"Saved output image 1 to "<<output_image1_path()<<vcl_endl;
00175 }
00176
00177
00178
00179
00180
00181 vcl_vector<fhs_arc> arcs(n_c-1);
00182 int root_node = pairs[0].first;
00183 for (unsigned i=0;i<pairs.size();++i)
00184 {
00185 int i1 = pairs[i].first;
00186 int i2 = pairs[i].second;
00187 vgl_vector_2d<double> dp = w_pts[i2]-w_pts[i1];
00188 double sd_x = vcl_max(0.1*ni,0.2*dp.length());
00189 double sd_y = vcl_max(0.1*nj,0.2*dp.length());
00190 arcs[i]=fhs_arc(i1,i2,dp.x(),dp.y(),sd_x*sd_x,sd_y*sd_y);
00191 }
00192
00193
00194
00195
00196 vcl_vector<vimt_image_2d_of<float> > feature_response(n_c);
00197 for (unsigned i=0;i<n_c;++i)
00198 {
00199
00200
00201 vimt_normalised_correlation_2d(image2_L,feature_response[i],
00202 patch[i],patch_ref[i],float());
00203
00204
00205 vil_math_scale_values(feature_response[i].image(),-f());
00206 }
00207
00208
00209
00210
00211
00212 fhs_searcher searcher;
00213 searcher.set_tree(arcs,root_node);
00214 searcher.search(feature_response);
00215 vcl_vector<vgl_point_2d<double> > pts2;
00216 searcher.best_points(pts2);
00217
00218
00219 draw_tree(image2.image(),pts2,pairs);
00220
00221 if (vil_save(image2.image(),output_image2_path().c_str()))
00222 {
00223 vcl_cout<<"Saved output image 2 to "<<output_image2_path()<<vcl_endl;
00224 }
00225
00226 return 0;
00227 }