@ -43,6 +43,7 @@
# include "precomp.hpp"
# include "opencv2/photo.hpp"
# include "opencv2/imgproc.hpp"
//#include "opencv2/highgui.hpp"
# include "hdr_common.hpp"
namespace cv
@ -51,11 +52,12 @@ namespace cv
class CalibrateDebevecImpl : public CalibrateDebevec
{
public :
CalibrateDebevecImpl ( int samples , float lambda ) :
CalibrateDebevecImpl ( int samples , float lambda , bool random ) :
samples ( samples ) ,
lambda ( lambda ) ,
name ( " CalibrateDebevec " ) ,
w ( tringleWeights ( ) )
w ( tringleWeights ( ) ) ,
random ( random )
{
}
@ -71,28 +73,44 @@ public:
int channels = images [ 0 ] . channels ( ) ;
int CV_32FCC = CV_MAKETYPE ( CV_32F , channels ) ;
dst . create ( 256 , 1 , CV_32FCC ) ;
dst . create ( LDR_SIZE , 1 , CV_32FCC ) ;
Mat result = dst . getMat ( ) ;
std : : vector < Point > sample_points ;
if ( random ) {
for ( int i = 0 ; i < samples ; i + + ) {
sample_points . push_back ( Point ( rand ( ) % images [ 0 ] . cols , rand ( ) % images [ 0 ] . rows ) ) ;
}
} else {
int x_points = sqrt ( static_cast < double > ( samples ) * images [ 0 ] . cols / images [ 0 ] . rows ) ;
int y_points = samples / x_points ;
int step_x = images [ 0 ] . cols / x_points ;
int step_y = images [ 0 ] . rows / y_points ;
for ( int i = 0 , x = step_x / 2 ; i < x_points ; i + + , x + = step_x ) {
for ( int j = 0 , y = step_y ; j < y_points ; j + + , y + = step_y ) {
sample_points . push_back ( Point ( x , y ) ) ;
}
}
}
std : : vector < Mat > result_split ( channels ) ;
for ( int channel = 0 ; channel < channels ; channel + + ) {
Mat A = Mat : : zeros ( samples * images . size ( ) + 257 , 256 + samples , CV_32F ) ;
Mat A = Mat : : zeros ( sample_point s . size ( ) * images . size ( ) + LDR_SIZE + 1 , LDR_SIZE + sample_point s . size ( ) , CV_32F ) ;
Mat B = Mat : : zeros ( A . rows , 1 , CV_32F ) ;
int eq = 0 ;
for ( int i = 0 ; i < samples ; i + + ) {
int pos = 3 * ( rand ( ) % images [ 0 ] . total ( ) ) + channel ;
for ( size_t i = 0 ; i < sample_points . size ( ) ; i + + ) {
for ( size_t j = 0 ; j < images . size ( ) ; j + + ) {
int val = ( images [ j ] . ptr ( ) + pos ) [ 0 ] ;
int val = images [ j ] . ptr ( ) [ 3 * ( sample_points [ i ] . y * images [ j ] . cols + sample_points [ j ] . x ) + channel ] ;
A . at < float > ( eq , val ) = w . at < float > ( val ) ;
A . at < float > ( eq , 256 + i ) = - w . at < float > ( val ) ;
A . at < float > ( eq , LDR_SIZE + i ) = - w . at < float > ( val ) ;
B . at < float > ( eq , 0 ) = w . at < float > ( val ) * log ( times [ j ] ) ;
eq + + ;
}
}
A . at < float > ( eq , 1 28 ) = 1 ;
A . at < float > ( eq , LDR_SIZE / 2 ) = 1 ;
eq + + ;
for ( int i = 0 ; i < 254 ; i + + ) {
@ -103,7 +121,7 @@ public:
}
Mat solution ;
solve ( A , B , solution , DECOMP_SVD ) ;
solution . rowRange ( 0 , 256 ) . copyTo ( result_split [ channel ] ) ;
solution . rowRange ( 0 , LDR_SIZE ) . copyTo ( result_split [ channel ] ) ;
}
merge ( result_split , result ) ;
exp ( result , result ) ;
@ -115,11 +133,15 @@ public:
float getLambda ( ) const { return lambda ; }
void setLambda ( float val ) { lambda = val ; }
bool getRandom ( ) const { return random ; }
void setRandom ( bool val ) { random = val ; }
void write ( FileStorage & fs ) const
{
fs < < " name " < < name
< < " samples " < < samples
< < " lambda " < < lambda ;
< < " lambda " < < lambda
< < " random " < < static_cast < int > ( random ) ;
}
void read ( const FileNode & fn )
@ -128,18 +150,21 @@ public:
CV_Assert ( n . isString ( ) & & String ( n ) = = name ) ;
samples = fn [ " samples " ] ;
lambda = fn [ " lambda " ] ;
int random_val = fn [ " random " ] ;
random = static_cast < bool > ( random_val ) ;
}
protected :
String name ;
int samples ;
float lambda ;
bool random ;
Mat w ;
} ;
Ptr < CalibrateDebevec > createCalibrateDebevec ( int samples , float lambda )
Ptr < CalibrateDebevec > createCalibrateDebevec ( int samples , float lambda , bool random )
{
return new CalibrateDebevecImpl ( samples , lambda ) ;
return new CalibrateDebevecImpl ( samples , lambda , random ) ;
}
class CalibrateRobertsonImpl : public CalibrateRobertson
@ -165,20 +190,14 @@ public:
int channels = images [ 0 ] . channels ( ) ;
int CV_32FCC = CV_MAKETYPE ( CV_32F , channels ) ;
dst . create ( 256 , 1 , CV_32FCC ) ;
dst . create ( LDR_SIZE , 1 , CV_32FCC ) ;
Mat response = dst . getMat ( ) ;
response = linearResponse ( 3 ) / ( LDR_SIZE / 2.0f ) ;
response = Mat : : zeros ( 256 , 1 , CV_32FCC ) ;
for ( int i = 0 ; i < 256 ; i + + ) {
for ( int c = 0 ; c < channels ; c + + ) {
response . at < Vec3f > ( i ) [ c ] = i / 128.0 ;
}
}
Mat card = Mat : : zeros ( 256 , 1 , CV_32FCC ) ;
for ( int i = 0 ; i < images . size ( ) ; i + + ) {
Mat card = Mat : : zeros ( LDR_SIZE , 1 , CV_32FCC ) ;
for ( size_t i = 0 ; i < images . size ( ) ; i + + ) {
uchar * ptr = images [ i ] . ptr ( ) ;
for ( in t pos = 0 ; pos < images [ i ] . total ( ) ; pos + + ) {
for ( size_t pos = 0 ; pos < images [ i ] . total ( ) ; pos + + ) {
for ( int c = 0 ; c < channels ; c + + , ptr + + ) {
card . at < Vec3f > ( * ptr ) [ c ] + = 1 ;
}
@ -186,43 +205,34 @@ public:
}
card = 1.0 / card ;
Ptr < MergeRobertson > merge = createMergeRobertson ( ) ;
for ( int iter = 0 ; iter < max_iter ; iter + + ) {
Scalar channel_err ( 0 , 0 , 0 ) ;
Mat radiance = Mat : : zeros ( images [ 0 ] . size ( ) , CV_32FCC ) ;
Mat wsum = Mat : : zeros ( images [ 0 ] . size ( ) , CV_32FCC ) ;
for ( int i = 0 ; i < images . size ( ) ; i + + ) {
Mat im , w ;
LUT ( images [ i ] , weight , w ) ;
LUT ( images [ i ] , response , im ) ;
Mat err_mat ;
pow ( im - times [ i ] * radiance , 2.0f , err_mat ) ;
err_mat = w . mul ( err_mat ) ;
channel_err + = sum ( err_mat ) ;
radiance + = times [ i ] * w . mul ( im ) ;
wsum + = pow ( times [ i ] , 2 ) * w ;
}
float err = ( channel_err [ 0 ] + channel_err [ 1 ] + channel_err [ 2 ] ) / ( channels * radiance . total ( ) ) ;
radiance = radiance . mul ( 1 / wsum ) ;
radiance = Mat : : zeros ( images [ 0 ] . size ( ) , CV_32FCC ) ;
merge - > process ( images , radiance , times , response ) ;
float * rad_ptr = radiance . ptr < float > ( ) ;
response = Mat : : zeros ( 256 , 1 , CV_32FC3 ) ;
for ( int i = 0 ; i < images . size ( ) ; i + + ) {
Mat new_response = Mat : : zeros ( LDR_SIZE , 1 , CV_32FC3 ) ;
for ( size_t i = 0 ; i < images . size ( ) ; i + + ) {
uchar * ptr = images [ i ] . ptr ( ) ;
for ( int pos = 0 ; pos < images [ i ] . total ( ) ; pos + + ) {
float * rad_ptr = radiance . ptr < float > ( ) ;
for ( size_t pos = 0 ; pos < images [ i ] . total ( ) ; pos + + ) {
for ( int c = 0 ; c < channels ; c + + , ptr + + , rad_ptr + + ) {
response . at < Vec3f > ( * ptr ) [ c ] + = times [ i ] * * rad_ptr ;
new_response . at < Vec3f > ( * ptr ) [ c ] + = times [ i ] * * rad_ptr ;
}
}
}
response = response . mul ( card ) ;
new_response = new_response . mul ( card ) ;
for ( int c = 0 ; c < 3 ; c + + ) {
for ( int i = 0 ; i < 256 ; i + + ) {
response . at < Vec3f > ( i ) [ c ] / = response . at < Vec3f > ( 128 ) [ c ] ;
float middle = new_response . at < Vec3f > ( LDR_SIZE / 2 ) [ c ] ;
for ( int i = 0 ; i < LDR_SIZE ; i + + ) {
new_response . at < Vec3f > ( i ) [ c ] / = middle ;
}
}
float diff = sum ( sum ( abs ( new_response - response ) ) ) [ 0 ] / channels ;
new_response . copyTo ( response ) ;
if ( diff < threshold ) {
break ;
}
}
}
@ -232,6 +242,8 @@ public:
float getThreshold ( ) const { return threshold ; }
void setThreshold ( float val ) { threshold = val ; }
Mat getRadiance ( ) const { return radiance ; }
void write ( FileStorage & fs ) const
{
fs < < " name " < < name
@ -251,7 +263,7 @@ protected:
String name ;
int max_iter ;
float threshold ;
Mat weight ;
Mat weight , radiance ;
} ;
Ptr < CalibrateRobertson > createCalibrateRobertson ( int max_iter , float threshold )