Filter Library Camera Interface Physics

ScanFilterNCCFFT.cpp

00001 /*
00002  * ScanFilterNCCFFT.cpp - fast normalized cross-correlation filter.
00003  *
00004  * This file is part of the Camera Filter Library.
00005  * Computer Aided Measurement Environment for Realtime Atomic imaging (Camera)
00006  *
00007  * Copyright (C) 2004, Leiden Probe Microscopy.
00008  * Copyright (C) 2004, Universiteit Leiden.
00009  *
00010  * Authors: Martin J. Moene
00011  *
00012  * $Id: ScanFilterNCCFFT.cpp 505 2007-01-29 06:46:39Z moene $
00013  */
00014 
00015 #include "stdafx.h"                     // for common (pre-compiled) headers
00016 //#include <cfl/stdafx.h>                 // for common (pre-compiled) headers
00017 #include <cfl/resource.h>               // for messages and other resources
00018 
00019 #include <Camera/InterfaceDll.h>        // Camera--Filter Library interface
00020 
00021 #include <cfl/ScanFilterNCCFFT.h>       // this filter's header FIXME
00022 #include <cfl/FilterDlg_NCCFFT.h>       // this filter's dialog
00023 #include <cfl/ToolCilImage.h>           // for Image type and ToImage conversion shim
00024 #include <cil/Traits.h>                 // type traits
00025 
00026 #include <cil/CorrelationImageFilter.h> // CorrelationImageFilter image filter (FFT)
00027 #include <cil/correlation/BackgroundSubtractor.h>    // for class BackgroundSubtractOperator
00028 #include <cil/correlation/MeanSubtractor.h>          // for class MeanSubtractOperator
00029 #include <cil/correlation/NormalOperator.h>          // for class NormalOperator
00030 #include <cil/correlation/PhaseOperator.h>           // for class PhaseOperator
00031 #include <cil/correlation/SimpleOptimizer.h>         // for class CorrelationSimpleOptimizer
00032 #include <cil/correlation/ScaleNormalizer.h>         // for class ScaleNormalizer
00033 #include <cil/correlation/EnergyNormalizer.h>        // for class EnergyNormalizer
00034 #include <cil/correlation/ZeroMeanNormalizer.h>      // for class ZeroMeanNormalizerType
00035 
00036 /*
00037  * configuration defines:
00038  */
00039 
00040 // none
00041 
00042 /*
00043  * end of configuration defines.
00044  */
00045 
00046 #ifdef _DEBUG
00047 #undef THIS_FILE
00048 static char THIS_FILE[]=__FILE__;
00049 #define new DEBUG_NEW
00050 #endif
00051 
00052 /*
00053  * convenience types.
00054  */
00055 
00056 #define CFL_SCHEMAVERSION_FILTERNCCFFT 0 ///< permanent storage schema version
00057                                         // this filter's name
00058 LPCTSTR CScanFilterNCCFFT::m_lpcsFilterName = _T("FNCC");
00059                                         // this filter's short name
00060 LPCTSTR CScanFilterNCCFFT::m_lpcsShortFilterName = CScanFilterNCCFFT::m_lpcsFilterName;
00061                                         // serialization
00062 IMPLEMENT_SERIAL(CScanFilterNCCFFT, CScanFilter, CFL_SCHEMAVERSION_FILTERNCCFFT)
00063 
00064 /*
00065  * the default scale factor.
00066  */
00067 const CScanFilterNCCFFT::ScaleType CScanFilterNCCFFT::m_defScale = 1000;
00068 
00069 /*
00070  * default constructor: setup filter to run without dialog;
00071  * see also CScanFilterNull::CScanFilterNull().
00072  */
00073 CScanFilterNCCFFT::CScanFilterNCCFFT()
00074    : m_lpsbIn2( NULL )
00075 {
00076 //    Q_LOG( _T("CScanFilterNCCFFT::CScanFilterNCCFFT()") );
00077 
00078    /*
00079     * we define our own normlization (sub-)type values to decouple this filter's
00080     * header from the Camera Imaging Library (CIL). Nonetheless, we want to use
00081     * the mode values as if they were from the CIL Threshld filter. Here we check
00082     * at compile-time if the values do match.
00083     */
00084 //   cil_static_assert( nmNone     == CorrelationImageFilterType::Normalization::None  , nmNone_values_must_match   );
00085 //   cil_static_assert( nmNormal   == CorrelationImageFilterType::Normalization::Normal, nmNormal_values_must_match   );
00086 //   cil_static_assert( nmPhase    == CorrelationImageFilterType::Normalization::Phase , nmPhase_values_must_match   );
00087 //
00088 //   cil_static_assert( nsZeroMean == CorrelationImageFilterType::NormalizationSub::ZeroMean, nsZeroMean_values_must_match   );
00089 //   cil_static_assert( nsEnergy   == CorrelationImageFilterType::NormalizationSub::Energy  , nsEnergy_values_must_match   );
00090 
00091    m_csFilterName = m_lpcsFilterName;
00092 
00093    ReadFilterSettings();
00094 }
00095 
00096 /*
00097  * destructor.
00098  */
00099 CScanFilterNCCFFT::~CScanFilterNCCFFT()
00100 {
00101 //    Q_LOG( _T("CScanFilterNCCFFT::~CScanFilterNCCFFT()") );
00102 
00103    ; // do nothing
00104 }
00105 
00106 /*
00107  * store or retrieve the object's settings;
00108  * currently filter serialization is not used;
00109  * see also CScanFilterNull::Serialize().
00110  */
00111 void CScanFilterNCCFFT::Serialize(CArchive& ar)
00112 {
00113 //   Q_LOG( _T("CScanFilterNCCFFT::Serialize()") );
00114 
00115    CScanFilter::Serialize( ar );
00116 
00117    if ( ar.IsStoring() )
00118    {
00119 //        ar << m_mode << m_lower << m_upper << m_outside;
00120    }
00121    else
00122    {
00123 //       int mode;
00124 //
00125 //       ar >> mode >> m_lower >> m_upper >> m_outside;
00126 //
00127 //       m_mode = static_cast< NormalizationMode >( mode );
00128    }
00129 };
00130 
00131 /*
00132  * \brief configure filter with settings as provided by the application on the
00133  * filterlist window (e.g. via registry); see also CScanFilterNull::ReadFilterSettings().
00134  */
00135 void CScanFilterNCCFFT::ReadFilterSettings()
00136 {
00137 //    Q_LOG( _T("CScanFilterNCCFFT::ReadFilterSettings()") );
00138 
00139    CWinApp* pApp = AfxGetApp();
00140 
00141    if ( Q_INVALID( NULL == pApp ) )
00142       return ;
00143 
00144    /*
00145     * parameter string:
00146     */
00147    SetParameters( pApp->GetProfileString( gCflRegistrySubkey, m_lpcsFilterName, _T( "1,0,0,1e-6,1000,1000" ) ) );
00148 }
00149 
00150 /*
00151  * \brief save filter settings e.g. for use with the filterlist window (e.g. via registry);
00152  * see also ReadFilterSettings().
00153  */
00154 void CScanFilterNCCFFT::WriteFilterSettings() const
00155 {
00156 //    Q_LOG( _T("CScanFilterNCCFFT::WriteFilterSettings()") );
00157 
00158    CWinApp* pApp = AfxGetApp();
00159 
00160    if ( Q_INVALID( NULL == pApp ) )
00161       return ;
00162 
00163    /*
00164     * parameter string:
00165     */
00166    LPCTSTR pStr = GetParameters();
00167 
00168    if ( pStr )
00169    {
00170       pApp->WriteProfileString( gCflRegistrySubkey, m_lpcsFilterName, pStr );
00171       delete const_cast<LPTSTR>( pStr );
00172    }
00173 }
00174 
00175 /*
00176  * provide current filter parameter(s) for filter-scripting capture
00177  * in the main application;
00178  * see also CScanFilterNull::GetParameters().
00179  */
00180 LPCTSTR CScanFilterNCCFFT::GetParameters() const
00181 {
00182 //    Q_LOG( _T("CScanFilterNCCFFT::GetParameters()") );
00183 
00184    /*
00185     * format parameters and return a c-string on the heap:
00186     */
00187    CString csParameters;
00188 
00189    csParameters.Format
00190       ( _T( "%d,%d,%d,%d,%g,%g,%g" )
00191       , GetSubtractionType()
00192       , GetNormalizationType()
00193       , GetNormalizationSubType()
00194       , DoRelaxFFTSize()
00195       , GetScale( nmNone )
00196       , GetScale( nmNormal )
00197       , GetScale( nmPhase )
00198    );
00199 
00200    return strcpy( new TCHAR[ csParameters.GetLength() + 1 ], csParameters );
00201 }
00202 
00203 /*
00204  * set parameters for filter-script execution of filter;
00205  * see also CScanFilterNull::SetParameters().
00206  */
00207 BOOL CScanFilterNCCFFT::SetParameters( LPCTSTR lpParameters )
00208 {
00209 //    Q_LOG( _T("CScanFilterNCCFFT::SetParameters()") );
00210 
00211    if ( Q_INVALID( NULL == lpParameters && "CScanFilterNCCFFT (SetParameters): parameters expected, none provided (NULL)." ) )
00212    {
00213       return FALSE;
00214    }
00215 
00216    /*
00217     * set defaults, read parameter string with factor and optional offset:
00218     */
00219    int subtract  = bgMean;
00220    int norm      = nmNormal;
00221    int normsub   = nsEnergy;
00222    int relax     = false;
00223    double scale0 = 1e-6; // m_defScale;
00224    double scale1 = m_defScale;
00225    double scale2 = m_defScale;
00226 
00227    int nfields = _stscanf
00228       ( lpParameters
00229       , _T( "%d,%d,%d,%d,%lg,%lg,%lg" )
00230       , &subtract
00231       , &norm
00232       , &normsub
00233       , &relax
00234       , &scale0
00235       , &scale1
00236       , &scale2
00237    );
00238 
00239    m_subtract = static_cast< SubtractionType >     ( subtract );
00240    m_norm     = static_cast< NormalizationType >   ( norm     );
00241    m_normsub  = static_cast< NormalizationSubType >( normsub  );
00242    m_relax_fft_size = 0 != relax;
00243    m_scale[0] = scale0;
00244    m_scale[1] = scale1;
00245    m_scale[2] = scale2;
00246 
00247    if ( Q_INVALID( 7 > nfields && "CScanFilterNCCFFT (SetParameters): FIXME parameters expected, got less." ) )
00248    {
00249       return FALSE;
00250    }
00251 
00252    return TRUE;
00253 }
00254 
00255 /**
00256  * the number of input buffers.
00257  */
00258 DWORD CScanFilterNCCFFT::GetNrOfInBuffers() const
00259 {
00260    return 2;
00261 }
00262 
00263 /**
00264  * return the requested input buffer.
00265  */
00266 CScanBaseBuffer *CScanFilterNCCFFT::GetInputBuffer( UINT nNr )
00267 {
00268    Q_ASSERT( 0 <= nNr && nNr < GetNrOfInBuffers() && "ensure valid input buffer nr" );
00269 
00270    if ( 1 == nNr )
00271    {
00272       return m_lpsbIn2;
00273    }
00274 
00275    return m_lpsbIn;
00276 }
00277 
00278 /**
00279  * set the given input buffer.
00280  */
00281 void CScanFilterNCCFFT::SetInputBuffer( UINT nNr, CScanBaseBuffer *lpsbIn )
00282 {
00283    Q_ASSERT( 0 <= nNr && nNr < GetNrOfInBuffers() && "ensure valid input buffer nr" );
00284    Q_ASSERT( NULL != lpsbIn && "ensure valid input buffer" );
00285 
00286    if ( 0 == nNr )
00287    {
00288       m_lpsbIn = lpsbIn;
00289    }
00290    else if ( 1 == nNr )
00291    {
00292       m_lpsbIn2 = lpsbIn;
00293    }
00294 }
00295 
00296 /*
00297  * create filter dialog and pre Apply() filter to view result;
00298  * see also CScanFilterNull::RunModeless().
00299  */
00300 BOOL CScanFilterNCCFFT::RunModeless( CWnd* pParentWnd, CDocument* pDoc )
00301 {
00302 //    Q_LOG( _T("CScanFilterNCCFFT::RunModeless()") );
00303 
00304    CFilterDlg_NCCFFTPtr pDlg = new CFilterDlg_NCCFFT();
00305 
00306    if ( Q_INVALID( NULL == pDlg ) )
00307       return FALSE;
00308 
00309    pDlg->SetParameters( this, pDoc );   // (void) method
00310 
00311    /*
00312     * Create returns non-zero if dialog was created and initialized succesfully.
00313     * Note: no pDlg->DestroyWindow() must be done.
00314     */
00315    pDlg->Create( IDD_FILTERDLG_NCCFFT, pParentWnd );
00316 
00317    m_pDlg = pDlg;
00318 
00319    BOOL bRet = Apply();
00320 
00321    if ( bRet )
00322    {
00323       pDlg->UpdateView();
00324    }
00325 
00326    return bRet;
00327 }
00328 
00329 /*
00330  * check parameters, take care of a properly sized output buffer, set its name
00331  * and copy filter parameters, CalculatePlane() and SubtractPlane();
00332  * see also CScanFilterNull::ApplyCore().
00333  */
00334 #include <cil/ImageFill.h>                   // for FillImageRandom()
00335 BOOL CScanFilterNCCFFT::Apply()
00336 {
00337 //    Q_LOG( _T("CScanFilterNCCFFT::Apply()") );
00338 
00339    if ( Q_INVALID( NULL == m_lpsbIn && "ensure first input buffer") )
00340       return FALSE;
00341 
00342    if ( Q_INVALID( NULL == m_lpsbIn2 && "ensure second input buffer" ) )
00343       return FALSE;
00344 
00345    if ( Q_INVALID( NULL == m_lpsbOut && "ensure output buffer" ) )
00346       return FALSE;
00347 
00348    if ( Q_INVALID( !m_lpsbIn->IsCompleteFrame() && "ensure complete frame" ) )
00349       return FALSE;
00350 
00351    if ( Q_INVALID( !m_lpsbIn2->IsCompleteFrame() && "ensure complete frame" ) )
00352       return FALSE;
00353 
00354    /*
00355     * copy the filter settings (not the data):
00356     */
00357    Q_RETURN( m_lpsbOut->CreateOutputBufferFor( *m_lpsbIn ) );
00358 
00359    m_lpsbOut->m_csBufferName.Format
00360       ( _T("%s - %s")
00361       , m_lpsbIn->m_csBufferName
00362       , m_lpcsShortFilterName
00363    );
00364 
00365    if ( IsInteractive() )
00366    {
00367       m_pDlg->SetDlgItemText( IDC_BUFFEROUTNAME, m_lpsbOut->m_csBufferName );
00368    }
00369 
00370    /*
00371     * apply filter to L2R part:
00372     */
00373 
00374    /*
00375     * convenience types.
00376     */
00377    typedef cil::Image< InputPixelType > InputImageType;
00378    typedef cil::Image< OutputPixelType > OutputImageType;
00379 
00380    typedef cil::CorrelationImageFilter
00381    < const InputImageType
00382    , const InputImageType
00383    ,       OutputImageType > FilterType;
00384 
00385    typedef cil::correlation::MeanSubtractor      < FilterType > MeanSubtractorType;
00386    typedef cil::correlation::BackgroundSubtractor< FilterType > BackgroundSubtractorType;
00387 
00388    typedef cil::correlation::NormalOperator      < FilterType > NormalOperatorType;
00389    typedef cil::correlation::PhaseOperator       < FilterType > PhaseOperatorType;
00390    typedef cil::correlation::EnergyNormalizer    < FilterType > EnergyNormalizerType;
00391    typedef cil::correlation::ZeroMeanNormalizer  < FilterType > ZeroMeanNormalizerType;
00392    typedef cil::correlation::ScaleNormalizer     < FilterType > ScaleNormalizerType;
00393 
00394    FilterType filter;
00395    filter.SetRelaxFFTSize( DoRelaxFFTSize() );
00396 
00397    /*
00398     * background subtraction:
00399     */
00400    switch ( GetSubtractionType() )
00401    {
00402       case bgMean:
00403          filter.SetSubtractor( MeanSubtractorType::New() );
00404          break;
00405       case bgBackground:
00406          filter.SetSubtractor( BackgroundSubtractorType::New() );
00407          break;
00408       default:
00409          filter.SetSubtractor( );
00410          break;
00411    };
00412 
00413    /*
00414     * normal or phase correlation:
00415     */
00416    switch ( GetNormalizationType() )
00417    {
00418       case nmNormal:
00419          filter.SetOperator( NormalOperatorType::New() );
00420 
00421          /*
00422           * none, energy or zero-mean normalization:
00423           */
00424          switch ( GetNormalizationSubType() )
00425          {
00426             case nsEnergy:
00427             {
00428                EnergyNormalizerType::Pointer normalizer = EnergyNormalizerType::New();
00429                normalizer->SetScale( GetScale( GetNormalizationType() ) );
00430                filter.SetNormalizer( normalizer );
00431                break;
00432             }
00433             case nsZeroMean:
00434             {
00435                ZeroMeanNormalizerType::Pointer normalizer = ZeroMeanNormalizerType::New();
00436                normalizer->SetScale( GetScale( GetNormalizationType() ) );
00437                filter.SetNormalizer( normalizer );
00438                break;
00439             }
00440             default:
00441             {
00442                /*
00443                 * error
00444                 */
00445                break;
00446             }
00447          };
00448          break; // nmNormal
00449 
00450       case nmPhase: default: {
00451          if ( nmPhase == GetNormalizationType() )
00452          {
00453             filter.SetOperator( PhaseOperatorType::New()  );
00454          }
00455          else
00456          {
00457             filter.SetOperator( NormalOperatorType::New() );
00458          }
00459 
00460          ScaleNormalizerType::Pointer normalizer = ScaleNormalizerType::New();
00461          normalizer->SetScale( GetScale( GetNormalizationType() ) );
00462          filter.SetNormalizer( normalizer );
00463          break;
00464       }
00465    };
00466 
00467    //            subject image       , template image     , correlation
00468    filter.Apply( ToImage( m_lpsbIn2 ), ToImage( m_lpsbIn ), ToImage( m_lpsbOut ) );
00469 
00470    /*
00471     * if we have a double buffer, L2R and R2L, process that part tooo.
00472     */
00473    if ( m_lpsbIn->IsBidirectionalScan() && m_lpsbOut->IsBidirectionalScan() )
00474    {
00475       //                     subject image    , template image           , correlation
00476       filter.Apply( ToImage( m_lpsbIn2, true ), ToImage( m_lpsbIn, true ), ToImage( m_lpsbOut, true ) );
00477    }
00478 
00479    /*
00480     * recalculate all temporary variables:
00481     */
00482    m_lpsbOut->m_dwParameterMask  = 0;
00483 
00484    return TRUE;
00485 }
00486 
00487 /*
00488  * end of file
00489  */
00490 

Camera Filter Library documentation © 2004-2007 by Leiden Probe Microscopy