int main(int argc, char *argv[]) { SIFT3D sift3d; Reg_SIFT3D reg; Image src, ref; Mat_rm match_src, match_ref; void *tform, *tform_arg; char *src_path, *ref_path, *warped_path, *match_path, *tform_path, *concat_path, *keys_path, *lines_path; tform_type type; double thresh; int num_args, c, have_match, have_tform; const struct option longopts[] = { {"matches", required_argument, NULL, MATCHES}, {"transform", required_argument, NULL, TRANSFORM}, {"warped", required_argument, NULL, WARPED}, {"concat", required_argument, NULL, CONCAT}, {"keys", required_argument, NULL, KEYS}, {"lines", required_argument, NULL, LINES}, {"thresh", required_argument, NULL, THRESH}, {"type", required_argument, NULL, TYPE}, {0, 0, 0, 0} }; const char str_affine[] = "affine"; SIFT3D_Descriptor_store *const desc_src = ®.desc_src; SIFT3D_Descriptor_store *const desc_ref = ®.desc_ref; // Parse the GNU standard options switch (parse_gnu(argc, argv)) { case SIFT3D_HELP: puts(help_msg); print_opts_SIFT3D(); return 0; case SIFT3D_VERSION: return 0; case SIFT3D_FALSE: break; default: err_msgu("Unexpected return from parse_gnu \n"); return 1; } // Initialize the data init_im(&src); init_im(&ref); init_Reg_SIFT3D(®); init_SIFT3D(&sift3d); if (init_Mat_rm(&match_src, 0, 0, DOUBLE, SIFT3D_FALSE) || init_Mat_rm(&match_ref, 0, 0, DOUBLE, SIFT3D_FALSE)) { err_msgu("Failed basic initialization."); return 1; } // Initialize parameters to defaults type = type_default; // Parse the SIFT3D options if ((argc = parse_args_SIFT3D(&sift3d, argc, argv, SIFT3D_FALSE)) < 0) return 1; set_SIFT3D_Reg_SIFT3D(®, &sift3d); // Parse the remaining options opterr = 1; have_match = have_tform = SIFT3D_FALSE; match_path = tform_path = warped_path = concat_path = keys_path = lines_path = NULL; while ((c = getopt_long(argc, argv, "", longopts, NULL)) != -1) { switch (c) { case MATCHES: match_path = optarg; have_match = SIFT3D_TRUE; break; case TRANSFORM: tform_path = optarg; have_tform = SIFT3D_TRUE; break; case WARPED: warped_path = optarg; have_tform = SIFT3D_TRUE; break; case CONCAT: concat_path = optarg; have_match = SIFT3D_TRUE; break; case KEYS: keys_path = optarg; have_match = SIFT3D_TRUE; break; case LINES: lines_path = optarg; have_match = SIFT3D_TRUE; break; case THRESH: thresh = atof(optarg); if (set_nn_thresh_Reg_SIFT3D(®, thresh)) { err_msg("Invalid value for thresh."); return 1; } break; case TYPE: if (!strcmp(optarg, str_affine)) { type = AFFINE; } else { char msg[1024]; sprintf(msg, "Unrecognized transformation " "type: %s\n", optarg); err_msg(msg); return 1; } break; case '?': default: return 1; } } // Ensure that at least one output was specified if (!have_match && !have_tform) { err_msg("No outputs were specified."); return 1; } // Parse the required arguments num_args = argc - optind; if (num_args < 2) { err_msg("Not enough arguments."); return 1; } else if (num_args > 2) { err_msg("Too many arguments."); return 1; } src_path = argv[optind]; ref_path = argv[optind + 1]; // Allocate memory for the transformation if ((tform = malloc(tform_type_get_size(type))) == NULL) { err_msg("Out of memory."); return 1; } // Initialize the transformation if (init_tform(tform, type)) return 1; // Read the images if (read_nii(src_path, &src)) { char msg[1024]; sprintf(msg, "Failed to read the source image \"%s\"", src_path); err_msg(msg); return 1; } if (read_nii(ref_path, &ref)) { char msg[1024]; sprintf(msg, "Failed to read the reference image \"%s\"", ref_path); err_msg(msg); return 1; } // Set the images if (set_src_Reg_SIFT3D(®, &src)) { err_msgu("Failed to set the source image."); return 1; } if (set_ref_Reg_SIFT3D(®, &ref)) { err_msgu("Failed to set the reference image."); return 1; } // Match the features, optionally registering the images tform_arg = have_tform ? tform : NULL; if (register_SIFT3D(®, tform_arg)) { err_msgu("Failed to register the images."); return 1; } // Convert the matches to matrices if (get_matches_Reg_SIFT3D(®, &match_src, &match_ref)) { err_msgu("Failed to convert matches to coordinates."); return 1; } // Write the outputs if (match_path != NULL) { Mat_rm matches; int i, j; // Initialize intermediates init_Mat_rm(&matches, 0, 0, DOUBLE, SIFT3D_FALSE); // Form a combined matrix for both sets of matches if (concat_Mat_rm(&match_src, &match_ref, &matches, 1)) { err_msgu("Failed to concatenate the matches."); return 1; } if (write_Mat_rm(match_path, &matches)) { char msg[1024]; sprintf(msg, "Failed to write the matches \"%s\"", match_path); err_msg(msg); return 1; } // Clean up cleanup_Mat_rm(&matches); } if (tform_path != NULL && write_tform(tform_path, tform)) { char msg[1024]; sprintf(msg, "Failed to write the transformation parameters " "\"%s\"", tform_path); err_msg(msg); return 1; } // Optionally warp the source image if (warped_path != NULL) { Image warped; // Initialize intermediates init_im(&warped); // Warp if (im_inv_transform(tform, &src, &warped, interp)) { err_msgu("Failed to warp the source image."); return 1; } // Write the warped image if (write_nii(warped_path, &warped)) { char msg[1024]; sprintf(msg, "Failed to write the warped image \"%s\"", warped_path); err_msg(msg); return 1; } // Clean up im_free(&warped); } // Optionally draw the matches if (concat_path != NULL || keys_path != NULL || lines_path != NULL) { Image concat, keys, lines; Mat_rm keys_src, keys_ref; Image *concat_arg, *keys_arg, *lines_arg; // Initialize intermediates init_im(&concat); init_im(&keys); init_im(&lines); if (init_Mat_rm(&keys_src, 0, 0, DOUBLE, SIFT3D_FALSE) || init_Mat_rm(&keys_ref, 0, 0, DOUBLE, SIFT3D_FALSE)) { err_msgu("Failed to initialize keypoint matrices."); return 1; } // Set up the pointers for the images concat_arg = concat_path == NULL ? NULL : &concat; keys_arg = keys_path == NULL ? NULL : &keys; lines_arg = lines_path == NULL ? NULL : &lines; // Convert the keypoints to matrices if (Keypoint_store_to_Mat_rm(®.kp_src, &keys_src) || Keypoint_store_to_Mat_rm(®.kp_ref, &keys_ref)) { err_msgu("Failed to convert the keypoints to " "matrices."); return 1; } // Draw the matches if (draw_matches(&src, &ref, &keys_src, &keys_ref, &match_src, &match_ref, concat_arg, keys_arg, lines_arg)) { err_msgu("Failed to draw the matches."); return 1; } // Optionally write a concatenated image if (concat_path != NULL && write_nii(concat_path, &concat)) { char msg[1024]; sprintf(msg, "Failed to write the concatenated image " "\"%s\"", concat_path); err_msg(msg); return 1; } // Optionally write the keypoints if (keys_path != NULL && write_nii(keys_path, &keys)) { char msg[1024]; sprintf(msg, "Failed to write the keypoint image " "\"%s\"", concat_path); err_msg(msg); return 1; } // Optionally write the matches if (lines_path != NULL && write_nii(lines_path, &lines)) { char msg[1024]; sprintf(msg, "Failed to write the line image " "\"%s\"", concat_path); err_msg(msg); return 1; } // Clean up im_free(&concat); im_free(&keys); im_free(&lines); } return 0; }
/* <ww, wh> is the size of the OpenGL window */ void draw_frame (int ww, int wh, botlcm_image_t **img1, botlcm_image_t **img2, int nimg, navlcm_feature_list_t *features1, navlcm_feature_list_t *features2, navlcm_feature_match_set_t *matches, double user_scale, double *user_trans, gboolean feature_finder_enabled, gboolean select, navlcm_feature_t *highlight_f, navlcm_feature_match_t *highlight_m, navlcm_feature_t *match_f1, navlcm_feature_t *match_f2, navlcm_feature_match_t *select_m, navlcm_feature_match_t *match, int feature_type, double precision, double recall) { if (!img1[0]) return; // determine scale factor float window_scale = .95*fmin (.25*ww/img1[0]->width, 1.0*wh/img1[0]->height); float ratio = user_scale* window_scale; double trans1[2] = {user_trans[0], user_trans[1]}; double trans2[2] = {user_trans[0], user_trans[1] + ratio*img1[0]->height}; if (!select) { // draw images draw_images (img1, nimg, ratio, trans1); draw_images (img2, nimg, ratio, trans2); } // this is the current match to be (or not to be) added to ground-truth if (match) { draw_match (match, GREEN, 2, img1[0]->width, img1[0]->height, ratio, trans1, trans2); draw_match_ends (match, RED, 4, img1[0]->width, img1[0]->height, ratio, trans1, trans2); } // draw features assert (check_gl_error ("1")); draw_features (features1, RED, 4, ratio, trans1, select, NAME_POINT1, highlight_f, feature_finder_enabled); assert (check_gl_error ("1")); draw_features (features2, RED, 4, ratio, trans2, select, NAME_POINT2, highlight_f, feature_finder_enabled); assert (check_gl_error ("1")); // draw matches draw_matches (matches, YELLOW, 2, img1[0]->width, img1[0]->height, ratio, trans1, trans2, select, highlight_m, select_m); // draw selected items if (features1 && features2) { draw_select_feature (match_f1, features1->width, GREEN, 12, ratio, trans1); draw_select_feature (match_f2, features2->width, GREEN, 12, ratio, trans2); } // draw feature thumbnails if (!select && select_m) { draw_img_subregion (img1, nimg, select_m->src.col, select_m->src.row, select_m->src.sensorid, select_m->src.scale, select_m->src.ori, feature_type, 0, 0); draw_img_subregion (img2, nimg, select_m->dst[0].col, select_m->dst[0].row, select_m->dst[0].sensorid, select_m->dst[0].scale, select_m->dst[0].ori, feature_type, 0, wh/2); } else if (!select && highlight_m) { draw_img_subregion (img1, nimg, highlight_m->src.col, highlight_m->src.row, highlight_m->src.sensorid, highlight_m->src.scale, highlight_m->src.ori, feature_type, 0, 0); draw_img_subregion (img2, nimg, highlight_m->dst[0].col, highlight_m->dst[0].row, highlight_m->dst[0].sensorid, highlight_m->dst[0].scale, highlight_m->dst[0].ori, feature_type, 0, wh/2); } else { if (!select && highlight_f) { draw_img_subregion (img1, nimg, highlight_f->col, highlight_f->row, highlight_f->sensorid, highlight_f->scale, highlight_f->ori, feature_type, 0, 0); draw_img_subregion (img2, nimg, highlight_f->col, highlight_f->row, highlight_f->sensorid, highlight_f->scale, highlight_f->ori, feature_type, 0, wh/2); } if (!select && match_f1) draw_img_subregion (img1, nimg, match_f1->col, match_f1->row, match_f1->sensorid, match_f1->scale, match_f1->ori, feature_type, 0, 0); if (!select && match_f2) draw_img_subregion (img2, nimg, match_f2->col, match_f2->row, match_f2->sensorid, match_f2->scale, match_f2->ori, feature_type, 0, wh/2); } assert (check_gl_error ("1")); if (!select) { // display text info if (matches) display_msg (10, wh-20, ww, wh, RED, 0, "# matches: %d", matches->num); if (features1 && features2) display_msg (200, wh-20, ww, wh, RED, 0, "# features: %d/%d", features1->num, features2->num); display_msg (500, wh-20, ww, wh, RED, 0, "precision: %.2f%% recall: %.2f %%", 100.0*precision, 100.0*recall); } }