// ** please don't make this program interactive. it must be // usable in a script, as a filter. ** int main(int argc,char **argv) { vul_arg<vcl_string> infile ("-in" ,"input image file" ,"-"); // default is stdin. vul_arg<vcl_string> outfile("-out" ,"output corner file (default is stdout)" ,""); vul_arg<double> sigma ("-sigma","gauss sigma" ,0.7); vul_arg<int> corner_count_max("-c","Max number of corners", 900); vul_arg<int> adaptive_window_size("-w","Adaptive window size (0 disables)", 64); vul_arg<vcl_string> cormap ("-map" ,"cornerness map (pnm)",""); vul_arg<bool> pab ("-pab" ,"emulate pab harris" ,false); vul_arg_parse(argc,argv); // load image vil1_image I; if (infile() == "-") { //vcl_cerr << "reading image from stdin\n"; //I = vil1_load(cin); vcl_cerr << "cannot read from stdin yet\n"; return 1; } else I = vil1_load(infile().c_str()); // parameters osl_harris_params params; params.corner_count_max = corner_count_max(); params.gauss_sigma = (float)sigma(); params.verbose = true; params.adaptive_window_size = adaptive_window_size(); params.adaptive = (adaptive_window_size() != 0); params.pab_emulate = pab(); // compute object osl_harris H(params); H.compute(I); // save if (outfile() == "") { vcl_cerr << "writing image to stdout\n"; H.save_corners(vcl_cout); } else H.save_corners(outfile().c_str()); // cornerness map if (cormap.set()) vil1_save(H.image_cornerness_buf, cormap().c_str(), "pnm"); return 0; }
// [ref] ${VXL_HOME}/contrib/mul/fhs/tools/find_matches.cxx int fhs_find_matches_example(int argc, char *argv[]) { vul_arg<vcl_string> image1_path("-i1", "Input image 1"); vul_arg<vcl_string> image2_path("-i2", "Input image 2"); vul_arg<vcl_string> output_image1_path("-o1", "Output image 1", "output1.png"); vul_arg<vcl_string> output_image2_path("-o2", "Output image 1", "output2.png"); vul_arg<unsigned> level("-L", "Image pyramid level to work on", 2); vul_arg<unsigned> nc("-n", "Number of points to select", 10); vul_arg<unsigned> w("-w", "Half width of filters", 7); vul_arg<double> f("-f", "Relative strength of intensity vs shape", 0.1); vul_arg_parse(argc, argv); if (image1_path() == "" || image2_path() == "") { local::print_usage(); return 0; } // ============================================ // Attempt to load in images // ============================================ vimt_image_2d_of<vxl_byte> image1, image2; image1.image() = vil_load(image1_path().c_str()); if (image1.image().size() == 0) { vcl_cerr << "Unable to read in image from " << image1_path() << vcl_endl; return 1; } image2.image() = vil_load(image2_path().c_str()); if (image2.image().size() == 0) { vcl_cerr <<" Unable to read in image from " << image2_path() << vcl_endl; return 1; } // ============================================ // Build image pyramids and select chosen level // ============================================ vimt_gaussian_pyramid_builder_2d<vxl_byte> pyr_builder; vimt_image_pyramid image_pyr1, image_pyr2; pyr_builder.build(image_pyr1, image1); pyr_builder.build(image_pyr2, image2); const vimt_image_2d_of<vxl_byte> &image1_L = static_cast<const vimt_image_2d_of<vxl_byte> &>(image_pyr1(level())); const vimt_image_2d_of<vxl_byte> &image2_L = static_cast<const vimt_image_2d_of<vxl_byte> &>(image_pyr2(level())); // ==================================================== // Apply corner operator to image1_L and select corners // ==================================================== vimt_image_2d_of<float> corner_im; corner_im.set_world2im(image1_L.world2im()); vil_corners(image1_L.image(), corner_im.image()); vcl_vector<unsigned> pi, pj; float threshold = 4.0f; vil_find_peaks_3x3(pi, pj, corner_im.image(), threshold); // Evaluate corner strength at each point (pi[i], pj[i]) unsigned n = pi.size(); vcl_vector<float> corner_str(n); for (unsigned i = 0 ; i < n; ++i) corner_str[i] = corner_im.image()(pi[i], pj[i]); // Sort and generate a list of image points and equivalent world points vcl_vector<unsigned> index; mbl_index_sort(corner_str, index); unsigned n_c = vcl_min(nc(),n); vcl_vector<vgl_point_2d<int> > im_pts(n_c); vcl_vector<vgl_point_2d<double> > w_pts(n_c); vimt_transform_2d im2w = image1_L.world2im().inverse(); for (unsigned i = 0; i < n_c; ++i) { im_pts[i] = vgl_point_2d<int>(pi[index[n - 1 - i]], pj[index[n - 1 - i]]); w_pts[i] = im2w(pi[index[n - 1 - i]], pj[index[n - 1 - i]]); } // ======================================================== // Extract patches around each selected point and normalise // ======================================================== vcl_vector<vil_image_view<float> > patch(n_c); vcl_vector<vgl_point_2d<double> > patch_ref(n_c); // Reference point int ni = image1.image().ni(); int nj = image1.image().nj(); for (unsigned i = 0; i < n_c; ++i) { // Select region around point, allowing for image edges. int ilo = vcl_max(0, int(im_pts[i].x() - w())); int ihi = vcl_min(ni - 1, int(im_pts[i].x() + w())); int jlo = vcl_max(0, int(im_pts[i].y() - w())); int jhi = vcl_min(nj - 1, int(im_pts[i].y() + w())); // Compute position of reference point relative to corner int kx = im_pts[i].x() - ilo; int ky = im_pts[i].y() - jlo; patch_ref[i] = vgl_point_2d<double>(kx, ky); vil_convert_cast(vil_crop(image1_L.image(), ilo, 1 + ihi - ilo, jlo, 1 + jhi - jlo), patch[i]); vil_math_normalise(patch[i]); } // Construct tree structure for points vcl_vector<vcl_pair<int, int> > pairs; mbl_minimum_spanning_tree(w_pts, pairs); assert(pairs.size() == n_c - 1); // Draw tree into image for display purposes local::draw_tree(image1.image(), w_pts, pairs); if (vil_save(image1.image(), output_image1_path().c_str())) { vcl_cout << "Saved output image 1 to " << output_image1_path() << vcl_endl; } // ================================================= // Construct the arc model from the points and pairs // ================================================= vcl_vector<fhs_arc> arcs(n_c - 1); int root_node = pairs[0].first; for (unsigned i = 0; i < pairs.size(); ++i) { int i1 = pairs[i].first; int i2 = pairs[i].second; vgl_vector_2d<double> dp = w_pts[i2] - w_pts[i1]; double sd_x = vcl_max(0.1 * ni, 0.2 * dp.length()); double sd_y = vcl_max(0.1 * nj, 0.2 * dp.length()); arcs[i] = fhs_arc(i1, i2, dp.x(), dp.y(), sd_x * sd_x, sd_y * sd_y); } // ================================================= // Apply filters to image2 (initially to whole image) // ================================================= vcl_vector<vimt_image_2d_of<float> > feature_response(n_c); for (unsigned i = 0; i < n_c; ++i) { // Apply to whole image in first instance // Ideally would crop a region around expected position vimt_normalised_correlation_2d(image2_L, feature_response[i], patch[i], patch_ref[i], float()); // Need good values to be small, not large, so apply -ve factor vil_math_scale_values(feature_response[i].image(), -f()); } // ====================================================== // Use fhs_searcher to locate equivalent points on image2 // ====================================================== fhs_searcher searcher; searcher.set_tree(arcs, root_node); searcher.search(feature_response); vcl_vector<vgl_point_2d<double> > pts2; searcher.best_points(pts2); // Draw tree into image for display purposes local::draw_tree(image2.image(), pts2, pairs); if (vil_save(image2.image(), output_image2_path().c_str())) { vcl_cout << "Saved output image 2 to " << output_image2_path() << vcl_endl; } return 0; }
// [ref] ${VXL_HOME}/contrib/mul/msm/tools/msm_draw_points_on_image.cxx int msm_draw_points_on_image_example(int argc, char *argv[]) { vul_arg<vcl_string> curves_path("-c", "File containing curves"); vul_arg<vcl_string> pts_path("-p", "File containing points"); vul_arg<vcl_string> image_path("-i", "Image"); vul_arg<vcl_string> out_path("-o", "Output path","image+pts.eps"); vul_arg<vcl_string> line_colour("-lc", "Line colour","yellow"); vul_arg<vcl_string> pt_colour("-pc", "Point colour","none"); vul_arg<vcl_string> pt_edge_colour("-pbc", "Point border colour","none"); vul_arg<double> pt_radius("-pr", "Point radius",2.0); vul_arg<double> scale("-s", "Scaling to apply",1.0); vul_arg_parse(argc, argv); if (pts_path() == "") { local::print_usage(); return 0; } msm_curves curves; if (curves_path() != "" && !curves.read_text_file(curves_path())) vcl_cerr << "Failed to read in curves from " << curves_path() << vcl_endl; msm_points points; if (!points.read_text_file(pts_path())) { vcl_cerr << "Failed to read points from " << pts_path() << vcl_endl; return 2; } vcl_vector<vgl_point_2d<double> > pts; points.get_points(pts); //================ Attempt to load image ======== vil_image_view<vxl_byte> image; if (image_path() != "") { image = vil_load(image_path().c_str()); if (image.size() == 0) { vcl_cout << "Failed to load image from " << image_path() << vcl_endl; return 1; } vcl_cout << "Image is " << image << vcl_endl; } if (scale() > 1.001 || scale() < 0.999) { // Scale image and points vil_image_view<vxl_byte> image2; image2.deep_copy(image); if (scale() < 0.51) vil_gauss_filter_2d(image, image2, 1.0, 3); vil_resample_bilin(image2, image, int(0.5 + scale() * image.ni()), int(0.5 + scale() * image.nj())); points.scale_by(scale()); } // Compute bounding box of points vgl_box_2d<double> bbox = points.bounds(); bbox.scale_about_centroid(1.05); // Add a border // If an image is supplied, use that to define bounding box if (image.size() > 0) { bbox = vgl_box_2d<double>(0, image.ni(), 0,image.nj()); } vgl_point_2d<double> blo = bbox.min_point(); // Translate all points to allow for shift of origin points.translate_by(-blo.x(), -blo.y()); mbl_eps_writer writer(out_path().c_str(), bbox.width(), bbox.height()); if (image.size() > 0) writer.draw_image(image, 0, 0, 1, 1); if (pt_colour() != "none") { // Draw all the points writer.set_colour(pt_colour()); msm_draw_points_to_eps(writer, points, pt_radius()); } if (pt_edge_colour() != "none") { // Draw disks around all the points writer.set_colour(pt_edge_colour()); msm_draw_points_to_eps(writer, points, pt_radius(), false); } if (curves.size() > 0 && line_colour() != "none") { // Draw all the lines writer.set_colour(line_colour()); msm_draw_shape_to_eps(writer, points, curves); } writer.close(); vcl_cout << "Graphics saved to " << out_path() << vcl_endl; return 0; }