TuttleOFX  1
noiseAnalysis.hpp
Go to the documentation of this file.
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