pfshdrcalibrate.cpp (pfstools-2.1.0.tgz) | : | pfshdrcalibrate.cpp (pfstools-2.2.0.tgz) | ||
---|---|---|---|---|
skipping to change at line 34 | skipping to change at line 34 | |||
* | * | |||
* @author Grzegorz Krawczyk, <krawczyk@mpi-sb.mpg.de> | * @author Grzegorz Krawczyk, <krawczyk@mpi-sb.mpg.de> | |||
* @author Ivo Ihrke, <ihrke@mmci.uni-saarland.de> | * @author Ivo Ihrke, <ihrke@mmci.uni-saarland.de> | |||
* | * | |||
* $Id: pfshdrcalibrate.cpp,v 1.16 2011/02/24 17:35:59 ihrke Exp $ | * $Id: pfshdrcalibrate.cpp,v 1.16 2011/02/24 17:35:59 ihrke Exp $ | |||
*/ | */ | |||
#include <config.h> | #include <config.h> | |||
#include <iostream> | #include <iostream> | |||
#include <sstream> | ||||
#include <vector> | #include <vector> | |||
#include <stdio.h> | #include <stdio.h> | |||
#include <stdlib.h> | #include <stdlib.h> | |||
#include <math.h> | #include <math.h> | |||
#include <getopt.h> | #include <getopt.h> | |||
#include <pfs.h> | #include <pfs.h> | |||
#include <responses.h> | #include <responses.h> | |||
#include <robertson02.h> | #include <robertson02.h> | |||
#include <mitsunaga99.h> | #include <mitsunaga99.h> | |||
#include <string> | ||||
using namespace std; | using namespace std; | |||
#define PROG_NAME "pfshdrcalibrate" | #define PROG_NAME "pfshdrcalibrate" | |||
inline float max3( float a, float b, float c ) | inline float max3( float a, float b, float c ) | |||
{ | { | |||
float max = (a>b) ? a : b; | float max = (a>b) ? a : b; | |||
return (c>max) ? c : max; | return (c>max) ? c : max; | |||
} | } | |||
skipping to change at line 84 | skipping to change at line 87 | |||
}; | }; | |||
void printHelp() | void printHelp() | |||
{ | { | |||
fprintf( stderr, PROG_NAME ": \n" | fprintf( stderr, PROG_NAME ": \n" | |||
"\t[--calibration <type>] [--luminance]\n" | "\t[--calibration <type>] [--luminance]\n" | |||
"\t[--response <type>] [--response-file <filename.m>] \n" | "\t[--response <type>] [--response-file <filename.m>] \n" | |||
"\t[--save-response <filename.m>] \n" | "\t[--save-response <filename.m>] \n" | |||
"\t[--multiplier <val>] \n" | "\t[--multiplier <val>] \n" | |||
"\t[--bpp <val>] \n" | "\t[--bpp <val>] \n" | |||
"\t[--saturation-offset <val>] \n" | ||||
"\t[--deghosting <val>] \n" | ||||
"\t[--noise-parameters <val>] \n" | ||||
"\t[--verbose] [--help]\n" | "\t[--verbose] [--help]\n" | |||
"See man page for more information.\n" ); | "See man page for more information.\n" ); | |||
} | } | |||
void pfshdrcalibrate( int argc, char* argv[] ) | void pfshdrcalibrate( int argc, char* argv[] ) | |||
{ | { | |||
/* --------------------------------------------------------------------------- --------------------- */ | /* --------------------------------------------------------------------------- --------------------- */ | |||
/* -------------------------------- initialization start --------------------- --------------------- */ | /* -------------------------------- initialization start --------------------- --------------------- */ | |||
/* --------------------------------------------------------------------------- --------------------- */ | /* --------------------------------------------------------------------------- --------------------- */ | |||
pfs::DOMIO pfsio; | pfs::DOMIO pfsio; | |||
enum TCalibration | enum TCalibration | |||
{ NONE, CALIBRATE } opt_calibration = CALIBRATE; | { NONE, CALIBRATE } opt_calibration = CALIBRATE; | |||
enum TResponse | enum TResponse | |||
{ FROM_FILE, LINEAR, GAMMA, LOG10 } opt_response = LINEAR; | { FROM_FILE, LINEAR, GAMMA, LOG10 } opt_response = LINEAR; | |||
enum TMethod | enum TMethod | |||
{ ROBERTSON_METHOD, MITSUNAGA_METHOD } opt_method = ROBERTSON_METHOD; | { ROBERTSON_METHOD, MITSUNAGA_METHOD } opt_method = ROBERTSON_METHOD; | |||
noise_parameters camera_presets[] = { | ||||
{ "Empty", {1, 1, 1}, 0, 0 }, | ||||
{ "SonyA7r1", {1.308256, 1.321364, 1.28384}, 2.796408, 0.1434412 }, | ||||
{ "CanonT1", {5.45232, 4.73024, 4.61276}, 3.752112, 20.021 }, | ||||
{ "SonyA7r3", {1.688176, 1.537108, 1.555868}, 2.820508, 12.1138 } | ||||
}; | ||||
/* defaults */ | /* defaults */ | |||
float input_multiplier = 1.0f; | float input_multiplier = 1.0f; | |||
FILE *responseFile = NULL; | FILE *responseFile = NULL; | |||
FILE *responseSaveFile = NULL; | FILE *responseSaveFile = NULL; | |||
int opt_bpp = 8; | int opt_bpp = 8; | |||
bool opt_fillgaps = false; /* todo remove */ | bool opt_fillgaps = false; /* todo remove */ | |||
bool opt_luminance = false; | bool opt_luminance = false; | |||
float opt_gauss = 0.2; | float opt_gauss = 0.2; | |||
int opt_maxresponse = -1; | int opt_maxresponse = -1; | |||
int opt_minresponse = -1; | int opt_minresponse = -1; | |||
unsigned long mitsunaga_sample_no = MITSUNAGA_SAMPLES_NO; | unsigned long mitsunaga_sample_no = MITSUNAGA_SAMPLES_NO; | |||
bool opt_deghosting = false; | int opt_saturation_offset = -1; | |||
float opt_saturation_offset_perc = -1; | ||||
float opt_deghosting = -1; | ||||
noise_parameters *camera = &camera_presets[0]; | ||||
/* helper */ | /* helper */ | |||
int c; | int c; | |||
static struct option cmdLineOptions[] = { | static struct option cmdLineOptions[] = { | |||
{ "help", no_argument, NULL, 'h' }, | { "help", no_argument, NULL, 'h' }, | |||
{ "verbose", no_argument, NULL, 'v' }, | { "verbose", no_argument, NULL, 'v' }, | |||
{ "luminance", no_argument, NULL, 'Y' }, | { "luminance", no_argument, NULL, 'Y' }, | |||
{ "method", required_argument, NULL, 'c' }, | { "method", required_argument, NULL, 'c' }, | |||
{ "gauss", required_argument, NULL, 'g' }, | { "gauss", required_argument, NULL, 'g' }, | |||
{ "max-response", required_argument, NULL, 'A' }, | { "max-response", required_argument, NULL, 'A' }, | |||
{ "min-response", required_argument, NULL, 'S' }, | { "min-response", required_argument, NULL, 'S' }, | |||
{ "response", required_argument, NULL, 'r' }, | { "response", required_argument, NULL, 'r' }, | |||
{ "response-file", required_argument, NULL, 'f' }, | { "response-file", required_argument, NULL, 'f' }, | |||
{ "save-response", required_argument, NULL, 's' }, | { "save-response", required_argument, NULL, 's' }, | |||
{ "multiplier", required_argument, NULL, 'm' }, | { "multiplier", required_argument, NULL, 'm' }, | |||
{ "bpp", required_argument, NULL, 'b' }, | { "bpp", required_argument, NULL, 'b' }, | |||
{ "samples", required_argument, NULL, 'p' }, | { "samples", required_argument, NULL, 'p' }, | |||
{ "deghosting", no_argument, NULL, 'd' }, | { "saturation-offset", required_argument, NULL, 'o' }, | |||
{ "deghosting", required_argument, NULL, 'd' }, | ||||
{ "noise-parameters", required_argument, NULL, 'n'}, | ||||
{ NULL, 0, NULL, 0 } | { NULL, 0, NULL, 0 } | |||
}; | }; | |||
int optionIndex = 0; | int optionIndex = 0; | |||
while( ( c = getopt_long( argc, | while( ( c = getopt_long( argc, | |||
argv, | argv, | |||
"hvYc:g:r:f:s:m:b:p:xd", | "hvYc:g:r:f:s:m:b:p:xo:d:n:", | |||
cmdLineOptions, | cmdLineOptions, | |||
&optionIndex) ) | &optionIndex) ) | |||
!= -1 ) | != -1 ) | |||
{ | { | |||
switch( c ) | switch( c ) | |||
{ | { | |||
/* help */ | /* help */ | |||
case 'h': | case 'h': | |||
printHelp(); | printHelp(); | |||
skipping to change at line 263 | skipping to change at line 281 | |||
if( opt_maxresponse<=opt_minresponse ) | if( opt_maxresponse<=opt_minresponse ) | |||
throw pfs::Exception("max response should be higher than min response "); | throw pfs::Exception("max response should be higher than min response "); | |||
break; | break; | |||
case 'S': // min response | case 'S': // min response | |||
opt_minresponse = atoi(optarg); | opt_minresponse = atoi(optarg); | |||
if( opt_minresponse<0 ) | if( opt_minresponse<0 ) | |||
throw pfs::Exception("min response should be >0"); | throw pfs::Exception("min response should be >0"); | |||
break; | break; | |||
case 'o': | ||||
opt_saturation_offset_perc = atof(optarg); | ||||
if( opt_saturation_offset_perc < 0 || opt_saturation_offset_perc > 0.5 ) | ||||
throw pfs::Exception("saturation offset should be between 0 and 0.5"); | ||||
break; | ||||
case 'd': | case 'd': | |||
opt_deghosting = true; | if( !optarg ) | |||
opt_deghosting = 2; | ||||
else | ||||
opt_deghosting = atof(optarg); | ||||
if( opt_deghosting<0 ) | ||||
throw pfs::Exception("deghosting threshold should be >0"); | ||||
break; | break; | |||
case 'n': | ||||
{ | ||||
int i = 0; | ||||
if( isalpha(optarg[0]) ) | ||||
{ | ||||
// Name of a camera, whose noise parameters are known, is provided | ||||
for( int i = 0; i < sizeof(camera_presets)/sizeof(*camera_presets); i++ ) | ||||
if( strcmp( optarg, camera_presets[i].camera_name ) == 0 ) | ||||
camera = &camera_presets[i]; | ||||
if( strcmp( optarg, "Empty" ) != 0 && strcmp( camera->camera_name, "Empty" | ||||
) == 0 ) | ||||
throw pfs::Exception("specified camera noise parameters not found"); | ||||
} | ||||
else if( isdigit(optarg[0]) ) | ||||
{ | ||||
// Custom noise parameters provided as a comma separated list | ||||
stringstream sstream(optarg); | ||||
string token; | ||||
for( int cc = 0; cc < 3; cc++ ) | ||||
{ | ||||
camera->camera_name = "Custom"; | ||||
if( !getline(sstream, token, ',') ) | ||||
throw pfs::Exception("invalid noise parameters"); | ||||
camera->color_coefficients[cc] = atof(token.c_str()); | ||||
} | ||||
if( !getline(sstream, token, ',') ) | ||||
throw pfs::Exception("invalid noise parameters"); | ||||
camera->std_readout = atof(token.c_str()); | ||||
if( !getline(sstream, token, ',') ) | ||||
throw pfs::Exception("invalid noise parameters"); | ||||
camera->std_adc = atof(token.c_str()); | ||||
if( getline(sstream, token, ',') ) | ||||
throw pfs::Exception("invalid noise parameters"); | ||||
} | ||||
else | ||||
throw pfs::Exception("invalid noise parameters"); | ||||
break; | ||||
} | ||||
case '?': | case '?': | |||
throw QuietException(); | throw QuietException(); | |||
case ':': | case ':': | |||
throw QuietException(); | throw QuietException(); | |||
} | } | |||
} | } | |||
/* FIX: this is most important, use fixed 0-1 range */ | /* FIX: this is most important, use fixed 0-1 range */ | |||
//!! FIX | //!! FIX | |||
skipping to change at line 326 | skipping to change at line 395 | |||
case LOG10: | case LOG10: | |||
VERBOSE_STR << "initial response: logarithmic" << endl; | VERBOSE_STR << "initial response: logarithmic" << endl; | |||
break; | break; | |||
default: | default: | |||
throw pfs::Exception("undefined standard response"); | throw pfs::Exception("undefined standard response"); | |||
break; | break; | |||
} | } | |||
if( opt_saturation_offset_perc==-1 ) { | ||||
// By default, use 1% of the maximum value as the saturation offset (pixels ab | ||||
ove 99 of the max pixel value will be considered as saturated) | ||||
opt_saturation_offset_perc = 0.01; | ||||
} | ||||
opt_saturation_offset = (int) (powf( 2.0f, opt_bpp )*opt_saturation_offset_perc | ||||
+ 0.5); | ||||
// VERBOSE_STR << "interpolate missing parts of response: " | // VERBOSE_STR << "interpolate missing parts of response: " | |||
// << (opt_fillgaps ? "yes" : "no") << endl; | // << (opt_fillgaps ? "yes" : "no") << endl; | |||
if( responseSaveFile != NULL ) | if( responseSaveFile != NULL ) | |||
VERBOSE_STR << "save response curve to a file" << endl; | VERBOSE_STR << "save response curve to a file" << endl; | |||
// number of input levels | // number of input levels | |||
int M = (int) powf( 2.0f, opt_bpp ); | int M = (int) powf( 2.0f, opt_bpp ); | |||
VERBOSE_STR << "number of input levels: " << M << endl; | VERBOSE_STR << "number of input levels: " << M << endl; | |||
VERBOSE_STR << "input multiplier: " << input_multiplier << endl; | VERBOSE_STR << "input multiplier: " << input_multiplier << endl; | |||
skipping to change at line 774 | skipping to change at line 849 | |||
} | } | |||
else | else | |||
{ | { | |||
pfs::Array2D *RGB_out[3] = { Xj, Yj, Zj }; | pfs::Array2D *RGB_out[3] = { Xj, Yj, Zj }; | |||
const ExposureList *exposures[] = { &imgsR, &imgsG, &imgsB }; | const ExposureList *exposures[] = { &imgsR, &imgsG, &imgsB }; | |||
const float *resp_curves[] = { Ir, Ig, Ib }; | const float *resp_curves[] = { Ir, Ig, Ib }; | |||
VERBOSE_STR << "applying response to RGB channels..." << endl; | VERBOSE_STR << "applying response to RGB channels..." << endl; | |||
sp = robertson02_applyResponseRGB( RGB_out, exposures, resp_curves, w, M, opt_deghosting ); | sp = robertson02_applyResponseRGB( RGB_out, exposures, resp_curves, w, M - opt_saturation_offset, camera, opt_deghosting); | |||
/* | /* | |||
VERBOSE_STR << "applying response to R channel..." << endl; | VERBOSE_STR << "applying response to R channel..." << endl; | |||
sp = robertson02_applyResponse( Xj, imgsR, Ir, w, M); | sp = robertson02_applyResponse( Xj, imgsR, Ir, w, M); | |||
VERBOSE_STR << "applying response to G channel..." << endl; | VERBOSE_STR << "applying response to G channel..." << endl; | |||
sp += robertson02_applyResponse( Yj, imgsG, Ig, w, M); | sp += robertson02_applyResponse( Yj, imgsG, Ig, w, M); | |||
VERBOSE_STR << "applying response to B channel..." << endl; | VERBOSE_STR << "applying response to B channel..." << endl; | |||
sp += robertson02_applyResponse( Zj, imgsB, Ib, w, M); | sp += robertson02_applyResponse( Zj, imgsB, Ib, w, M); | |||
End of changes. 12 change blocks. | ||||
5 lines changed or deleted | 83 lines changed or added |