PCL
FFTConvolution.h
Go to the documentation of this file.
1 // ____ ______ __
2 // / __ \ / ____// /
3 // / /_/ // / / /
4 // / ____// /___ / /___ PixInsight Class Library
5 // /_/ \____//_____/ PCL 2.4.7
6 // ----------------------------------------------------------------------------
7 // pcl/FFTConvolution.h - Released 2020-12-17T15:46:29Z
8 // ----------------------------------------------------------------------------
9 // This file is part of the PixInsight Class Library (PCL).
10 // PCL is a multiplatform C++ framework for development of PixInsight modules.
11 //
12 // Copyright (c) 2003-2020 Pleiades Astrophoto S.L. All Rights Reserved.
13 //
14 // Redistribution and use in both source and binary forms, with or without
15 // modification, is permitted provided that the following conditions are met:
16 //
17 // 1. All redistributions of source code must retain the above copyright
18 // notice, this list of conditions and the following disclaimer.
19 //
20 // 2. All redistributions in binary form must reproduce the above copyright
21 // notice, this list of conditions and the following disclaimer in the
22 // documentation and/or other materials provided with the distribution.
23 //
24 // 3. Neither the names "PixInsight" and "Pleiades Astrophoto", nor the names
25 // of their contributors, may be used to endorse or promote products derived
26 // from this software without specific prior written permission. For written
27 // permission, please contact info@pixinsight.com.
28 //
29 // 4. All products derived from this software, in any form whatsoever, must
30 // reproduce the following acknowledgment in the end-user documentation
31 // and/or other materials provided with the product:
32 //
33 // "This product is based on software from the PixInsight project, developed
34 // by Pleiades Astrophoto and its contributors (https://pixinsight.com/)."
35 //
36 // Alternatively, if that is where third-party acknowledgments normally
37 // appear, this acknowledgment must be reproduced in the product itself.
38 //
39 // THIS SOFTWARE IS PROVIDED BY PLEIADES ASTROPHOTO AND ITS CONTRIBUTORS
40 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
41 // TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL PLEIADES ASTROPHOTO OR ITS
43 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
44 // EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, BUSINESS
45 // INTERRUPTION; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; AND LOSS OF USE,
46 // DATA OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
47 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
48 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
49 // POSSIBILITY OF SUCH DAMAGE.
50 // ----------------------------------------------------------------------------
51 
52 #ifndef __PCL_FFTConvolution_h
53 #define __PCL_FFTConvolution_h
54 
56 
57 #include <pcl/Defs.h>
58 #include <pcl/Diagnostics.h>
59 
60 #include <pcl/AutoPointer.h>
62 #include <pcl/KernelFilter.h>
63 #include <pcl/ParallelProcess.h>
64 
65 namespace pcl
66 {
67 
68 // ----------------------------------------------------------------------------
69 
87 class PCL_CLASS FFTConvolution : public ImageTransformation, public ParallelProcess
88 {
89 public:
90 
98  FFTConvolution() = default;
99 
109  FFTConvolution( const KernelFilter& filter )
110  : m_filter( filter.Clone() )
111  {
112  PCL_CHECK( bool( m_filter ) )
113  }
114 
129  : m_image( f )
130  {
131  PCL_CHECK( bool( m_image ) )
132  }
133 
138  : ImageTransformation( x )
139  , ParallelProcess( x )
140  , m_image( x.m_image )
141  , m_outputRealCmp( x.m_outputRealCmp )
142  {
143  if ( x.m_filter )
144  m_filter = x.m_filter->Clone();
145  }
146 
150  FFTConvolution( FFTConvolution&& ) = default;
151 
155  virtual ~FFTConvolution()
156  {
157  }
158 
162  FFTConvolution& operator =( const FFTConvolution& x )
163  {
164  if ( &x != this )
165  {
166  (void)ImageTransformation::operator =( x );
167  (void)ParallelProcess::operator =( x );
168  DestroyFilter();
169  if ( x.m_filter )
170  m_filter = x.m_filter->Clone();
171  else
172  m_image = x.m_image;
173  m_outputRealCmp = x.m_outputRealCmp;
174  }
175  return *this;
176  }
177 
181  FFTConvolution& operator =( FFTConvolution&& ) = default;
182 
187  bool UsingFilter() const
188  {
189  return m_filter;
190  }
191 
199  const KernelFilter& Filter() const
200  {
201  PCL_PRECONDITION( bool( m_filter ) )
202  return *m_filter;
203  }
204 
215  const ImageVariant& FilterImage() const
216  {
217  return m_image;
218  }
219 
228  void SetFilter( const KernelFilter& filter )
229  {
230  DestroyFilter();
231  m_filter = filter.Clone();
232  PCL_CHECK( bool( m_filter ) )
233  }
234 
245  void SetFilter( const ImageVariant& filter )
246  {
247  DestroyFilter();
248  m_image = filter;
249  PCL_CHECK( bool( m_image ) )
250  }
251 
274  {
275  return m_h;
276  }
277 
289  {
290  return m_outputRealCmp;
291  }
292 
304  {
305  return !m_outputRealCmp;
306  }
307 
314  void EnableRealComponentOutput( bool enable = true )
315  {
316  m_outputRealCmp = enable;
317  }
318 
325  void EnableMagnitudeOutput( bool enable = true )
326  {
327  m_outputRealCmp = !enable;
328  }
329 
342  static constexpr int FasterThanNonseparableFilterSize( int numThreads )
343  {
344 #ifdef __PCL_COMPATIBILITY
345 
346  // No vectorization
347 
348  if ( numThreads >= 32 )
349  return 17;
350  if ( numThreads >= 24 )
351  return 15;
352  if ( numThreads >= 12 )
353  return 13;
354  if ( numThreads >= 8 )
355  return 11;
356  return 9;
357 
358 #else
359 
360  // Vectorization with SSE4.2 / AVX2 and FMA instructions
361 
362  if ( numThreads >= 32 )
363  return 29;
364  if ( numThreads >= 24 )
365  return 27;
366  if ( numThreads >= 16 )
367  return 25;
368  if ( numThreads >= 12 )
369  return 21;
370  if ( numThreads >= 8 )
371  return 19;
372  if ( numThreads >= 4 )
373  return 17;
374  if ( numThreads >= 2 )
375  return 15;
376  return 13;
377 
378 #endif
379  }
380 
393  static constexpr int FasterThanSeparableFilterSize( int numThreads )
394  {
395 #ifdef __PCL_COMPATIBILITY
396 
397  // No vectorization
398 
399  if ( numThreads >= 24 )
400  return 191;
401  if ( numThreads >= 16 )
402  return 141;
403  if ( numThreads >= 12 )
404  return 135;
405  if ( numThreads >= 8 )
406  return 95;
407  if ( numThreads >= 4 )
408  return 75;
409  return 61;
410 
411 #else
412 
413  // Vectorization with SSE4.2 / AVX2 and FMA instructions
414 
415  if ( numThreads >= 16 )
416  return 901;
417  if ( numThreads >= 12 )
418  return 831;
419  if ( numThreads >= 8 )
420  return 741;
421  return 395;
422 
423 #endif
424  }
425 
426 protected:
427 
428  /*
429  * The response function for convolution is defined as either a KernelFilter
430  * instance or as an image. In the latter case, the image transported by the
431  * ImageVariant must remain valid while this object is actively used.
432  */
433  AutoPointer<KernelFilter> m_filter;
434  ImageVariant m_image;
435  bool m_outputRealCmp = false;
436 
437  /*
438  * Internal DFT of the response function. Initially zero. This matrix is
439  * generated/reused/regenerated as this object is applied to convolve
440  * different target images. It is destroyed when a new filter is specified.
441  */
442  mutable AutoPointer<ComplexImage> m_h;
443 
444  /*
445  * In-place Fourier-based 2-D convolution algorithm.
446  */
447  void Apply( pcl::Image& ) const override;
448  void Apply( pcl::DImage& ) const override;
449  void Apply( pcl::UInt8Image& ) const override;
450  void Apply( pcl::UInt16Image& ) const override;
451  void Apply( pcl::UInt32Image& ) const override;
452  void Apply( pcl::ComplexImage& ) const override;
453  void Apply( pcl::DComplexImage& ) const override;
454 
455  friend class PCL_FFTConvolutionEngine;
456 
457 private:
458 
459  void DestroyFilter()
460  {
461  m_filter.Destroy();
462  m_image.Free();
463  m_h.Destroy();
464  }
465 
466  void Validate() const;
467  void ValidateFilter() const;
468 };
469 
470 // ----------------------------------------------------------------------------
471 
472 } // pcl
473 
474 #endif // __PCL_FFTConvolution_h
475 
476 // ----------------------------------------------------------------------------
477 // EOF pcl/FFTConvolution.h - Released 2020-12-17T15:46:29Z
void SetFilter(const KernelFilter &filter)
bool IsMagnitudeOutputEnabled() const
void EnableRealComponentOutput(bool enable=true)
const KernelFilter & Filter() const
FFTConvolution(const ImageVariant &f)
bool UsingFilter() const
const ImageVariant & FilterImage() const
PCL root namespace.
Definition: AbstractImage.h:76
virtual KernelFilter * Clone() const
Definition: KernelFilter.h:190
A smart pointer with exclusive object ownership and optional automatic object destruction.
Definition: AutoPointer.h:241
16-bit unsigned integer image.
void SetFilter(const ImageVariant &filter)
void EnableMagnitudeOutput(bool enable=true)
Acts like a union for all types of images in PCL, with optional class-wide ownership of transported i...
Definition: ImageVariant.h:317
FFTConvolution(const KernelFilter &filter)
32-bit floating point complex image.
void Apply(FI i, FI j, F f) noexcept(noexcept(f))
Definition: Utility.h:249
64-bit floating point real image.
32-bit unsigned integer image.
8-bit unsigned integer image.
ImageVariant & Free()
Root base class of all PCL image transformations.
Kernel filter in two dimensions.
Definition: KernelFilter.h:89
const ComplexImage * ResponseFunctionDFT() const
bool IsRealComponentOutputEnabled() const
static constexpr int FasterThanSeparableFilterSize(int numThreads)
64-bit floating point complex image.
static constexpr int FasterThanNonseparableFilterSize(int numThreads)
Fourier-based two-dimensional convolution in the spatial domain.
32-bit floating point real image.
FFTConvolution(const FFTConvolution &x)
A process using multiple concurrent execution threads.