TuttleOFX
1
|
00001 #ifndef _TUTTLE_PLUGIN_NOISE_ANALYSIS_HPP_ 00002 #define _TUTTLE_PLUGIN_NOISE_ANALYSIS_HPP_ 00003 00004 #include <terry/globals.hpp> 00005 00006 #include <boost/gil/gil_all.hpp> 00007 00008 #include <cmath> 00009 00010 namespace tuttle { 00011 namespace plugin { 00012 namespace imageUtils { 00013 00014 /** 00015 * @brief Compute somme pseudo-residuals 00016 * The pseudo residual r_i of the image Y_i are so thar E[r_i^2] = E[Y_i^2]. 00017 * This is the 2D pseudo-implementation. 00018 */ 00019 template <class S_VIEW, class D_VIEW> 00020 D_VIEW & pseudo_residual( S_VIEW & src, D_VIEW & dst ) 00021 { 00022 using namespace boost::gil; 00023 typedef typename S_VIEW::locator Loc; 00024 typedef typename D_VIEW::x_iterator dxIterator; 00025 typedef typename channel_type<D_VIEW>::type pix_t; 00026 00027 int w = src.width( ); 00028 int h = src.height( ); 00029 int nc = src.num_channels( ); 00030 int x, y, c; 00031 double t2; 00032 00033 gil_function_requires < ColorSpacesCompatibleConcept< 00034 typename color_space_type<S_VIEW>::type, 00035 typename color_space_type<D_VIEW>::type > > ( ); 00036 00037 for( y = 0; y < h; ++y ) 00038 { 00039 dxIterator dst_it = dst.row_begin( y ); 00040 00041 for( x = 0; x < w; ++x ) 00042 { 00043 Loc loc = src.xy_at( x, y ); 00044 for( c = 0; c < nc; ++c ) 00045 { 00046 t2 = 0; 00047 if( x == 0 ) 00048 t2 += loc( 1, 0 )[c]; 00049 else 00050 t2 += loc( -1, 0 )[c]; 00051 if( x == w - 1 ) 00052 t2 += loc( -1, 0 )[c]; 00053 else 00054 t2 += loc( 1, 0 )[c]; 00055 if( y == 0 ) 00056 t2 += loc( 0, 1 )[c]; 00057 else 00058 t2 += loc( 0, -1 )[c]; 00059 if( y == h - 1 ) 00060 t2 += loc( 0, -1 )[c]; 00061 else 00062 t2 += loc( 0, 1 )[c]; 00063 ( *dst_it )[c] = ( pix_t ) ( 0.223606798 * ( 4.0 * ( double ) loc( 0, 0 )[c] - t2 ) ); 00064 } 00065 dst_it++; 00066 } 00067 } 00068 return dst; 00069 } 00070 00071 /** 00072 * @brief Return the variance and the mean of the image 00073 * Least Mean of Square 00074 */ 00075 template<class S_VIEW, typename t> 00076 double variance_mean( S_VIEW & src, t& mean ) 00077 { 00078 typedef typename S_VIEW::x_iterator sxIterator; 00079 int w = src.width( ); 00080 int h = src.height( ); 00081 int nc = src.num_channels( ); 00082 int x, y, c; 00083 double variance = 0, average = 0; 00084 const unsigned int siz = w * h * nc; 00085 double S = 0, S2 = 0; 00086 00087 for( y = 0; y < h; ++y ) 00088 { 00089 sxIterator src_it = src.row_begin( y ); 00090 for( x = 0; x < w; ++x ) 00091 { 00092 for( c = 0; c < nc; c++ ) 00093 { 00094 const double val = ( *src_it )[c]; 00095 S += val; 00096 S2 += val * val; 00097 } 00098 ++src_it; 00099 } 00100 } 00101 variance = ( S2 - S * S / siz ) / siz; 00102 average = S; 00103 mean = ( t ) ( average / siz ); 00104 return variance; 00105 } 00106 00107 00108 00109 /** 00110 * @brief Robustly estimate the variance of a the noise using the pseudo-residuals. 00111 * @see variance_estimation() 00112 */ 00113 template <class S_VIEW> 00114 double noise_variance( S_VIEW & src ) 00115 { 00116 using namespace boost::gil; 00117 double mean; 00118 typename terry::image_from_view<S_VIEW>::type tmp( src.dimensions() ); 00119 S_VIEW v_tmp( view( tmp ) ); 00120 return variance_mean( pseudo_residual( src, v_tmp ), mean ); 00121 } 00122 00123 } 00124 } 00125 } 00126 00127 #endif