00001 #include "TePDIContrast.hpp"
00002
00003 #include "../kernel/TeAgnostic.h"
00004 #include "TePDITypes.hpp"
00005 #include "TePDIUtils.hpp"
00006 #include "TePDIHistogram.hpp"
00007 #include "TePDIMatrix.hpp"
00008
00009 #include <math.h>
00010 #include <float.h>
00011
00012
00013 TePDIContrast::TePDIContrast()
00014 {
00015 }
00016
00017
00018 TePDIContrast::~TePDIContrast()
00019 {
00020 }
00021
00022
00023 bool TePDIContrast::RunImplementation()
00024 {
00025
00026
00027 TePDIContrastType contrast_type;
00028 params_.GetParameter( "contrast_type", contrast_type );
00029
00030 TePDITypes::TePDIRasterPtrType inRaster;
00031 int input_band = 0;
00032 if( params_.CheckParameter< TePDITypes::TePDIRasterPtrType >(
00033 "input_image" ) ) {
00034
00035 params_.GetParameter( "input_image", inRaster );
00036 params_.GetParameter( "input_band", input_band );
00037 }
00038
00039 int output_band = 0;
00040 TePDITypes::TePDIRasterPtrType outRaster;
00041 if( params_.CheckParameter< TePDITypes::TePDIRasterPtrType >(
00042 "output_image" ) ) {
00043
00044 params_.GetParameter( "output_image", outRaster );
00045 params_.GetParameter( "output_band", output_band );
00046 }
00047
00048 double min_level = 0;
00049 double max_level = 0;
00050 if( params_.CheckParameter< double >( "min_level" ) ) {
00051
00052 params_.GetParameter( "min_level", min_level );
00053 }
00054 if( params_.CheckParameter< double >( "max_level" ) ) {
00055
00056 params_.GetParameter( "max_level", max_level );
00057 }
00058
00059 TePDIRgbPalette::pointer palette;
00060 if( params_.CheckParameter< TePDIRgbPalette::pointer >( "rgb_palette" ) ) {
00061
00062 params_.GetParameter( "rgb_palette", palette );
00063 }
00064
00065
00066
00067 bool output_raster_uses_dummy = false;
00068 double output_raster_dummy = 0;
00069
00070 if( outRaster.isActive() ) {
00071 output_raster_uses_dummy = outRaster->params().useDummy_;
00072
00073 if( output_raster_uses_dummy ) {
00074 output_raster_dummy = outRaster->params().dummy_[ 0 ];
00075 }
00076 }
00077
00078 if( params_.CheckParameter< double >( "dummy_value" ) ) {
00079
00080 params_.GetParameter( "dummy_value", output_raster_dummy );
00081
00082 output_raster_uses_dummy = true;
00083 }
00084
00085
00086
00087 if( outRaster.isActive() ) {
00088 switch( contrast_type ) {
00089 case TePDIContrastSimpleSlicer :
00090 {
00091 bool output_reset_not_needed = true;
00092
00093 if( ! params_.CheckParameter< int >( "restrict_out_reset" ) ) {
00094 output_reset_not_needed = false;
00095 }
00096
00097 if( output_reset_not_needed &&
00098 ( inRaster->params().nlines_ != outRaster->params().nlines_ ) ) {
00099
00100 output_reset_not_needed = false;
00101 }
00102
00103 if( output_reset_not_needed &&
00104 ( inRaster->params().ncols_ != outRaster->params().ncols_ ) ) {
00105
00106 output_reset_not_needed = false;
00107 }
00108
00109 if( output_reset_not_needed &&
00110 ( output_band >= outRaster->params().nBands() ) ) {
00111
00112 output_reset_not_needed = false;
00113 }
00114
00115 if( output_reset_not_needed )
00116 {
00117 if( inRaster->projection() )
00118 {
00119 if( outRaster->projection() )
00120 {
00121 if( !( (*inRaster->projection()) == (*outRaster->projection()) ) )
00122 {
00123 output_reset_not_needed = false;
00124 }
00125 }
00126 else
00127 {
00128 output_reset_not_needed = false;
00129 }
00130 }
00131 else
00132 {
00133 if( outRaster->projection() )
00134 {
00135 output_reset_not_needed = false;
00136 }
00137 }
00138 }
00139
00140 if( output_reset_not_needed &&
00141 ( inRaster->params().box() != outRaster->params().box() ) )
00142 {
00143
00144 output_reset_not_needed = false;
00145 }
00146
00147 if( output_reset_not_needed &&
00148 ( inRaster->params().photometric_[ 0 ] != TeRasterParams::TePallete
00149 ) )
00150 {
00151
00152 output_reset_not_needed = false;
00153 }
00154
00155 if( output_reset_not_needed &&
00156 ( ( outRaster->params().useDummy_ == output_raster_uses_dummy ) ?
00157 false :
00158 ( outRaster->params().useDummy_ ?
00159 ( outRaster->params().dummy_[ 0 ] != output_raster_dummy ) :
00160 false
00161 )
00162 )
00163 ) {
00164
00165 output_reset_not_needed = false;
00166 }
00167
00168 if( ! output_reset_not_needed )
00169 {
00170 TeRasterParams new_outRaster_params = outRaster->params();
00171 new_outRaster_params.nBands( output_band + 1 );
00172 if( inRaster->projection() == 0 ) {
00173 new_outRaster_params.projection( 0 );
00174 } else {
00175 new_outRaster_params.projection( inRaster->projection() );
00176 }
00177 new_outRaster_params.boxResolution( inRaster->params().box().x1(),
00178 inRaster->params().box().y1(), inRaster->params().box().x2(),
00179 inRaster->params().box().y2(),
00180 inRaster->params().resx_, inRaster->params().resy_ );
00181
00182 new_outRaster_params.setPhotometric( TeRasterParams::TePallete, -1 );
00183
00184 new_outRaster_params.lutr_.clear();
00185 new_outRaster_params.lutg_.clear();
00186 new_outRaster_params.lutb_.clear();
00187 new_outRaster_params.lutClassName_.clear();
00188
00189 TePDIRgbPalette::iterator pal_it = palette->begin();
00190 TePDIRgbPalette::iterator pal_it_end = palette->end();
00191 for( unsigned int lut_index = 0 ; lut_index < palette->size() ;
00192 ++lut_index ) {
00193
00194 new_outRaster_params.lutr_.push_back(
00195 (unsigned short)pal_it->second.red_ );
00196 new_outRaster_params.lutg_.push_back(
00197 (unsigned short)pal_it->second.green_ );
00198 new_outRaster_params.lutb_.push_back(
00199 (unsigned short)pal_it->second.blue_ );
00200
00201 ++pal_it;
00202 }
00203
00204 new_outRaster_params.lutClassName_.resize(palette->size());
00205
00206 if( output_raster_uses_dummy ) {
00207 new_outRaster_params.setDummy( output_raster_dummy, -1 );
00208 } else {
00209 new_outRaster_params.useDummy_ = false;
00210 }
00211
00212 TEAGN_TRUE_OR_RETURN( outRaster->init( new_outRaster_params ),
00213 "Output raster reset error" );
00214 }
00215
00216 break;
00217 }
00218 default :
00219 {
00220
00221
00222 bool output_reset_not_needed = true;
00223
00224 if( ! params_.CheckParameter< int >( "restrict_out_reset" ) ) {
00225 output_reset_not_needed = false;
00226 }
00227
00228 if( output_reset_not_needed &&
00229 ( inRaster->params().nlines_ != outRaster->params().nlines_ ) ) {
00230
00231 output_reset_not_needed = false;
00232 }
00233
00234 if( output_reset_not_needed &&
00235 ( inRaster->params().ncols_ != outRaster->params().ncols_ ) ) {
00236
00237 output_reset_not_needed = false;
00238 }
00239
00240 if( output_reset_not_needed &&
00241 ( output_band >= outRaster->params().nBands() ) ) {
00242
00243 output_reset_not_needed = false;
00244 }
00245
00246 if( output_reset_not_needed &&
00247 (
00248 ( inRaster->projection() == outRaster->projection() ) ?
00249 false :
00250 (
00251 ( inRaster->projection() == 0 ) ?
00252 true :
00253 (
00254 ( outRaster->projection() == 0 ) ?
00255 true :
00256 ( inRaster->projection()->name() ==
00257 outRaster->projection()->name() ) ? false : true
00258 )
00259 )
00260 )
00261 ) {
00262
00263 output_reset_not_needed = false;
00264 }
00265
00266 if( output_reset_not_needed &&
00267 ( inRaster->params().box() != outRaster->params().box() ) ) {
00268
00269 output_reset_not_needed = false;
00270 }
00271
00272 if( output_reset_not_needed &&
00273 ( ( outRaster->params().useDummy_ == output_raster_uses_dummy ) ?
00274 false :
00275 ( outRaster->params().useDummy_ ?
00276 ( outRaster->params().dummy_[ 0 ] != output_raster_dummy ) :
00277 false
00278 )
00279 )
00280 ) {
00281
00282 output_reset_not_needed = false;
00283 }
00284
00285 if( ! output_reset_not_needed ) {
00286
00287 TeRasterParams new_outRaster_params = outRaster->params();
00288 new_outRaster_params.nBands( output_band + 1 );
00289 if( inRaster->projection() == 0 ) {
00290 new_outRaster_params.projection( 0 );
00291 } else {
00292 TeSharedPtr< TeProjection > proj( TeProjectionFactory::make(
00293 inRaster->projection()->params() ) );
00294 new_outRaster_params.projection( proj.nakedPointer() );
00295 }
00296 new_outRaster_params.boxResolution( inRaster->params().box().x1(),
00297 inRaster->params().box().y1(), inRaster->params().box().x2(),
00298 inRaster->params().box().y2(),
00299 inRaster->params().resx_, inRaster->params().resy_ );
00300
00301 if( output_raster_uses_dummy ) {
00302 new_outRaster_params.setDummy( output_raster_dummy, -1 );
00303 } else {
00304 new_outRaster_params.useDummy_ = false;
00305 }
00306
00307 new_outRaster_params.setPhotometric( TeRasterParams::TeMultiBand );
00308
00309 TEAGN_TRUE_OR_RETURN( outRaster->init( new_outRaster_params ),
00310 "Output raster reset error" );
00311 }
00312
00313 break;
00314 }
00315 }
00316 }
00317
00318
00319
00320 double output_channel_min_level = 0;
00321 double output_channel_max_level = 0;
00322
00323 if( params_.CheckParameter< double >( "output_channel_min_level" ) ) {
00324 params_.GetParameter( "output_channel_min_level",
00325 output_channel_min_level );
00326 params_.GetParameter( "output_channel_max_level",
00327 output_channel_max_level );
00328 } else {
00329 TEAGN_TRUE_OR_RETURN( TePDIUtils::TeGetRasterMinMaxBounds(
00330 outRaster, output_band, output_channel_min_level,
00331 output_channel_max_level ), "Unable to get raster channel level bounds" );
00332 }
00333
00334
00335
00336 TePDITypes::TePDILutType lut;
00337 bool hist_based_lut = false;
00338 bool fixed_step_lut = false;
00339
00340 switch( contrast_type ) {
00341 case TePDIContrastMinMax :
00342 {
00343 TePDITypes::TePDILutType baselut;
00344 TEAGN_TRUE_OR_RETURN( getBaseLut( baselut, hist_based_lut,
00345 output_raster_uses_dummy, output_raster_dummy ),
00346 "Error getting base lut" );
00347
00348 lut = GetMinMaxLut( output_channel_min_level, output_channel_max_level,
00349 baselut );
00350
00351 break;
00352 }
00353 case TePDIContrastLinear :
00354 {
00355 TePDITypes::TePDILutType baselut;
00356 TEAGN_TRUE_OR_RETURN( getBaseLut( baselut, hist_based_lut,
00357 output_raster_uses_dummy, output_raster_dummy ),
00358 "Error getting base lut" );
00359
00360 lut = GetLinearLut( baselut,
00361 min_level, max_level, output_channel_min_level, output_channel_max_level );
00362
00363 break;
00364 }
00365 case TePDIContrastSquareRoot :
00366 {
00367 TePDITypes::TePDILutType baselut;
00368 TEAGN_TRUE_OR_RETURN( getBaseLut( baselut, hist_based_lut,
00369 output_raster_uses_dummy, output_raster_dummy ),
00370 "Error getting base lut" );
00371
00372 lut = GetSquareRootLut( baselut,
00373 min_level, max_level, output_channel_min_level, output_channel_max_level );
00374
00375 break;
00376 }
00377 case TePDIContrastSquare :
00378 {
00379 TePDITypes::TePDILutType baselut;
00380 TEAGN_TRUE_OR_RETURN( getBaseLut( baselut, hist_based_lut,
00381 output_raster_uses_dummy, output_raster_dummy ),
00382 "Error getting base lut" );
00383
00384 lut = GetSquareLut( baselut,
00385 min_level, max_level, output_channel_min_level, output_channel_max_level );
00386
00387 break;
00388 }
00389 case TePDIContrastLog :
00390 {
00391 TePDITypes::TePDILutType baselut;
00392 TEAGN_TRUE_OR_RETURN( getBaseLut( baselut, hist_based_lut,
00393 output_raster_uses_dummy, output_raster_dummy ),
00394 "Error getting base lut" );
00395
00396 lut = GetLogLut( baselut,
00397 min_level, max_level, output_channel_min_level, output_channel_max_level );
00398
00399 break;
00400 }
00401 case TePDIContrastNegative :
00402 {
00403 TePDITypes::TePDILutType baselut;
00404 TEAGN_TRUE_OR_RETURN( getBaseLut( baselut, hist_based_lut,
00405 output_raster_uses_dummy, output_raster_dummy ),
00406 "Error getting base lut" );
00407
00408 lut = GetNegativeLut( baselut,
00409 min_level, max_level, output_channel_min_level, output_channel_max_level );
00410
00411 break;
00412 }
00413 case TePDIContrastHistEqualizer :
00414 {
00415 TePDIHistogram::pointer histogram;
00416 TEAGN_TRUE_OR_RETURN( getHistogram( histogram, output_raster_uses_dummy,
00417 output_raster_dummy ), "Unable to get histogram" );
00418
00419 fixed_step_lut = histogram->hasFixedStep();
00420 hist_based_lut = true;
00421
00422 lut = GetHistEqualizerLut( histogram,
00423 output_channel_min_level, output_channel_max_level );
00424
00425 break;
00426 }
00427 case TePDIContrastSimpleSlicer :
00428 {
00429 TePDIHistogram::pointer histogram;
00430 TEAGN_TRUE_OR_RETURN( getHistogram( histogram, output_raster_uses_dummy,
00431 output_raster_dummy ), "Unable to get histogram" );
00432
00433 fixed_step_lut = histogram->hasFixedStep();
00434 hist_based_lut = true;
00435
00436 GetSimpleSlicerLut( histogram,
00437 palette, min_level, max_level, lut );
00438
00439 break;
00440 }
00441 case TePDIContrastStat :
00442 {
00443 TePDIHistogram::pointer histogram;
00444 TEAGN_TRUE_OR_RETURN( getHistogram( histogram, output_raster_uses_dummy,
00445 output_raster_dummy ), "Unable to get histogram" );
00446
00447 fixed_step_lut = histogram->hasFixedStep();
00448 hist_based_lut = true;
00449
00450 double target_mean = 0;
00451 params_.GetParameter( "target_mean", target_mean );
00452
00453 double target_variance = 0;
00454 params_.GetParameter( "target_variance", target_variance );
00455 GetStatLut( histogram, target_mean, target_variance,
00456 output_channel_min_level, output_channel_max_level, lut );
00457
00458 break;
00459 }
00460 default :
00461 {
00462 TEAGN_LOG_AND_THROW( "Unsuported contrast type" );
00463 break;
00464 }
00465 }
00466
00467
00468
00469 if( params_.CheckParameter< TePDITypes::TePDILutPtrType >(
00470 "outlut" ) ) {
00471
00472 TePDITypes::TePDILutPtrType outlut;
00473 params_.GetParameter( "outlut", outlut );
00474
00475 *outlut = lut;
00476 }
00477
00478
00479
00480 if( outRaster.isActive() ) {
00481 if( hist_based_lut ) {
00482 TEAGN_TRUE_OR_RETURN( RemapLevels( inRaster, lut, input_band,
00483 output_band, outRaster, output_raster_uses_dummy, output_raster_dummy,
00484 fixed_step_lut ), "Level remapping error" );
00485 } else {
00486 TEAGN_TRUE_OR_RETURN( FullRangeLutRemapLevels( inRaster, lut,
00487 input_band, output_band, outRaster, output_raster_uses_dummy,
00488 output_raster_dummy ), "Level remapping error" );
00489 }
00490 }
00491
00492
00493
00494 if( params_.CheckParameter< TePDIHistogram::pointer >(
00495 "output_original_histogram" ) ) {
00496
00497 TePDIHistogram::pointer curr_histo_ptr;
00498 TEAGN_TRUE_OR_RETURN( getHistogram( curr_histo_ptr,
00499 output_raster_uses_dummy, output_raster_dummy ),
00500 "Unable to get histogram" );
00501
00502 TePDIHistogram::pointer output_original_histogram;
00503 params_.GetParameter( "output_original_histogram",
00504 output_original_histogram );
00505
00506 (*output_original_histogram) = (*curr_histo_ptr);
00507 }
00508
00509
00510
00511 if( params_.CheckParameter< TePDIHistogram::pointer >(
00512 "output_enhanced_histogram" ) ) {
00513
00514 TePDIHistogram::pointer curr_histo_ptr;
00515 TEAGN_TRUE_OR_RETURN( getHistogram( curr_histo_ptr,
00516 output_raster_uses_dummy, output_raster_dummy ),
00517 "Unable to get histogram" );
00518
00519 TePDIHistogram::pointer output_enhanced_histogram;
00520 params_.GetParameter( "output_enhanced_histogram",
00521 output_enhanced_histogram );
00522
00523 TePDIHistogram::iterator curr_histo_it = curr_histo_ptr->begin();
00524 TePDIHistogram::iterator curr_histo_it_end = curr_histo_ptr->end();
00525 TePDITypes::TePDILutType::iterator lut_it_end = lut.end();
00526 TePDITypes::TePDILutType::iterator found_lut_mapping_it;
00527
00528 while( curr_histo_it != curr_histo_it_end ) {
00529 found_lut_mapping_it = lut.find( curr_histo_it->first );
00530
00531 if( found_lut_mapping_it != lut_it_end ) {
00532 (*output_enhanced_histogram)[ found_lut_mapping_it->second ]
00533 += curr_histo_it->second;
00534 }
00535
00536 ++curr_histo_it;
00537 }
00538 }
00539
00540 return true;
00541 }
00542
00543
00544 bool TePDIContrast::CheckParameters(
00545 const TePDIParameters& parameters ) const
00546 {
00547
00548
00549 if( parameters.CheckParameter< TePDITypes::TePDIRasterPtrType >(
00550 "input_image" ) ) {
00551
00552 TePDITypes::TePDIRasterPtrType inRaster;
00553
00554 if( ! parameters.GetParameter( "input_image", inRaster ) ) {
00555
00556 TEAGN_LOGERR( "Missing parameter: input_image" );
00557 return false;
00558 }
00559 if( ! inRaster.isActive() ) {
00560
00561 TEAGN_LOGERR( "Invalid parameter: input_image inactive" );
00562 return false;
00563 }
00564 if( inRaster->params().status_ == TeRasterParams::TeNotReady ) {
00565
00566 TEAGN_LOGERR( "Invalid parameter: input_image not ready" );
00567 return false;
00568 }
00569
00570
00571
00572 int input_band;
00573 TEAGN_TRUE_OR_RETURN( parameters.GetParameter( "input_band", input_band ),
00574 "Missing parameter: input_band" );
00575 TEAGN_TRUE_OR_RETURN( ( ( input_band >= 0 ) &&
00576 ( input_band < inRaster->nBands() ) ),
00577 "Invalid parameter: input_band" );
00578
00579
00580
00581 TEAGN_TRUE_OR_RETURN( (
00582 ( inRaster->params().photometric_[ input_band ] ==
00583 TeRasterParams::TeRGB ) ||
00584 ( inRaster->params().photometric_[ input_band ] ==
00585 TeRasterParams::TeMultiBand ) ),
00586 "Invalid parameter - input_image (invalid photometric interpretation)" );
00587 }
00588
00589
00590
00591 TePDITypes::TePDIRasterPtrType output_image;
00592 if( parameters.CheckParameter< TePDITypes::TePDIRasterPtrType >(
00593 "output_image" ) ) {
00594
00595 TEAGN_TRUE_OR_RETURN( parameters.GetParameter( "output_image",
00596 output_image ), "Missing parameter: output_image" );
00597 TEAGN_TRUE_OR_RETURN( output_image.isActive(),
00598 "Invalid parameter: output_image inactive" );
00599 TEAGN_TRUE_OR_RETURN( output_image->params().status_ !=
00600 TeRasterParams::TeNotReady,
00601 "Invalid parameter: output_image not ready" );
00602
00603
00604
00605 int output_band;
00606 TEAGN_TRUE_OR_RETURN( parameters.GetParameter( "output_band",
00607 output_band ), "Missing parameter: output_band" );
00608 TEAGN_TRUE_OR_RETURN( ( output_band >= 0 ),
00609 "Invalid parameter: output_band" );
00610
00611
00612
00613 TEAGN_TRUE_OR_RETURN(
00614 parameters.CheckParameter< TePDITypes::TePDIRasterPtrType >(
00615 "input_image" ), "Missing parameter: input_image" );
00616 }
00617
00618
00619
00620 TePDIContrastType contrast_type;
00621 if( ! parameters.GetParameter( "contrast_type", contrast_type ) ) {
00622 TEAGN_LOGERR( "Missing parameter: contrast_type" );
00623 return false;
00624 }
00625 TEAGN_CHECK_NOTEQUAL( contrast_type, 0, "Invalid Contrast type" );
00626 if( ( contrast_type != TePDIContrastMinMax ) &&
00627 ( contrast_type != TePDIContrastLinear ) &&
00628 ( contrast_type != TePDIContrastSquareRoot ) &&
00629 ( contrast_type != TePDIContrastSquare ) &&
00630 ( contrast_type != TePDIContrastLog ) &&
00631 ( contrast_type != TePDIContrastNegative ) &&
00632 ( contrast_type != TePDIContrastHistEqualizer ) &&
00633 ( contrast_type != TePDIContrastSimpleSlicer ) &&
00634 ( contrast_type != TePDIContrastStat ) ) {
00635
00636 TEAGN_LOGERR( "Invalid parameter: contrast_type" );
00637 return false;
00638 }
00639
00640
00641
00642 if( ( contrast_type == TePDIContrastLinear ) ||
00643 ( contrast_type == TePDIContrastSquareRoot ) ||
00644 ( contrast_type == TePDIContrastSquare ) ||
00645 ( contrast_type == TePDIContrastLog ) ||
00646 ( contrast_type == TePDIContrastNegative ) ||
00647 ( contrast_type == TePDIContrastSimpleSlicer ) ) {
00648
00649 if( ! parameters.CheckParameter< double >( "min_level" ) ) {
00650
00651 TEAGN_LOGERR( "Missing parameter: min_level" );
00652 return false;
00653 }
00654 if( ! parameters.CheckParameter< double >( "max_level" ) ) {
00655
00656 TEAGN_LOGERR( "Missing parameter: max_level" );
00657 return false;
00658 }
00659 }
00660
00661
00662
00663 if( ( contrast_type == TePDIContrastSimpleSlicer ) ) {
00664 TePDIRgbPalette::pointer rgb_palette;
00665
00666 if( ( ! parameters.GetParameter( "rgb_palette", rgb_palette ) ) ||
00667 ( ! rgb_palette.isActive() ) ) {
00668
00669 TEAGN_LOGERR( "Missing parameter: rgb_palette" );
00670 return false;
00671 }
00672 }
00673
00674
00675
00676 if( parameters.CheckParameter< TePDITypes::TePDILutPtrType >(
00677 "outlut" ) ) {
00678
00679 TePDITypes::TePDILutPtrType outlut;
00680 parameters.GetParameter( "outlut", outlut );
00681
00682 TEAGN_TRUE_OR_RETURN( outlut.isActive(),
00683 "Invalid parameter: outlut" );
00684 }
00685
00686
00687
00688 TePDIHistogram::pointer input_histogram;
00689
00690 if( parameters.CheckParameter< TePDIHistogram::pointer >(
00691 "input_histogram" ) ) {
00692
00693 parameters.GetParameter( "input_histogram", input_histogram );
00694 TEAGN_TRUE_OR_RETURN( input_histogram.isActive(),
00695 "Invalid parameter: input_histogram" );
00696 TEAGN_TRUE_OR_RETURN( ( input_histogram->size() > 0 ),
00697 "Invalid parameter: input_histogram" );
00698 } else {
00699
00700
00701 TEAGN_TRUE_OR_RETURN(
00702 parameters.CheckParameter< TePDITypes::TePDIRasterPtrType >(
00703 "input_image" ), "Missing parameter: input_image" );
00704 }
00705
00706
00707
00708 TePDIHistogram::pointer output_original_histogram;
00709
00710 if( parameters.CheckParameter< TePDIHistogram::pointer >(
00711 "output_original_histogram" ) ) {
00712
00713 parameters.GetParameter( "output_original_histogram",
00714 output_original_histogram );
00715 TEAGN_TRUE_OR_RETURN( output_original_histogram.isActive(),
00716 "Invalid parameter: output_original_histogram" );
00717 }
00718
00719
00720
00721 TePDIHistogram::pointer output_enhanced_histogram;
00722
00723 if( parameters.CheckParameter< TePDIHistogram::pointer >(
00724 "output_enhanced_histogram" ) ) {
00725
00726 parameters.GetParameter( "output_enhanced_histogram",
00727 output_enhanced_histogram );
00728 TEAGN_TRUE_OR_RETURN( output_enhanced_histogram.isActive(),
00729 "Invalid parameter: output_enhanced_histogram" );
00730 }
00731
00732
00733
00734 if( ( contrast_type == TePDIContrastStat ) ) {
00735 double target_mean = 0;
00736 TEAGN_TRUE_OR_RETURN(
00737 parameters.GetParameter( "target_mean", target_mean ),
00738 "Missing parameter: target_mean" );
00739
00740 double target_variance = 0;
00741 TEAGN_TRUE_OR_RETURN(
00742 parameters.GetParameter( "target_variance", target_variance ),
00743 "Missing parameter: target_variance" );
00744 }
00745
00746
00747
00748
00749
00750 double input_variance = 0;
00751
00752 if( parameters.CheckParameter< double >( "input_variance" ) ) {
00753 parameters.GetParameter( "input_variance", input_variance );
00754
00755 TEAGN_TRUE_OR_RETURN( ( input_variance != 0 ),
00756 "Invalid parameter - input_variance" )
00757 }
00758
00759
00760
00761 if( ! output_image.isActive() ) {
00762
00763 TEAGN_TRUE_OR_RETURN(
00764 parameters.CheckParameter< double >( "output_channel_min_level" ),
00765 "Missing parameter: output_channel_min_level" );
00766 TEAGN_TRUE_OR_RETURN(
00767 parameters.CheckParameter< double >( "output_channel_max_level" ),
00768 "Missing parameter: output_channel_max_level" );
00769 }
00770
00771 return true;
00772 }
00773
00774
00775 void TePDIContrast::ResetState( const TePDIParameters& params )
00776 {
00777 if( params != params_ ) {
00778 histo_ptr_.reset();
00779 }
00780 }
00781
00782
00783 TePDITypes::TePDILutType TePDIContrast::GetMinMaxLut(
00784 double output_channel_min_level, double output_channel_max_level,
00785 TePDITypes::TePDILutType& base_lut )
00786 {
00787 TEAGN_TRUE_OR_THROW( base_lut.size() != 0, "Invalid base_lut" );
00788
00789 double lut_max = (-1.0) * DBL_MAX;
00790 double lut_min = DBL_MAX;
00791
00792 TePDITypes::TePDILutType::iterator it = base_lut.begin();
00793 TePDITypes::TePDILutType::iterator it_end = base_lut.end();
00794
00795 while( it != it_end ) {
00796 if( it->first < lut_min ) {
00797 lut_min = it->first;
00798 }
00799 if( it->first > lut_max ) {
00800 lut_max = it->first;
00801 }
00802
00803 ++it;
00804 }
00805
00806 return GetLinearLut( base_lut, lut_min,
00807 lut_max, output_channel_min_level, output_channel_max_level );
00808 }
00809
00810
00811 TePDITypes::TePDILutType TePDIContrast::GetLinearLut(
00812 TePDITypes::TePDILutType& base_lut,
00813 double min, double max,
00814 double output_channel_min_level, double output_channel_max_level )
00815 {
00816 TEAGN_CHECK_NOTEQUAL( base_lut.size(), 0, "Invalid base_lut size" );
00817 TEAGN_TRUE_OR_THROW( max > min, "Invalid max and min values" );
00818
00819
00820
00821 unsigned int levels = base_lut.size();
00822
00823 double a = 0;
00824 double b = 0;
00825
00826 if( max == min ) {
00827 a = (double)levels;
00828 b = -1. * ((double)levels) * min;
00829 } else {
00830 a = ((double)levels) / ( max - min );
00831 b = ( -1. * ((double)levels) * min ) / ( max - min );
00832 }
00833
00834
00835
00836 TePDITypes::TePDILutType out_lut;
00837
00838 TePDITypes::TePDILutType::iterator base_lut_it = base_lut.begin();
00839 TePDITypes::TePDILutType::iterator base_lut_it_end = base_lut.end();
00840
00841 unsigned int progress = 0;
00842 double mapped_level = 0;
00843 StartProgInt( "Building Linear Lut...", base_lut.size() );
00844
00845 while( base_lut_it != base_lut_it_end ) {
00846 UpdateProgInt( progress );
00847
00848 if( base_lut_it->first <= min ) {
00849 out_lut[ base_lut_it->first ] = output_channel_min_level;
00850 } else if( base_lut_it->first >= max ) {
00851 out_lut[ base_lut_it->first ] = output_channel_max_level;
00852 } else {
00853 mapped_level = ( a * base_lut_it->first ) + b;
00854
00855 if( mapped_level < output_channel_min_level ) {
00856 mapped_level = output_channel_min_level;
00857 } else if( mapped_level > output_channel_max_level ) {
00858 mapped_level = output_channel_max_level;
00859 }
00860
00861 out_lut[ base_lut_it->first ] = mapped_level;
00862 }
00863
00864 ++progress;
00865 ++base_lut_it;
00866 }
00867
00868 return out_lut;
00869 }
00870
00871
00872 TePDITypes::TePDILutType TePDIContrast::GetSquareRootLut(
00873 TePDITypes::TePDILutType& base_lut,
00874 double min, double max,
00875 double output_channel_min_level, double output_channel_max_level )
00876 {
00877 TEAGN_CHECK_NOTEQUAL( base_lut.size(), 0, "Invalid base_lut size" );
00878 TEAGN_TRUE_OR_THROW( min < max, "Invalid min and max values" );
00879
00880 unsigned int levels = base_lut.size();
00881
00882 double factor = ((double)levels) / sqrt( max - min );
00883
00884
00885
00886 TePDITypes::TePDILutType out_lut;
00887
00888 TePDITypes::TePDILutType::iterator base_lut_it = base_lut.begin();
00889 TePDITypes::TePDILutType::iterator base_lut_it_end = base_lut.end();
00890
00891 unsigned int progress = 0;
00892 double mapped_level = 0;
00893 StartProgInt( "Building Square Root Lut...", base_lut.size() );
00894
00895 while( base_lut_it != base_lut_it_end ) {
00896 UpdateProgInt( progress );
00897
00898 if( base_lut_it->first <= min ) {
00899 out_lut[ base_lut_it->first ] = output_channel_min_level;
00900 } else if( base_lut_it->first >= max ) {
00901 out_lut[ base_lut_it->first ] = output_channel_max_level;
00902 } else {
00903 mapped_level = factor * sqrt( base_lut_it->first - min );
00904
00905 if( mapped_level < output_channel_min_level ) {
00906 mapped_level = output_channel_min_level;
00907 } else if( mapped_level > output_channel_max_level ) {
00908 mapped_level = output_channel_max_level;
00909 }
00910
00911 out_lut[ base_lut_it->first ] = mapped_level;
00912 }
00913
00914 ++progress;
00915 ++base_lut_it;
00916 }
00917
00918 return out_lut;
00919 }
00920
00921
00922 TePDITypes::TePDILutType TePDIContrast::GetSquareLut(
00923 TePDITypes::TePDILutType& base_lut,
00924 double min, double max,
00925 double output_channel_min_level, double output_channel_max_level )
00926 {
00927 TEAGN_CHECK_NOTEQUAL( base_lut.size(), 0, "Invalid base_lut size" );
00928 TEAGN_TRUE_OR_THROW( min < max, "Invalid min and max values" );
00929
00930 unsigned int levels = base_lut.size();
00931
00932 double factor = ((double)levels) / pow( (max - min), 2 );
00933
00934
00935
00936 TePDITypes::TePDILutType out_lut;
00937
00938 TePDITypes::TePDILutType::iterator base_lut_it = base_lut.begin();
00939 TePDITypes::TePDILutType::iterator base_lut_it_end = base_lut.end();
00940
00941 unsigned int progress = 0;
00942 double mapped_level = 0;
00943 StartProgInt( "Building Square Lut...", base_lut.size() );
00944
00945 while( base_lut_it != base_lut_it_end ) {
00946 UpdateProgInt( progress );
00947
00948 if( base_lut_it->first <= min ) {
00949 out_lut[ base_lut_it->first ] = output_channel_min_level;
00950 } else if( base_lut_it->first >= max ) {
00951 out_lut[ base_lut_it->first ] = output_channel_max_level;
00952 } else {
00953 mapped_level = factor * pow( base_lut_it->first - min, 2 );
00954
00955 if( mapped_level < output_channel_min_level ) {
00956 mapped_level = output_channel_min_level;
00957 } else if( mapped_level > output_channel_max_level ) {
00958 mapped_level = output_channel_max_level;
00959 }
00960
00961 out_lut[ base_lut_it->first ] = mapped_level;
00962 }
00963
00964 ++progress;
00965 ++base_lut_it;
00966 }
00967
00968 return out_lut;
00969 }
00970
00971
00972 TePDITypes::TePDILutType TePDIContrast::GetLogLut(
00973 TePDITypes::TePDILutType& base_lut,
00974 double min, double max,
00975 double output_channel_min_level, double output_channel_max_level )
00976 {
00977 TEAGN_CHECK_NOTEQUAL( base_lut.size(), 0, "Invalid base_lut size" );
00978 TEAGN_TRUE_OR_THROW( max > ( min+1 ), "Invalid min and max values" );
00979
00980 unsigned int levels = base_lut.size();
00981
00982 double factor = ((double)levels) / log10( max - min + 1 );
00983
00984
00985
00986 TePDITypes::TePDILutType out_lut;
00987
00988 TePDITypes::TePDILutType::iterator base_lut_it = base_lut.begin();
00989 TePDITypes::TePDILutType::iterator base_lut_it_end = base_lut.end();
00990
00991 unsigned int progress = 0;
00992 double mapped_level = 0;
00993 StartProgInt( "Building Log Lut...", base_lut.size() );
00994
00995 while( base_lut_it != base_lut_it_end ) {
00996 UpdateProgInt( progress );
00997
00998 if( base_lut_it->first <= min ) {
00999 out_lut[ base_lut_it->first ] = output_channel_min_level;
01000 } else if( base_lut_it->first >= max ) {
01001 out_lut[ base_lut_it->first ] = output_channel_max_level;
01002 } else {
01003 mapped_level = factor * log10( base_lut_it->first - min + 1 );
01004
01005 if( mapped_level < output_channel_min_level ) {
01006 mapped_level = output_channel_min_level;
01007 } else if( mapped_level > output_channel_max_level ) {
01008 mapped_level = output_channel_max_level;
01009 }
01010
01011 out_lut[ base_lut_it->first ] = mapped_level;
01012 }
01013
01014 ++progress;
01015 ++base_lut_it;
01016 }
01017
01018 return out_lut;
01019 }
01020
01021
01022 TePDITypes::TePDILutType TePDIContrast::GetNegativeLut(
01023 TePDITypes::TePDILutType& base_lut,
01024 double min, double max,
01025 double output_channel_min_level, double output_channel_max_level )
01026 {
01027 TEAGN_CHECK_NOTEQUAL( base_lut.size(), 0, "Invalid base_lut size" );
01028 TEAGN_TRUE_OR_THROW( max > min, "Invalid max and min values" );
01029
01030
01031
01032 unsigned int levels = base_lut.size();
01033
01034 double a = -1. * ((double)levels) / ( max - min );
01035 double b = ( ((double)levels) * max ) / ( max - min );
01036
01037
01038
01039 TePDITypes::TePDILutType out_lut;
01040
01041 TePDITypes::TePDILutType::iterator base_lut_it = base_lut.begin();
01042 TePDITypes::TePDILutType::iterator base_lut_it_end = base_lut.end();
01043
01044 unsigned int progress = 0;
01045 double mapped_level = 0;
01046 StartProgInt( "Building Negative Lut...", base_lut.size() );
01047
01048 while( base_lut_it != base_lut_it_end ) {
01049 UpdateProgInt( progress );
01050
01051 if( base_lut_it->first <= min ) {
01052 out_lut[ base_lut_it->first ] = output_channel_max_level;
01053 } else if( base_lut_it->first >= max ) {
01054 out_lut[ base_lut_it->first ] = output_channel_min_level;
01055 } else {
01056 mapped_level = ( a * base_lut_it->first ) + b;
01057
01058 if( mapped_level < output_channel_min_level ) {
01059 mapped_level = output_channel_min_level;
01060 } else if( mapped_level > output_channel_max_level ) {
01061 mapped_level = output_channel_max_level;
01062 }
01063
01064 out_lut[ base_lut_it->first ] = mapped_level;
01065 }
01066
01067 ++progress;
01068 ++base_lut_it;
01069 }
01070
01071 return out_lut;
01072 }
01073
01074 TePDITypes::TePDILutType TePDIContrast::GetHistEqualizerLut(
01075 TePDIHistogram::pointer hist,
01076 double output_channel_min_level, double output_channel_max_level )
01077 {
01078 TEAGN_TRUE_OR_THROW( hist->size() > 1, "Invalid histogram size" );
01079 TEAGN_TRUE_OR_THROW( ( output_channel_max_level > output_channel_min_level ),
01080 "Invalid paramters output_channel_max_level <= output_channel_min_level" );
01081 TEAGN_TRUE_OR_THROW( ( hist->GetMaxCount() > 0 ),
01082 "Invalid histogram" );
01083
01084
01085
01086 TePDIHistogram::iterator in_hist_it = hist->begin();
01087 TePDIHistogram::iterator in_hist_it_end = hist->end();
01088
01089 TePDIMatrix< double > accumulative_matrix;
01090 TEAGN_TRUE_OR_THROW( accumulative_matrix.Reset( hist->size(), 2 ),
01091 "Matrix reset error" );
01092
01093 accumulative_matrix( 0, 0 ) = in_hist_it->first;
01094 accumulative_matrix( 0, 1 ) = (double)in_hist_it->second;
01095 ++in_hist_it;
01096
01097 unsigned int accumulative_matrix_line = 1;
01098 double hist_population = (double)in_hist_it->second;
01099
01100 StartProgInt( "Building Histogram Equalizer Lut...", 2 * hist->size() );
01101
01102 while( in_hist_it != in_hist_it_end ) {
01103 accumulative_matrix( accumulative_matrix_line, 0 ) = in_hist_it->first;
01104 accumulative_matrix( accumulative_matrix_line, 1 ) =
01105 accumulative_matrix( accumulative_matrix_line - 1, 1 ) +
01106 (double)in_hist_it->second;
01107
01108 hist_population += (double)in_hist_it->second;
01109
01110 ++accumulative_matrix_line;
01111 ++in_hist_it;
01112
01113 IncProgInt();
01114 }
01115
01116
01117
01118 double total_levels_nmb = (double)hist->size();
01119 double mapped_level = 0;
01120 TePDITypes::TePDILutType out_lut;
01121
01122 for( accumulative_matrix_line = 0 ;
01123 accumulative_matrix_line < accumulative_matrix.GetLines() ;
01124 ++accumulative_matrix_line ) {
01125
01126 mapped_level = ( accumulative_matrix( accumulative_matrix_line, 1 ) *
01127 total_levels_nmb ) / hist_population;
01128
01129 if( mapped_level < output_channel_min_level ) {
01130 mapped_level = output_channel_min_level;
01131 } else if( mapped_level > output_channel_max_level ) {
01132 mapped_level = output_channel_max_level;
01133 }
01134
01135 out_lut[ accumulative_matrix( accumulative_matrix_line, 0 ) ] =
01136 mapped_level;
01137
01138 IncProgInt();
01139 }
01140
01141 StopProgInt();
01142
01143 return out_lut;
01144 }
01145
01146
01147 void TePDIContrast::GetSimpleSlicerLut(
01148 TePDIHistogram::pointer hist,
01149 TePDIRgbPalette::pointer in_palette,
01150 double min,
01151 double max,
01152 TePDITypes::TePDILutType& out_lut )
01153 {
01154 TEAGN_TRUE_OR_THROW( ( hist->size() > 0 ), "Invalid histogram size" );
01155 TEAGN_TRUE_OR_THROW( max > min, "Invalid max and min values" );
01156 TEAGN_TRUE_OR_THROW( in_palette->size() > 0,
01157 "Invalid input palette size" );
01158
01159 out_lut.clear();
01160
01161
01162
01163 std::vector< double > palette_levels;
01164 TePDIRgbPalette::iterator pal_it = in_palette->begin();
01165 TePDIRgbPalette::iterator pal_it_end = in_palette->end();
01166
01167 unsigned int progress = 0;
01168 StartProgInt( "Building Simple Slicer Lut...", hist->size() +
01169 in_palette->size() );
01170
01171 while( pal_it != pal_it_end ) {
01172 UpdateProgInt( progress );
01173
01174 palette_levels.push_back( pal_it->first );
01175
01176 ++progress;
01177 ++pal_it;
01178 }
01179
01180
01181
01182 double in_hist_max = hist->GetMaxLevel();
01183 double in_hist_min = hist->GetMinLevel();
01184
01185 min = ( min < in_hist_min ) ? in_hist_min : min;
01186 max = ( max > in_hist_max ) ? in_hist_max : max;
01187
01188
01189
01190 double slice_size = ( max - min ) / ((double)in_palette->size());
01191
01192 double first_pal_level = palette_levels[ 0 ];
01193 double last_pal_level = palette_levels[ palette_levels.size() - 1 ];
01194
01195 TePDIHistogram::iterator in_hist_it = hist->begin();
01196 TePDIHistogram::iterator in_hist_it_end = hist->end();
01197
01198 double current_level;
01199 unsigned int current_slice;
01200
01201 while( in_hist_it != in_hist_it_end ) {
01202 UpdateProgInt( progress );
01203
01204 current_level = in_hist_it->first;
01205
01206 if( current_level <= min ) {
01207 out_lut[ current_level ] = first_pal_level;
01208 } else if ( current_level >= max ) {
01209 out_lut[ current_level ] = last_pal_level;
01210 } else {
01211 current_slice =
01212 (unsigned int) floor( ( current_level - min ) / slice_size );
01213
01214 TEAGN_DEBUG_CONDITION( ( current_slice < palette_levels.size() ),
01215 "Invalid current_slice=" + Te2String( current_slice ) +
01216 " for pallete_levels size=" + Te2String( palette_levels.size() ) );
01217
01218 out_lut[ current_level ] = palette_levels[ current_slice ];
01219 }
01220
01221 ++progress;
01222 ++in_hist_it;
01223 }
01224 }
01225
01226
01227 void TePDIContrast::GetStatLut( TePDIHistogram::pointer hist,
01228 double target_mean, double target_variance, double output_channel_min_level,
01229 double output_channel_max_level, TePDITypes::TePDILutType& out_lut )
01230 {
01231 TEAGN_CHECK_NOTEQUAL( hist->size(), 0, "Invalid histogram size" );
01232
01233 out_lut.clear();
01234
01235 TePDIHistogram::iterator in_hist_it;
01236 TePDIHistogram::iterator in_hist_it_end = hist->end();
01237
01238
01239
01240 unsigned int total_pixels = 0;
01241
01242 in_hist_it = hist->begin();
01243
01244 while( in_hist_it != in_hist_it_end ) {
01245 total_pixels += in_hist_it->second;
01246
01247 ++in_hist_it;
01248 }
01249
01250
01251
01252 double current_mean = 0;
01253
01254 if( params_.CheckParameter< double >( "input_mean" ) ) {
01255 params_.GetParameter( "input_mean", current_mean );
01256 } else {
01257 in_hist_it = hist->begin();
01258
01259 while( in_hist_it != in_hist_it_end ) {
01260 current_mean += ( in_hist_it->first * ((double)in_hist_it->second) );
01261
01262 ++in_hist_it;
01263 }
01264
01265 current_mean = current_mean / ((double)total_pixels);
01266 }
01267
01268
01269
01270 double current_variance = 0;
01271
01272 if( params_.CheckParameter< double >( "input_variance" ) ) {
01273 params_.GetParameter( "input_variance", current_variance );
01274 } else {
01275 double temp_double = 0;
01276
01277 in_hist_it = hist->begin();
01278
01279 while( in_hist_it != in_hist_it_end ) {
01280 temp_double = ( in_hist_it->first - current_mean );
01281 temp_double = temp_double * temp_double * ((double)in_hist_it->second);
01282
01283 current_variance += temp_double;
01284
01285 ++in_hist_it;
01286 }
01287
01288 current_variance = current_variance / ( (double) total_pixels );
01289 }
01290
01291
01292
01293 double gain = sqrt( target_variance / current_variance );
01294 double offset = target_mean - ( gain * current_mean );
01295
01296 in_hist_it = hist->begin();
01297
01298 double current_level = 0;
01299 double mapped_level = 0;
01300
01301 while( in_hist_it != in_hist_it_end ) {
01302 current_level = in_hist_it->first;
01303 mapped_level = ( current_level * gain ) + offset;
01304
01305 if( mapped_level < output_channel_min_level ) {
01306 out_lut[ current_level ] = output_channel_min_level;
01307 } else if ( mapped_level > output_channel_max_level ) {
01308 out_lut[ current_level ] = output_channel_max_level;
01309 } else {
01310 out_lut[ current_level ] = mapped_level;
01311 }
01312
01313 ++in_hist_it;
01314 }
01315 }
01316
01317
01318 bool TePDIContrast::RemapLevels(
01319 TePDITypes::TePDIRasterPtrType& inRaster,
01320 TePDITypes::TePDILutType& lut,
01321 int in_channel,
01322 int out_channel,
01323 TePDITypes::TePDIRasterPtrType& outRaster,
01324 bool use_dummy, double dummy_value, bool fixed_step_lut )
01325 {
01326 TEAGN_TRUE_OR_RETURN( inRaster.isActive(),
01327 "inRaster inactive" );
01328 TEAGN_TRUE_OR_RETURN( outRaster.isActive(),
01329 "outRaster inactive" );
01330 TEAGN_TRUE_OR_RETURN(
01331 inRaster->params().status_ != TeRasterParams::TeNotReady,
01332 "inRaster not ready" );
01333 TEAGN_TRUE_OR_RETURN(
01334 ( outRaster->params().status_ != TeRasterParams::TeNotReady ),
01335 "outRaster not ready" );
01336
01337 TEAGN_TRUE_OR_RETURN( ( inRaster->params().nlines_ ==
01338 outRaster->params().nlines_ ),
01339 "Lines number mismatch between input and output image" );
01340 TEAGN_TRUE_OR_RETURN( ( inRaster->params().ncols_ ==
01341 outRaster->params().ncols_ ),
01342 "Columns number mismatch between input and output image" );
01343 TEAGN_TRUE_OR_RETURN( in_channel < inRaster->nBands(),
01344 "Invalid input band" );
01345 TEAGN_TRUE_OR_RETURN( out_channel < outRaster->nBands(),
01346 "Invalid output band" );
01347 TEAGN_TRUE_OR_RETURN( ( lut.size() > 1 ), "Invalid lut" );
01348
01349 const int raster_lines = inRaster->params().nlines_;
01350 const int raster_columns = inRaster->params().ncols_;
01351
01352
01353
01354 bool inRaster_uses_dummy = inRaster->params().useDummy_;
01355
01356 bool outRaster_uses_dummy = outRaster->params().useDummy_;
01357 double outRaster_dummy = 0;
01358 if( outRaster_uses_dummy ) {
01359 outRaster_dummy = outRaster->params().dummy_[ out_channel ];
01360 } else {
01361 outRaster_dummy = dummy_value;
01362 }
01363
01364
01365
01366 TePDIMatrix< double > lutmatrix;
01367 TEAGN_TRUE_OR_RETURN( lutmatrix.Reset( 2, lut.size(),
01368 TePDIMatrix< double >::AutoMemPol ),
01369 "Unable to create lut matrix" );
01370 {
01371 TePDITypes::TePDILutType::iterator it = lut.begin();;
01372
01373 for( unsigned int lutcol = 0 ; lutcol < lutmatrix.GetColumns() ;
01374 ++lutcol ) {
01375
01376 lutmatrix( 0, lutcol ) = it->first;
01377 lutmatrix( 1, lutcol ) = it->second;
01378
01379 ++it;
01380 }
01381 }
01382
01383
01384
01385 StartProgInt( "Remapping Levels...", raster_lines );
01386
01387 if( fixed_step_lut ) {
01388 double current_level = 0;
01389 const double lut_min_level = lutmatrix( 0, 0 );
01390 const double lut_max_level = lutmatrix( 0, lutmatrix.GetColumns() - 1 );
01391 unsigned int best_lut_index = 0;
01392 const unsigned int lutmatrix_last_index = ( lutmatrix.GetColumns() - 1 );
01393
01394 double lut_step = 0;
01395 if( lutmatrix.GetColumns() > 1 ) {
01396 lut_step = lutmatrix( 0, 1 ) - lutmatrix( 0, 0 );
01397 }
01398
01399 for( int line = 0 ; line < raster_lines ; ++line ) {
01400 TEAGN_FALSE_OR_RETURN( UpdateProgInt( line ), "Canceled by the user" );
01401
01402 for( int column = 0 ; column < raster_columns ; ++column ) {
01403 if( inRaster->getElement( column, line, current_level,
01404 in_channel ) ) {
01405
01406 if( use_dummy && ( current_level == dummy_value ) ) {
01407 TEAGN_TRUE_OR_RETURN( outRaster->setElement( column, line,
01408 outRaster_dummy, out_channel ),
01409 "Level remmaping error at " + Te2String( line ) +
01410 "," + Te2String( column ) );
01411 } else {
01412
01413
01414 if( current_level < lut_min_level ) {
01415 best_lut_index = 0;
01416 } else if( current_level > lut_max_level ) {
01417 best_lut_index = lutmatrix_last_index;
01418 } else {
01419 best_lut_index = ( unsigned int ) ( TeRound( ( current_level -
01420 lut_min_level ) / lut_step ) );
01421 }
01422
01423
01424
01425 TEAGN_TRUE_OR_RETURN( outRaster->setElement( column, line,
01426 lutmatrix( 1, best_lut_index ), out_channel ),
01427 "Level remmaping error at " + Te2String( line ) +
01428 "," + Te2String( column ) );
01429 }
01430 } else {
01431 TEAGN_TRUE_OR_RETURN( inRaster_uses_dummy, "Raster read error" );
01432
01433 TEAGN_TRUE_OR_RETURN( outRaster->setElement( column, line,
01434 outRaster_dummy, out_channel ),
01435 "Level remmaping error at " + Te2String( line ) +
01436 "," + Te2String( column ) );
01437 }
01438 }
01439 }
01440 } else {
01441 double current_level;
01442 unsigned int left_element_index;
01443 unsigned int middle_element_index;
01444 unsigned int right_element_index;
01445 const unsigned int last_valid_index = lutmatrix.GetColumns() - 1;
01446 const unsigned int lut_size = lutmatrix.GetColumns();
01447 double middle_element_level;
01448
01449 for( int line = 0 ; line < raster_lines ; ++line ) {
01450 TEAGN_FALSE_OR_RETURN( UpdateProgInt( line ), "Canceled by the user" );
01451
01452 for( int column = 0 ; column < raster_columns ; ++column ) {
01453 if( inRaster->getElement( column, line, current_level,
01454 in_channel ) ) {
01455
01456 if( use_dummy && ( current_level == dummy_value ) ) {
01457 TEAGN_TRUE_OR_RETURN( outRaster->setElement( column, line,
01458 outRaster_dummy, out_channel ),
01459 "Level remmaping error at " + Te2String( line ) +
01460 "," + Te2String( column ) );
01461 } else {
01462
01463
01464 if( lut_size == 1 ) {
01465 right_element_index = left_element_index = 1;
01466 } else {
01467 left_element_index = 0;
01468 right_element_index = last_valid_index;
01469
01470 do {
01471 middle_element_index = left_element_index +
01472 ( ( right_element_index - left_element_index ) / 2 );
01473 middle_element_level = lutmatrix( 0, middle_element_index );
01474
01475 if( current_level == middle_element_level ) {
01476 left_element_index = right_element_index =
01477 middle_element_index;
01478 break;
01479 } else if( current_level < middle_element_level ) {
01480 right_element_index = middle_element_index;
01481 } else {
01482 left_element_index = middle_element_index;
01483 }
01484 } while( ( right_element_index - left_element_index ) > 1 );
01485 }
01486
01487
01488
01489 if( ( current_level - lutmatrix( 0, left_element_index ) ) <
01490 ( lutmatrix( 0, right_element_index ) - current_level ) ) {
01491
01492 TEAGN_TRUE_OR_RETURN( outRaster->setElement( column, line,
01493 lutmatrix( 1, left_element_index ), out_channel ),
01494 "Level remmaping error at " + Te2String( line ) +
01495 "," + Te2String( column ) );
01496 } else {
01497 TEAGN_TRUE_OR_RETURN( outRaster->setElement( column, line,
01498 lutmatrix( 1, right_element_index ), out_channel ),
01499 "Level remmaping error at " + Te2String( line ) +
01500 "," + Te2String( column ) );
01501 }
01502 }
01503 } else {
01504 TEAGN_TRUE_OR_RETURN( inRaster_uses_dummy, "Raster read error" );
01505
01506 TEAGN_TRUE_OR_RETURN( outRaster->setElement( column, line,
01507 outRaster_dummy, out_channel ),
01508 "Level remmaping error at " + Te2String( line ) +
01509 "," + Te2String( column ) );
01510 }
01511 }
01512 }
01513 }
01514
01515 StopProgInt();
01516
01517 return true;
01518 }
01519
01520
01521 bool TePDIContrast::FullRangeLutRemapLevels(
01522 TePDITypes::TePDIRasterPtrType& inRaster, TePDITypes::TePDILutType& lut,
01523 int in_channel, int out_channel, TePDITypes::TePDIRasterPtrType& outRaster,
01524 bool use_dummy, double dummy_value )
01525 {
01526 TEAGN_TRUE_OR_RETURN( inRaster.isActive(),
01527 "inRaster inactive" );
01528 TEAGN_TRUE_OR_RETURN( outRaster.isActive(),
01529 "outRaster inactive" );
01530 TEAGN_TRUE_OR_RETURN(
01531 inRaster->params().status_ != TeRasterParams::TeNotReady,
01532 "inRaster not ready" );
01533 TEAGN_TRUE_OR_RETURN(
01534 ( outRaster->params().status_ != TeRasterParams::TeNotReady ),
01535 "outRaster not ready" );
01536
01537 TEAGN_TRUE_OR_RETURN( ( inRaster->params().nlines_ ==
01538 outRaster->params().nlines_ ),
01539 "Lines number mismatch between input and output image" );
01540 TEAGN_TRUE_OR_RETURN( ( inRaster->params().ncols_ ==
01541 outRaster->params().ncols_ ),
01542 "Columns number mismatch between input and output image" );
01543 TEAGN_TRUE_OR_RETURN( in_channel < inRaster->nBands(),
01544 "Invalid input band" );
01545 TEAGN_TRUE_OR_RETURN( out_channel < outRaster->nBands(),
01546 "Invalid output band" );
01547 TEAGN_TRUE_OR_RETURN( ( lut.size() > 1 ), "Invalid lut" );
01548
01549 const int raster_lines = inRaster->params().nlines_;
01550 const int raster_columns = inRaster->params().ncols_;
01551
01552
01553
01554 bool inRaster_uses_dummy = inRaster->params().useDummy_;
01555
01556 bool outRaster_uses_dummy = outRaster->params().useDummy_;
01557 double outRaster_dummy = 0;
01558 if( outRaster_uses_dummy ) {
01559 outRaster_dummy = outRaster->params().dummy_[ out_channel ];
01560 } else {
01561 outRaster_dummy = dummy_value;
01562 }
01563
01564
01565
01566 TePDIMatrix< double > lutmatrix;
01567 TEAGN_TRUE_OR_RETURN( lutmatrix.Reset( 2, lut.size(),
01568 TePDIMatrix< double >::AutoMemPol ),
01569 "Unable to create lut matrix" );
01570 {
01571 TePDITypes::TePDILutType::iterator it = lut.begin();;
01572
01573 for( unsigned int lutcol = 0 ; lutcol < lutmatrix.GetColumns() ;
01574 ++lutcol ) {
01575
01576 lutmatrix( 0, lutcol ) = it->first;
01577 lutmatrix( 1, lutcol ) = it->second;
01578
01579 ++it;
01580 }
01581 }
01582
01583
01584
01585 TeRaster& inRaster_ref = *inRaster;
01586 TeRaster& outRaster_ref = *outRaster;
01587 int line = 0;
01588 int column = 0 ;
01589 double current_level = 0;
01590
01591 StartProgInt( "Remapping Levels...", raster_lines );
01592
01593 for( line = 0 ; line < raster_lines ; ++line ) {
01594 TEAGN_FALSE_OR_RETURN( UpdateProgInt( line ), "Canceled by the user" );
01595
01596 for( column = 0 ; column < raster_columns ; ++column ) {
01597 if( inRaster_ref.getElement( column, line, current_level,
01598 in_channel ) ) {
01599
01600 if( use_dummy && ( current_level == dummy_value ) ) {
01601 TEAGN_TRUE_OR_RETURN( outRaster_ref.setElement( column, line,
01602 outRaster_dummy, out_channel ),
01603 "Level remmaping error at " + Te2String( line ) +
01604 "," + Te2String( column ) );
01605 } else {
01606 TEAGN_DEBUG_CONDITION( ( ( (unsigned int)current_level ) <
01607 lutmatrix.GetColumns() ), "Level out of lut range" );
01608 TEAGN_DEBUG_CONDITION(
01609 ( lutmatrix( 0, ( (unsigned int)current_level ) ) ==
01610 ( (unsigned int)current_level ) ),
01611 "Requested value not found inside lut" );
01612
01613 TEAGN_TRUE_OR_RETURN( outRaster_ref.setElement( column, line,
01614 lutmatrix( 1, ( (unsigned int)current_level ) ), out_channel ),
01615 "Level remmaping error at " + Te2String( line ) +
01616 "," + Te2String( column ) );
01617 }
01618 } else {
01619 TEAGN_TRUE_OR_RETURN( inRaster_uses_dummy, "Raster read error" );
01620
01621 TEAGN_TRUE_OR_RETURN( outRaster_ref.setElement( column, line,
01622 outRaster_dummy, out_channel ),
01623 "Level remmaping error at " + Te2String( line ) +
01624 "," + Te2String( column ) );
01625 }
01626 }
01627 }
01628
01629 StopProgInt();
01630
01631 return true;
01632 }
01633
01634
01635 bool TePDIContrast::getHistogram( TePDIHistogram::pointer& hist,
01636 bool useDummy, double dummyValue )
01637 {
01638 if( ! histo_ptr_.isActive() ) {
01639 if( params_.CheckParameter< TePDIHistogram::pointer >(
01640 "input_histogram" ) ) {
01641
01642 params_.GetParameter( "input_histogram", histo_ptr_ );
01643 } else {
01644
01645
01646 TePDITypes::TePDIRasterPtrType inRaster;
01647 TEAGN_TRUE_OR_RETURN( params_.GetParameter( "input_image", inRaster ),
01648 "Missing parameter : input_image" );
01649
01650 int input_band = 0;
01651 TEAGN_TRUE_OR_RETURN( params_.GetParameter( "input_band", input_band ),
01652 "Missing parameter : input_band" );
01653
01654 int histo_levels = 0;
01655 if( ( inRaster->params().dataType_[ input_band ] == TeFLOAT ) ||
01656 ( inRaster->params().dataType_[ input_band ] == TeDOUBLE ) ) {
01657
01658 histo_levels = 256;
01659 }
01660 if( params_.CheckParameter< int >( "histo_levels" ) ) {
01661 params_.GetParameter( "histo_levels", histo_levels );
01662 }
01663
01664 histo_ptr_.reset( new TePDIHistogram );
01665 TEAGN_TRUE_OR_RETURN(
01666 histo_ptr_->reset( inRaster, input_band,
01667 (unsigned int)histo_levels,
01668 TeBoxPixelIn ), "Histogram generation error" );
01669
01670
01671
01672 if( useDummy )
01673 {
01674 histo_ptr_->erase( dummyValue );
01675 }
01676 }
01677 }
01678
01679 hist = histo_ptr_;
01680
01681 return true;
01682 }
01683
01684 bool TePDIContrast::getBaseLut( TePDITypes::TePDILutType& lut,
01685 bool& hist_based_lut, bool useDummy, double dummyValue )
01686 {
01687 lut.clear();
01688
01689 if( params_.CheckParameter< TePDIHistogram::pointer >(
01690 "input_histogram" ) )
01691 {
01692
01693 TePDIHistogram::pointer hist;
01694 TEAGN_TRUE_OR_RETURN( getHistogram( hist, useDummy, dummyValue ),
01695 "Unable to get histogram" );
01696
01697 TePDIHistogram::iterator it = hist->begin();
01698 TePDIHistogram::iterator it_end = hist->end();
01699
01700 while( it != it_end ) {
01701 lut[ it->first ] = it->first;
01702
01703 ++it;
01704 }
01705
01706 hist_based_lut = true;
01707 } else {
01708 TePDITypes::TePDIRasterPtrType inRaster;
01709 params_.GetParameter( "input_image", inRaster );
01710
01711 int input_band = 0;
01712 params_.GetParameter( "input_band", input_band );
01713
01714 switch( inRaster->params().dataType_[ input_band ] ) {
01715 case TeBIT :
01716 case TeUNSIGNEDCHAR :
01717 case TeUNSIGNEDSHORT :
01718 {
01719 unsigned int lut_size = (unsigned int)(
01720 pow( 2.0, (double)( inRaster->params().elementSize( input_band ) *
01721 8 ) ) );
01722
01723 for( unsigned int index = 0 ; index < lut_size ; ++index ) {
01724 lut[ index ] = index;
01725 }
01726
01727 hist_based_lut = false;
01728
01729 break;
01730 }
01731 case TeCHAR :
01732 case TeSHORT :
01733 case TeINTEGER :
01734 case TeLONG :
01735 case TeUNSIGNEDLONG :
01736 case TeFLOAT :
01737 case TeDOUBLE :
01738 {
01739 TePDIHistogram::pointer hist;
01740 TEAGN_TRUE_OR_RETURN( getHistogram( hist, useDummy, dummyValue ),
01741 "Unable to get histogram" );
01742
01743 TePDIHistogram::iterator it = hist->begin();
01744 TePDIHistogram::iterator it_end = hist->end();
01745
01746 while( it != it_end ) {
01747 lut[ it->first ] = it->first;
01748
01749 ++it;
01750 }
01751
01752 hist_based_lut = true;
01753
01754 break;
01755 }
01756 default :
01757 {
01758 TEAGN_LOG_AND_THROW( "Invalid raster pixel type" );
01759 break;
01760 }
01761 }
01762 }
01763
01764 return true;
01765 }
01766