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