00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "stdafx.h"
00019
00020 #include <cfl/resource.h>
00021
00022 #include <Camera/InterfaceDll.h>
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034 #include <cfl/ScanFilterFFT.h>
00035 #include <cfl/ToolCilImage.h>
00036 #include <cil/Math.h>
00037
00038 #if defined( ScanFilter_Use_FFTW )
00039 # include <cil/FFTWImageFilter.h>
00040 # include <cil/FFTWInverseImageFilter.h>
00041 #else
00042 # include <cil/FFTImageFilter.h>
00043 # include <cil/FFTInverseImageFilter.h>
00044 #endif // defined( ScanFilter_Use_FFTW )
00045
00046 #include <cil/FFTPowerSpectrumImageFilter.h>
00047 #include <cil/FFTSwapQuadrantsImageFilter.h>
00048 #include <cil/ShiftScaleImageFilter.h>
00049
00050
00051
00052
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
00065 LPCTSTR CScanFilterFFT::m_lpcsFilterName = _T("Fast-Fourier-Transform");
00066
00067 LPCTSTR CScanFilterFFT::m_lpcsShortFilterName = _T( "FFT" );
00068
00069 const CScanFilterFFT::ValueType CScanFilterFFT::maximumAmplitude = 20000;
00070
00071 IMPLEMENT_SERIAL(CScanFilterFFT, CScanFilter, CFL_SCHEMAVERSION_FILTERFFT )
00072
00073
00074
00075
00076 CScanFilterFFT::CScanFilterFFT()
00077 : m_progress( 0 )
00078 {
00079 m_csFilterName = m_lpcsFilterName;
00080 }
00081
00082
00083
00084
00085 CScanFilterFFT::~CScanFilterFFT()
00086 {
00087 ;
00088 }
00089
00090
00091
00092
00093 BOOL CScanFilterFFT::CanDoDialogEntry() const
00094 {
00095 return FALSE;
00096 }
00097
00098
00099
00100
00101
00102 void CScanFilterFFT::Serialize(CArchive& ar)
00103 {
00104 CScanFilter::Serialize( ar );
00105
00106 if ( ar.IsStoring() )
00107 {
00108 ;
00109 }
00110 else
00111 {
00112 ;
00113 }
00114 };
00115
00116
00117
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
00131
00132 LPCTSTR CScanFilterFFT::GetParameters() const
00133 {
00134 return NULL;
00135 }
00136
00137
00138
00139
00140
00141
00142 BOOL CScanFilterFFT::Apply()
00143 {
00144
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
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
00165
00166
00167 CProgressDlg dlg( AfxGetMainWnd() );
00168
00169 ThreadArgs threadArgs( &dlg, this );
00170
00171 CWinThread *hThread = AfxBeginThread(
00172 ComputationThreadFunction,
00173 &threadArgs,
00174 THREAD_PRIORITY_BELOW_NORMAL,
00175 0,
00176
00177 CREATE_SUSPENDED,
00178 NULL
00179 );
00180
00181
00182
00183
00184 if ( dlg.DoModal( hThread ) <= 0 )
00185 {
00186 return FALSE;
00187 };
00188
00189
00190
00191
00192 return threadArgs.bReturn;
00193 }
00194
00195
00196
00197
00198 UINT CScanFilterFFT::ComputationThreadFunction( LPVOID lpContext )
00199 {
00200
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
00213
00214 BOOL CScanFilterFFT::Compute( CProgressDlg *pDlg )
00215 {
00216 ASSERT( m_lpsbIn );
00217 ASSERT( m_lpsbOut );
00218
00219
00220
00221
00222 BOOL bL2R = m_lpsbIn->HasLeftToRightScan();
00223 BOOL bR2L = m_lpsbIn->HasRightToLeftScan();
00224
00225
00226
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
00241
00242 Q_RETURN( m_lpsbOut->ResizeDataBuffer( CSize( ncol, nrow ) ) );
00243 Q_RETURN( m_lpsbOut->CreateFourierBuffer() );
00244
00245
00246
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
00277
00278 RealType maxAmpL2R = 0;
00279 RealType maxAmpR2L = 0;
00280
00281
00282
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
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
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
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
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
00399
00400
00401
00402
00403
00404
00405
00406
00407
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
00416
00417 typedef cil::FFTWInverseImageFilter< FFTImageType, OutputImageType > FFTInverseImageFilter;
00418
00419 FFTImageFilter fftFilter;
00420 FFTInverseImageFilter fftiFilter;
00421
00422
00423
00424
00425 fftFilter.Apply( src , fftImage );
00426 fftiFilter.Apply( fftImage, dst );
00427 #else // !USE_FFT_FFTI
00428
00429
00430
00431 PowerImageType powerImage( fftSize );
00432
00433
00434
00435
00436 FFTImageFilter fftFilter;
00437 FFTPowerSpectrumImageFilter powerSpectrumFilter;
00438 FFTSwapQuadrantsImageFilter swapQuadrantsFilter;
00439 ScaleImageFilter scaleFilter;
00440
00441
00442
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
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
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
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
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515 Size2D fftSize( Size2D( pwr.Width(), pwr.Height() ) );
00516 FFTImageType fftImage( reinterpret_cast<FFTImageType::PixelType*>( cil::To1DView( pFFT ) ), fftSize );
00517
00518
00519
00520
00521 FFTImageFilter fftFilter;
00522 FFTPowerSpectrumImageFilter powerSpectrumFilter;
00523
00524
00525
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
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
00547
00548 ScaleImageFilter scaleFilter;
00549 FFTSwapQuadrantsImageFilter swapQuadrantsFilter;
00550
00551
00552
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
00565