Page Menu
Home
c4science
Search
Configure Global Search
Log In
Files
F81167512
main.cpp
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Subscribers
None
File Metadata
Details
File Info
Storage
Attached
Created
Wed, Sep 4, 13:18
Size
12 KB
Mime Type
text/x-c
Expires
Fri, Sep 6, 13:18 (2 d)
Engine
blob
Format
Raw Data
Handle
20523687
Attached To
R6289 Motion correction paper
main.cpp
View Options
/*
Copyright (C) 2014 Jerome Revaud
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>
*/
#include "std.h"
#include "image.h"
#include "io.h"
#include "deep_matching.h"
#include "main.h"
#include <thread>
void usage(const int language)
{
#define p(msg) std_printf(msg "\n");
p("usage:");
switch(language){
case EXE_OPTIONS:
p("./deepmatching image1 image2 [options]");
p("Compute the 'DeepMatching' between two images and print a list of")
p("pair-wise point correspondences:")
p(" x1 y1 x2 y2 score index ...")
p("(index refers to the local maximum from which the match was retrieved)")
p("Images must be in PPM, PNG or JPG format. Version 1.2.2")
break;
case MATLAB_OPTIONS:
p("matches = deepmatching(image1, image2 [, options])")
p("Compute the 'DeepMatching' between two images.")
p("Images must be HxWx3 single matrices.")
p("Options is an optional string argument ('' by default).")
p("The function returns a matrix with 6 columns, each row being x1 y1 x2 y2 score index.")
p("(index refers to the local maximum from which the match was retrieved)")
p("Version 1.2.2")
break;
case PYTHON_OPTIONS:
p("matches = deepmatching.deepmatching(image1, image2, options='')")
p("Compute the 'DeepMatching' between two images.")
p("Images must be HxWx3 numpy arrays (converted to float32).")
p("Options is an optional string argument ('' by default).")
p("The function returns a numpy array with 6 columns, each row being x1 y1 x2 y2 score index.")
p("(index refers to the local maximum from which the match was retrieved)")
p("Version 1.2.2")
break;
}
p("")
p("Options:")
p(" -h, --help print this message")
//p(" HOG parameters (low-level pixel descriptor):")
//p(" -png_settings (auto) recommended for uncompressed images")
//p(" -jpg_settings (auto) recommended for compressed images")
//p(" in more details: (for fine-tuning)")
//p(" -hog.presm <f=1.0> prior image smoothing")
//p(" -hog.midsm <f=1.0> intermediate HOG smoothing")
//p(" -hog.sig <f=0.2> sigmoid strength")
//p(" -hog.postsm <f=1.0> final HOG-smoothing")
//p(" -hog.ninth <f=0.3> robustness to pixel noise (eg. JPEG artifacts)")
p("")
p(" Matching parameters:")
//p(" -iccv_settings settings used for the ICCV paper")
//p(" -improved_settings (default) supposedly improved settings")
//p(" in more details: (for fine-tuning)")
p(" -downscale/-R <n=1> downsize the input images by a factor 2^n")
//p(" -overlap <n=999> use overlapping patches in image1 from level n")
//p(" -subref <n=0> 0: denser sampling or 1: not of image1 patches")
p(" -ngh_rad <n=0> if n>0: restrict matching to n pxl neighborhood")
p(" -nlpow <f=1.4> non-linear rectification x := x^f")
//p(" -maxima_mode <n=0> 0: from all top cells / 1: from local maxima")
//p(" -min_level <n=2> skip maxima in levels [0, 1, ..., n-1]")
p(" -mem <n=1> if n>0: optimize memory footprint (bit unstable)")
//p(" -scoring_mode <n=1> type of correspondence scoring mode (0/1)")
p("")
p(" Fully scale & rotation invariant DeepMatching:")
p(" if either one of these options is used, then this mode is activated:")
p(" -max_scale <factor=5> max scaling factor")
p(" -rot_range <from=0> <to=360> rotation range")
p("")
p(" Other parameters:")
p(" -resize <width> <height> to resize input images beforehand")
p(" -v increase verbosity")
p(" -nt <n> multi-threading with <n> threads")
if(language==EXE_OPTIONS) {
p(" -out <file_name> output correspondences in a file")
exit(1);}
}
bool endswith(const char *str, const char *suffix)
{
if(!str || !suffix) return false;
size_t lenstr = strlen(str);
size_t lensuffix = strlen(suffix);
if(lensuffix > lenstr) return false;
return strncmp(str + lenstr - lensuffix, suffix, lensuffix) == 0;
}
image_t* rescale_image( image_t* im, int width, int height )
{
image_t* res = image_new(width,height);
image_resize_bilinear_newsize(res, im, width, height);
image_delete(im);
return res;
}
const char *parse_options(dm_params_t *params, scalerot_params_t *sr_params, bool *use_scalerot, float *fx, float *fy, const int argc, const char **argv, const int language, image_t **im1, image_t **im2) {
int current_arg = 0;
const char* out_filename = NULL;
// parse options
while(current_arg < argc)
{
const char* a = argv[current_arg++];
#define isarg(key) !strcmp(a,key)
if(isarg("-h") || isarg("--help") ) usage(language);
// HOG and patch parameters
//else if(isarg("-hog.presm"))
// params->desc_params.presmooth_sigma = atof(argv[current_arg++]);
//else if(isarg("-hog.sig"))
// params->desc_params.hog_sigmoid = atof(argv[current_arg++]);
//else if(isarg("-hog.midsm"))
// params->desc_params.mid_smoothing = atof(argv[current_arg++]);
//else if(isarg("-hog.postsm"))
// params->desc_params.post_smoothing = atof(argv[current_arg++]);
//else if(isarg("-hog.ninth"))
// params->desc_params.ninth_dim = atof(argv[current_arg++]);
//else if(isarg("-hog.nrmpix"))
// params->desc_params.norm_pixels = atof(argv[current_arg++]);
else if(isarg("-png_settings")) {
params->desc_params.presmooth_sigma = 0; // no image smoothing since the image is uncompressed
params->desc_params.hog_sigmoid = 0.2;
params->desc_params.mid_smoothing = 1.5;
params->desc_params.post_smoothing = 1;
params->desc_params.ninth_dim = 0.1; } // low ninth_dim since image PSNR is high
else if(isarg("-jpg_settings")) {
params->desc_params.presmooth_sigma = 1; // smooth the image to remove jpg artifacts
params->desc_params.hog_sigmoid = 0.2;
params->desc_params.mid_smoothing = 1.5;
params->desc_params.post_smoothing = 1;
params->desc_params.ninth_dim = 0.3; } // higher ninth_dim because of pixel noise
// matching parameters
else if(isarg("-R") || isarg("-downscale"))
params->prior_img_downscale = atoi(argv[current_arg++]);
//else if(isarg("-overlap"))
// params->overlap = atoi(argv[current_arg++]);
//else if(isarg("-subref"))
// params->subsample_ref = atoi(argv[current_arg++]);
else if(isarg("-nlpow"))
params->nlpow = atof(argv[current_arg++]);
else if(isarg("-ngh_rad"))
params->ngh_rad = atoi(argv[current_arg++]);
// maxima parameters
//else if(isarg("-maxima_mode"))
// params->maxima_mode = atoi(argv[current_arg++]);
else if(isarg("-mem")) {
params->low_mem = atoi(argv[current_arg++]); }
//else if(isarg("-min_level"))
// params->min_level = atoi(argv[current_arg++]);
//else if(isarg("-scoring_mode"))
// params->scoring_mode = atoi(argv[current_arg++]);
//else if(isarg("-iccv_settings")) {
// params->prior_img_downscale = 2;
// params->overlap = 0; // overlap from level 0
// params->subsample_ref = 1;
// params->nlpow = 1.6;
// params->maxima_mode = 1;
// params->low_mem = 0;
// params->min_level = 2;
// params->scoring_mode = 0; }
//else if(isarg("-improved_settings")) {
// params->prior_img_downscale = 1; // less down-scale
// params->overlap = 999; // no overlap
// params->subsample_ref = 0; // dense patch sampling at every level in first image
// params->nlpow = 1.4;
// params->maxima_mode = 0;
// params->low_mem = 1;
// params->min_level = 2;
// params->scoring_mode = 1; } // improved scoring
//else if(isarg("-max_psize")) {
// params->max_psize = atoi(argv[current_arg++]); }
// scale & rot invariant version
else if(isarg("-scale") || isarg("-max_scale")) {
*use_scalerot = true;
float scale = atof(argv[current_arg++]);
sr_params->max_sc0 = sr_params->max_sc1 = int(1 + 2*log2(scale)); }
else if(isarg("-rot") || isarg("-rot_range")) {
*use_scalerot = true;
int min_rot = atoi(argv[current_arg++]);
int max_rot = atoi(argv[current_arg++]);
while( min_rot < 0 ) {
min_rot += 360;
max_rot += 360;
}
sr_params->min_rot = int(floor(0.5 + min_rot/45.));
sr_params->max_rot = int(floor(1.5 + max_rot/45.));
while( sr_params->max_rot - sr_params->min_rot > 8 )
sr_params->max_rot--;
assert( sr_params->min_rot < sr_params->max_rot ); }
// other parameters
else if(isarg("-resize")) {
assert((*im1)->width==(*im2)->width && (*im1)->height==(*im2)->height);
int width = atoi(argv[current_arg++]);
int height = atoi(argv[current_arg++]);
*fx *= (*im1)->width / float(width);
*fy *= (*im1)->height / float(height);
*im1 = rescale_image(*im1, width, height);
*im2 = rescale_image(*im2, width, height); }
else if(isarg("-v"))
params->verbose++;
else if(isarg("-nt")) {
params->n_thread = atoi(argv[current_arg++]);
if (params->n_thread==0)
params->n_thread = std::thread::hardware_concurrency(); }
else if(language == EXE_OPTIONS && isarg("-out"))
out_filename = argv[current_arg++];
else {
err_printf("error: unexpected parameter '%s'", a);
exit(-1);
}
}
if( *use_scalerot )
assert( params->ngh_rad == 0 || !"max trans cannot be used in full scale and rotation mode");
else
if( params->subsample_ref && (!ispowerof2((*im1)->width) || !ispowerof2((*im1)->height)) ) {
err_printf("WARNING: first image has dimension which are not power-of-2\n");
err_printf("For improved results, you should consider resizing the images with '-resize <w> <h>'\n");
}
return out_filename;
}
int main(int argc, const char ** argv)
{
if( argc<=2 || !strcmp(argv[1],"-h") || !strcmp(argv[1],"--help") ) usage(EXE_OPTIONS);
int current_arg = 3;
image_t *im1=NULL, *im2=NULL;
{
color_image_t *cim1 = color_image_load(argv[1]);
color_image_t *cim2 = color_image_load(argv[2]);
// Following deactivated because quite useless/dangerous in practice
// default behavior == always using -jpg_settings
//if( endswith(argv[1],"png") || endswith(argv[1],"PNG") )
// argv[--current_arg] = "-png_settings"; // set default
//if( endswith(argv[1],"ppm") || endswith(argv[1],"PPM") )
// argv[--current_arg] = "-png_settings"; // set default
//if( endswith(argv[1],"jpg") || endswith(argv[1],"JPG") )
// argv[--current_arg] = "-jpg_settings"; // set default
//if( endswith(argv[1],"jpeg") || endswith(argv[1],"JPEG") )
// argv[--current_arg] = "-jpg_settings"; // set default
im1 = image_gray_from_color(cim1);
im2 = image_gray_from_color(cim2);
color_image_delete(cim1);
color_image_delete(cim2);
}
// set params to default
dm_params_t params;
set_default_dm_params(¶ms);
scalerot_params_t sr_params;
set_default_scalerot_params(&sr_params);
bool use_scalerot = false;
float fx=1, fy=1;
// parse options
const char* out_filename = parse_options(¶ms, &sr_params, &use_scalerot, &fx, &fy, argc-current_arg,
&argv[current_arg], EXE_OPTIONS, &im1, &im2);
// compute deep matching
float_image* corres = use_scalerot ?
deep_matching_scale_rot( im1, im2, ¶ms, &sr_params ) :
deep_matching ( im1, im2, ¶ms, NULL ); // standard call
// save result
output_correspondences( out_filename, (corres_t*)corres->pixels, corres->ty, fx, fy );
free_image(corres);
image_delete(im1);
image_delete(im2);
return 0;
}
Event Timeline
Log In to Comment