Filter Library Camera Interface Physics

ScanFilterFFT.cpp

00001 /*
00002  * ScanFilterFFT.cpp - forward FFT.
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-2005, Leiden Probe Microscopy.
00008  * Copyright (C) 2004-2005, Universiteit Leiden.
00009  *
00010  * Authors: Martin J. Moene
00011  *
00012  * $Id: ScanFilterFFT.cpp 400 2006-09-28 13:34:02Z moene $
00013  */
00014 
00015 /*
00016  * Note: adding anything before stdafx has no effect>
00017  */
00018 #include "stdafx.h"                     // for common (pre-compiled) headers
00019 //#include <cfl/stdafx.h>                 // for common (pre-compiled) headers
00020 #include <cfl/resource.h>               // for messages and other resources
00021 
00022 #include <Camera/InterfaceDll.h>        // Camera--Filter Library interface
00023 
00024 /*
00025  * configuration defines:
00026  */
00027 // #define ScanFilter_Use_FFTW          // use FFTW routines; NOTE: this is not yet in order (MO 20060719)
00028 // #define USE_SEPARATE_AMPLITUDE_SCALE // use separate scaling factor for each power spectrum (L2R, R2L)
00029 
00030 /*
00031  * end of configuration defines.
00032  */
00033 
00034 #include <cfl/ScanFilterFFT.h>          // this filter's header
00035 #include <cfl/ToolCilImage.h>           // for Image type and ToImage conversion shim
00036 #include <cil/Math.h>                   // for real(), //min(), max(), sqrt(), sin(), Pi
00037 
00038 #if defined( ScanFilter_Use_FFTW )
00039 #   include <cil/FFTWImageFilter.h>             // FFTW image filter
00040 #   include <cil/FFTWInverseImageFilter.h>      // FFTW inverse image filter
00041 #else
00042 #   include <cil/FFTImageFilter.h>              // FFT image filter
00043 #   include <cil/FFTInverseImageFilter.h>       // FFT inverse image filter
00044 #endif // defined( ScanFilter_Use_FFTW )
00045 
00046 #include <cil/FFTPowerSpectrumImageFilter.h>    // FFT power spectrum image filter
00047 #include <cil/FFTSwapQuadrantsImageFilter.h>    // FFT swap quadrants image filter
00048 #include <cil/ShiftScaleImageFilter.h>          // FFT scale intensity image filter
00049 
00050 // #pragma warning( disable : 4663 )       // template<> Class<type>
00051 // #include <limits>                       // for numeric_limits<>
00052 // #pragma warning( default : 4663 )
00053 
00054 #undef min                              // use cil::min instead of macro
00055 #undef max                              // use cil::max instead of macro
00056 
00057 #ifdef _DEBUG
00058 #undef THIS_FILE
00059 static char THIS_FILE[]=__FILE__;
00060 #define new DEBUG_NEW
00061 #endif
00062 
00063 #define CFL_SCHEMAVERSION_FILTERFFT 0   // permanent storage schema version
00064                                         // this filter's name
00065 LPCTSTR CScanFilterFFT::m_lpcsFilterName = _T("Fast-Fourier-Transform");
00066                                         // this filter's short name
00067 LPCTSTR CScanFilterFFT::m_lpcsShortFilterName = _T( "FFT" );
00068                                         // the maximum amplitude to scale power spectrum to
00069 const CScanFilterFFT::ValueType CScanFilterFFT::maximumAmplitude = 20000;
00070                                         // serialization
00071 IMPLEMENT_SERIAL(CScanFilterFFT, CScanFilter, CFL_SCHEMAVERSION_FILTERFFT )
00072 
00073 /**
00074  * constructor.
00075  */
00076 CScanFilterFFT::CScanFilterFFT()
00077    : m_progress( 0 )
00078 {
00079    m_csFilterName = m_lpcsFilterName;
00080 }
00081 
00082 /**
00083  * destructor.
00084  */
00085 CScanFilterFFT::~CScanFilterFFT()
00086 {
00087    ; // do nothing
00088 }
00089 
00090 /**
00091  * no dialog.
00092  */
00093 BOOL CScanFilterFFT::CanDoDialogEntry() const
00094 {
00095    return FALSE;
00096 }
00097 
00098 /**
00099  * store or retrieve the object's settings;
00100  * see also CScanFilterNull::Serialize().
00101  */
00102 void CScanFilterFFT::Serialize(CArchive& ar)
00103 {
00104    CScanFilter::Serialize( ar );
00105 
00106    if ( ar.IsStoring() )
00107    {
00108       ; // do nothing
00109    }
00110    else
00111    {
00112       ; // do nothing
00113    }
00114 };
00115 
00116 /**
00117  * no parameters.
00118  */
00119 #pragma warning( push )
00120 #pragma warning( disable : 4100 )       // unreferenced formal parameter
00121 
00122 BOOL CScanFilterFFT::SetParameters(LPCTSTR lpParameters)
00123 {
00124    return TRUE;
00125 }
00126 
00127 #pragma warning( pop )
00128 
00129 /*
00130  * no parameters.
00131  */
00132 LPCTSTR CScanFilterFFT::GetParameters() const
00133 {
00134    return NULL;
00135 }
00136 
00137 /**
00138  * check parameters, take care of a properly sized output buffer,
00139  * set its name and copy filter parameters and process;
00140  * see also CScanFilterNull::ApplyCore().
00141  */
00142 BOOL CScanFilterFFT::Apply()
00143 {
00144 //   Q_LOG( _T("CScanFilterCrossCorrelate::Apply()") );
00145 
00146    if ( Q_INVALID( NULL == m_lpsbIn && "ensure input buffer") )
00147       return FALSE;
00148 
00149    if ( Q_INVALID( NULL == m_lpsbOut && "ensure output buffer" ) )
00150       return FALSE;
00151 
00152    if ( Q_INVALID( !m_lpsbIn->IsCompleteFrame() && "ensure complete frame" ) )
00153       return FALSE;
00154 
00155    /*
00156     * copy the filter settings (not the data):
00157     */
00158    Q_RETURN( m_lpsbOut->CreateOutputBufferFor( *m_lpsbIn ) );
00159 
00160    m_lpsbOut->m_csBufferName = m_lpsbIn->m_csBufferName + _T(" - ") + m_lpcsShortFilterName;
00161    m_lpsbOut->m_csDataName.Format( _T( "10Log %s(%s)" ), m_lpcsShortFilterName, m_lpsbIn->m_csDataName );
00162 
00163    /*
00164     * create a new suspended thread to do the computation;
00165     * the progressdialog resumes the thread and displays the progress:
00166     */
00167    CProgressDlg dlg( AfxGetMainWnd() ); // FFT has no dialog
00168 
00169    ThreadArgs threadArgs( &dlg, this );
00170 
00171    CWinThread *hThread = AfxBeginThread(
00172       ComputationThreadFunction,        // the controlling function for the worker thread
00173       &threadArgs,                      // the arguments and return value
00174       THREAD_PRIORITY_BELOW_NORMAL,     // the priority
00175       0,                                // 0: the stack size defaults to the same size
00176                                         //    stack as the creating thread.
00177       CREATE_SUSPENDED,                 // create it in suspended state
00178       NULL                              // security attributes structure
00179    );
00180 
00181    /*
00182     * show progress dialog, try to start thread:
00183     */
00184    if ( dlg.DoModal( hThread ) <= 0 )
00185    {
00186       return FALSE;
00187    };
00188 
00189    /*
00190     * return thread result:
00191     */
00192    return threadArgs.bReturn;
00193 }
00194 
00195 /**
00196  * create a thread that computes the result.
00197  */
00198 UINT CScanFilterFFT::ComputationThreadFunction( LPVOID lpContext )
00199 {
00200 //   Q_LOG( _T("CScanFilterFFT::ComputationThreadFunction()") );
00201 
00202    CScanFilterFFT::ThreadArgs *lpTreadArgs = static_cast< CScanFilterFFT::ThreadArgs* >( lpContext );
00203 
00204    lpTreadArgs->bReturn = lpTreadArgs->pThis->Compute( lpTreadArgs->pDlg );
00205 
00206    lpTreadArgs->pDlg->Terminate();
00207 
00208    return lpTreadArgs->bReturn;
00209 }
00210 
00211 /**
00212  * compute the desired result.
00213  */
00214 BOOL CScanFilterFFT::Compute( CProgressDlg *pDlg )
00215 {
00216    ASSERT( m_lpsbIn );
00217    ASSERT( m_lpsbOut );
00218 
00219    /*
00220     * prepare some local varables:
00221     */
00222    BOOL bL2R = m_lpsbIn->HasLeftToRightScan();
00223    BOOL bR2L = m_lpsbIn->HasRightToLeftScan();
00224 
00225    /*
00226     * update progress dlg; don't touch dialog from other thread!
00227     */
00228    pDlg->SetText ( _T("Computing 2D fast fourier transformation" ) );
00229    pDlg->SetRange( 0, bR2L && bL2R ? 8 : 4 );
00230 
00231 #if defined( ScanFilter_Use_FFTW )
00232    int  nrow = cil::GetSizeForFFT( m_lpsbIn->Rows()    );
00233    int  ncol = cil::GetSizeForFFT( m_lpsbIn->Columns() );
00234 #else
00235    int  nrow = m_lpsbIn->GetRowsForFFT();
00236    int  ncol = m_lpsbIn->GetColumnsForFFT();
00237 #endif // defined( ScanFilter_Use_FFTW )
00238 
00239    /*
00240     * (re)allocate buffers:
00241     */
00242    Q_RETURN( m_lpsbOut->ResizeDataBuffer( CSize( ncol, nrow ) ) );
00243    Q_RETURN( m_lpsbOut->CreateFourierBuffer()                   );
00244 
00245    /*
00246     * perform the left-right and right-left transformations:
00247     */
00248    m_progress = 0;
00249 
00250 #ifdef USE_SEPARATE_AMPLITUDE_SCALE
00251 
00252    if ( bL2R )
00253    {
00254       ComputePart(
00255          pDlg,
00256          ToImage( m_lpsbIn , false ),
00257          ToImage( m_lpsbOut, false ),
00258          m_lpsbOut->FourierDataL2R()
00259       );
00260    }
00261 
00262    if ( bR2L )
00263    {
00264       ComputePart(
00265          pDlg,
00266          ToImage( m_lpsbIn , true ),
00267          ToImage( m_lpsbOut, true ),
00268          m_lpsbOut->FourierDataR2L()
00269       );
00270 
00271 #else // ! USE_SEPARATE_AMPLITUDE_SCALE
00272 
00273    using cil::Size2D;
00274 
00275    /*
00276     * maximum amplitudes found for buffers:
00277     */
00278    RealType maxAmpL2R = 0;
00279    RealType maxAmpR2L = 0;
00280 
00281    /*
00282     * buffers for power spectrum:
00283     */
00284    Size2D zeroSize  (    0, 0    );
00285    Size2D fftSize   ( ncol, nrow );
00286 
00287    Size2D fftSizeL2R( bL2R ? fftSize : zeroSize );
00288    Size2D fftSizeR2L( bR2L ? fftSize : zeroSize );
00289 
00290    PowerImageType powerImageL2R( fftSizeL2R );
00291    PowerImageType powerImageR2L( fftSizeR2L );
00292 
00293    if ( bL2R )
00294    {
00295       maxAmpL2R = ComputePower(
00296          pDlg,
00297          ToImage( m_lpsbIn , false ),
00298          m_lpsbOut->FourierDataL2R(),
00299          powerImageL2R
00300       );
00301    }
00302 
00303    if ( bR2L )
00304    {
00305       maxAmpR2L = ComputePower(
00306          pDlg,
00307          ToImage( m_lpsbIn , true ),
00308          m_lpsbOut->FourierDataR2L(),
00309          powerImageR2L
00310       );
00311    }
00312 
00313    /*
00314     * select maximum amplitude to use:
00315     */
00316    enum ScaleSelector { e_Same, e_L2R, e_R2L };
00317    ScaleSelector s = e_Same;
00318 
00319    switch ( s )
00320    {
00321       case e_Same:
00322          maxAmpL2R = maxAmpR2L = lpm::absmax( maxAmpL2R, maxAmpR2L );
00323          break;
00324 
00325       case e_L2R:
00326          maxAmpR2L = maxAmpL2R ;
00327          break;
00328 
00329       case e_R2L:
00330          maxAmpL2R = maxAmpR2L;
00331          break;
00332    }
00333 
00334    /*
00335     * compute output:
00336     */
00337    if ( bL2R )
00338    {
00339       ComputeOutput(
00340          pDlg,
00341          maxAmpL2R,
00342          powerImageL2R,
00343          ToImage( m_lpsbOut, false )
00344       );
00345    }
00346 
00347    if ( bR2L )
00348    {
00349       ComputeOutput(
00350          pDlg,
00351          maxAmpR2L,
00352          powerImageR2L,
00353          ToImage( m_lpsbOut, true )
00354       );
00355    }
00356 #endif // USE_SEPARATE_AMPLITUDE_SCALE
00357 
00358    /*
00359     * check if a stop is requested from the progress dialog:
00360     */
00361    if ( pDlg->StopRequested() )
00362    {
00363       return FALSE;
00364    }
00365    else
00366    {
00367       return TRUE;
00368    }
00369 }
00370 
00371 #ifdef USE_SEPARATE_AMPLITUDE_SCALE
00372 
00373 /**
00374  * compute a frame.
00375  */
00376 void CScanFilterFFT::ComputePart( CProgressDlg *pDlg, const Image& src, Image& dst, FourierElementType** pFFT )
00377 {
00378    using   cil::Size2D;
00379 
00380    typedef std::complex< FourierElementType > Complex;
00381 
00382    typedef      Image             InputImageType;
00383    typedef      Image             OutputImageType;
00384 
00385    typedef cil::Image< RealType > PowerImageType;
00386    typedef cil::Image< Complex  > FFTImageType;
00387 
00388 #if defined( ScanFilter_Use_FFTW )
00389    typedef cil::FFTWImageFilter             < InputImageType , FFTImageType    > FFTImageFilter;
00390 #else
00391    typedef cil::FFTImageFilter              < InputImageType , FFTImageType    > FFTImageFilter;
00392 #endif // defined( ScanFilter_Use_FFTW )
00393    typedef cil::FFTPowerSpectrumImageFilter < FFTImageType   , PowerImageType  > FFTPowerSpectrumImageFilter;
00394    typedef cil::FFTSwapQuadrantsImageFilter < OutputImageType                  > FFTSwapQuadrantsImageFilter;
00395    typedef cil::ShiftScaleImageFilter       < PowerImageType , OutputImageType > ScaleImageFilter;
00396 
00397    /*
00398     * the FFT Image view on the CScanBaseBuffer FFT databuffer:
00399     *
00400     * the FFT Image is a 1-dimensional array of complex<FourierElementType>
00401     * the CScanBaseBuffer FFT databuffer is a 2-dimensional array of FourierElementType
00402     *
00403     *            fftImage.Data () ----------->   cmplx
00404     * m_lpsbOut->FourierDataL2R() => [row0] -> [ re,im . . . ]  <- important: contiguous block
00405     *                                   .      [   .   . . . ]
00406     *                                   .      [   .   . . . ]
00407     *                                [rowN] -> [   .   . . . ]
00408     *
00409     */
00410    Size2D fftSize( Size2D( dst.Width(), dst.Height() ) );
00411    FFTImageType fftImage( reinterpret_cast<FFTImageType::PixelType*>( cil::To1DView( pFFT ) ), fftSize );
00412 
00413 #if defined( USE_FFT_FFTI )     // for test, perform fft-fft inverse
00414    /*
00415     * filters:
00416     */
00417    typedef cil::FFTWInverseImageFilter< FFTImageType, OutputImageType > FFTInverseImageFilter;
00418 
00419    FFTImageFilter        fftFilter;
00420    FFTInverseImageFilter fftiFilter;
00421 
00422    /*
00423     * perform transformations:
00424     */
00425     fftFilter.Apply( src     , fftImage );
00426    fftiFilter.Apply( fftImage, dst      );
00427 #else // !USE_FFT_FFTI
00428    /*
00429     * buffer for power spectrum:
00430     */
00431    PowerImageType powerImage( fftSize );  // this is temporary
00432 
00433    /*
00434     * filters:
00435     */
00436    FFTImageFilter                 fftFilter;
00437    FFTPowerSpectrumImageFilter    powerSpectrumFilter;
00438    FFTSwapQuadrantsImageFilter    swapQuadrantsFilter;
00439    ScaleImageFilter               scaleFilter;
00440 
00441    /*
00442     * perform transformations:
00443     */
00444              fftFilter.Apply( src       , fftImage   ); pDlg->SetPos( ++m_progress );
00445    powerSpectrumFilter.Apply( fftImage  , powerImage ); pDlg->SetPos( ++m_progress );
00446 
00447         scaleFilter.SetScale( maximumAmplitude / powerSpectrumFilter.GetAbsoluteMaximumAmplitude() );
00448 
00449            scaleFilter.Apply( powerImage, dst        ); pDlg->SetPos( ++m_progress );
00450    swapQuadrantsFilter.Apply( dst                    ); pDlg->SetPos( ++m_progress );
00451 #endif
00452 }
00453 
00454 /*
00455  * stubs
00456  */
00457 #pragma warning( disable : 4100 )       // unreferenced formal parameter
00458 CScanFilterFFT::RealType CScanFilterFFT::ComputePower( CProgressDlg *pDlg, const Image& src, FourierElementType** pFFT, PowerImageType& pwr )
00459 {
00460 }
00461 
00462 void CScanFilterFFT::ComputeOutput( CProgressDlg *pDlg, RealType maxAmpIn, const PowerImageType& pwr, Image& dst )
00463 {
00464 }
00465 #pragma warning( default : 4100 )
00466 
00467 #else // ! USE_SEPARATE_AMPLITUDE_SCALE
00468 
00469 /*
00470  * stub
00471  */
00472 #pragma warning( disable : 4100 )       // unreferenced formal parameter
00473 void CScanFilterFFT::ComputePart( CProgressDlg *pDlg, const Image& src, Image& dst, FourierElementType** pFFT )
00474 {
00475 }
00476 #pragma warning( default : 4100 )
00477 
00478 #if defined( _CIL_MSC_6 )
00479 #pragma optimize( "atpw", on )
00480 #endif
00481 /**
00482  * compute power for a frame.
00483  */
00484 CScanFilterFFT::RealType CScanFilterFFT::ComputePower( CProgressDlg *pDlg, const Image& src, FourierElementType** pFFT, PowerImageType& pwr )
00485 {
00486    using   cil::Size2D;
00487 
00488    typedef std::complex< FourierElementType > Complex;
00489 
00490    typedef      Image             InputImageType;
00491    typedef      Image             OutputImageType;
00492 
00493    typedef cil::Image< Complex  > FFTImageType;
00494 
00495 #if defined( ScanFilter_Use_FFTW )
00496    typedef cil::FFTWImageFilter             < InputImageType , FFTImageType    > FFTImageFilter;
00497 #else
00498    typedef cil::FFTImageFilter              < InputImageType , FFTImageType    > FFTImageFilter;
00499 #endif // defined( ScanFilter_Use_FFTW )
00500    typedef cil::FFTPowerSpectrumImageFilter < FFTImageType   , PowerImageType  > FFTPowerSpectrumImageFilter;
00501 
00502    /*
00503     * the FFT Image view on the CScanBaseBuffer FFT databuffer:
00504     *
00505     * the FFT Image is a 1-dimensional array of complex<FourierElementType>
00506     * the CScanBaseBuffer FFT databuffer is a 2-dimensional array of FourierElementType
00507     *
00508     *            fftImage.Data () ----------->   cmplx
00509     * m_lpsbOut->FourierDataL2R() => [row0] -> [ re,im . . . ]  <- important: contiguous block
00510     *                                   .      [   .   . . . ]
00511     *                                   .      [   .   . . . ]
00512     *                                [rowN] -> [   .   . . . ]
00513     *
00514     */
00515    Size2D fftSize( Size2D( pwr.Width(), pwr.Height() ) );
00516    FFTImageType fftImage( reinterpret_cast<FFTImageType::PixelType*>( cil::To1DView( pFFT ) ), fftSize );
00517 
00518    /*
00519     * filters:
00520     */
00521    FFTImageFilter                 fftFilter;
00522    FFTPowerSpectrumImageFilter    powerSpectrumFilter;
00523 
00524    /*
00525     * perform transformations:
00526     */
00527              fftFilter.Apply( src       , fftImage ); pDlg->SetPos( ++m_progress );
00528    powerSpectrumFilter.Apply( fftImage  , pwr      ); pDlg->SetPos( ++m_progress );
00529 
00530    return powerSpectrumFilter.GetAbsoluteMaximumAmplitude();
00531 }
00532 
00533 /**
00534  * compute output for a frame.
00535  */
00536 void CScanFilterFFT::ComputeOutput( CProgressDlg *pDlg, RealType maxAmpIn, const PowerImageType& pwr, Image& dst )
00537 {
00538    using   cil::Size2D;
00539 
00540    typedef Image OutputImageType;
00541 
00542    typedef cil::ShiftScaleImageFilter       < PowerImageType , OutputImageType > ScaleImageFilter;
00543    typedef cil::FFTSwapQuadrantsImageFilter < OutputImageType                  > FFTSwapQuadrantsImageFilter;
00544 
00545    /*
00546     * filters:
00547     */
00548    ScaleImageFilter            scaleFilter;
00549    FFTSwapQuadrantsImageFilter swapQuadrantsFilter;
00550 
00551    /*
00552     * perform transformations:
00553     */
00554         scaleFilter.SetScale( maximumAmplitude / maxAmpIn );
00555 
00556            scaleFilter.Apply( pwr, dst ); pDlg->SetPos( ++m_progress );
00557    swapQuadrantsFilter.Apply( dst      ); pDlg->SetPos( ++m_progress );
00558 }
00559 #pragma optimize( "", on )      // restore
00560 
00561 #endif // #ifdef USE_SEPARATE_AMPLITUDE_SCALE
00562 
00563 /*
00564  * end of file
00565  */

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