/*=========================================================================
*
*  Copyright NumFOCUS
*
*  Licensed under the Apache License, Version 2.0 (the "License");
*  you may not use this file except in compliance with the License.
*  You may obtain a copy of the License at
*
*         http://www.apache.org/licenses/LICENSE-2.0.txt
*
*  Unless required by applicable law or agreed to in writing, software
*  distributed under the License is distributed on an "AS IS" BASIS,
*  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*  See the License for the specific language governing permissions and
*  limitations under the License.
*
*=========================================================================*/
#ifndef sitkMaskedFFTNormalizedCorrelationImageFilter_h
#define sitkMaskedFFTNormalizedCorrelationImageFilter_h

/*
 * WARNING: DO NOT EDIT THIS FILE!
 * THIS FILE IS AUTOMATICALLY GENERATED BY THE SIMPLEITK BUILD PROCESS.
 * Please look at sitkImageFilterTemplate.h.in to make changes.
 */

#include <memory>

#include "sitkBasicFilters.h"
#include "sitkImageFilter.h"

namespace itk::simple {

    /**\class MaskedFFTNormalizedCorrelationImageFilter
\brief Calculate masked normalized cross correlation using FFTs.

This filter calculates the masked normalized cross correlation (NCC) of two images under masks using FFTs instead of spatial correlation. It is much faster than spatial correlation for reasonably large structuring elements. This filter is not equivalent to simply masking the images first and then correlating them; the latter approach yields incorrect results because the zeros in the images still affect the metric in the correlation process. This filter implements the masked NCC correctly so that the masked-out regions are completely ignored. The fundamental difference is described in detail in the references below. If the masks are set to images of all ones, the result of this filter is the same as standard NCC.

Inputs: Two images are required as inputs, fixedImage and movingImage, and two are optional, fixedMask and movingMask. In the context of correlation, inputs are often defined as: "image" and "template". In this filter, the fixedImage plays the role of the image, and the movingImage plays the role of the template. However, this filter is capable of correlating any two images and is not restricted to small movingImages (templates). In the fixedMask and movingMask, non-zero positive values indicate locations of useful information in the corresponding image, whereas zero and negative values indicate locations that should be masked out (ignored). Internally, the masks are converted to have values of only 0 and 1. For each optional mask that is not set, the filter internally creates an image of ones, which is equivalent to not masking the image. Thus, if both masks are not set, the result will be equivalent to unmasked NCC. For example, if only a mask for the fixed image is needed, the movingMask can either not be set or can be set to an image of ones.

Optional parameters: The RequiredNumberOfOverlappingPixels enables the user to specify the minimum number of voxels of the two masks that must overlap; any location in the correlation map that results from fewer than this number of voxels will be set to zero. Larger values zero-out pixels on a larger border around the correlation image. Thus, larger values remove less stable computations but also limit the capture range. If RequiredNumberOfOverlappingPixels is set to 0, the default, no zeroing will take place.

The RequiredFractionOfOverlappingPixels enables the user to specify a fraction of the maximum number of overlapping pixels that need to overlap; any location in the correlation map that results from fewer than the product of this fraction and the internally computed maximum number of overlapping pixels will be set to zero. The value ranges between 0.0 and 1.0. This is very useful when the user does does not know beforehand the maximum number of pixels of the masks that will overlap. For example, when the masks have strange shapes, it is difficult to predict how the correlation of the masks will interact and what the maximum overlap will be. It is also useful when the mask shapes or sizes change because it is relative to the internally computed maximum of the overlap. Larger values zero-out pixels on a larger border around the correlation image. Thus, larger values remove less stable computations but also limit the capture range. Experiments have shown that a value between 0.1 and 0.6 works well for images with significant overlap and between 0.05 and 0.1 for images with little overlap (such as in stitching applications). If RequiredFractionOfOverlappingPixels is set to 0, the default, no zeroing will take place.

The user can either specify RequiredNumberOfOverlappingPixels or RequiredFractionOfOverlappingPixels (or both or none). Internally, the number of required pixels resulting from both of these methods is calculated and the one that gives the largest number of pixels is chosen. Since these both default to 0, if a user only sets one, the other is ignored.

Image size: fixedImage and movingImage need not be the same size, but fixedMask must be the same size as fixedImage, and movingMask must be the same size as movingImage. Furthermore, whereas some algorithms require that the "template" be smaller than the "image" because of errors in the regions where the two are not fully overlapping, this filter has no such restriction.

Image spacing: Since the computations are done in the pixel domain, all input images must have the same spacing.

Outputs; The output is an image of RealPixelType that is the masked NCC of the two images and its values range from -1.0 to 1.0. The size of this NCC image is, by definition, size(fixedImage) + size(movingImage) - 1.

Example filter usage: \code
using FilterType = itk::MaskedFFTNormalizedCorrelationImageFilter< ShortImageType, DoubleImageType > ;

auto filter = FilterType::New ();

filter->SetFixedImage( fixedImage );

filter->SetMovingImage( movingImage );

filter->SetFixedImageMask( fixedMask );

filter->SetMovingImageMask( movingMask );

filter->SetRequiredNumberOfOverlappingPixels(20);

filter->Update();

\endcode


\warning The pixel type of the output image must be of real type (float or double). ConceptChecking is used to enforce the output pixel type. You will get a compilation error if the pixel type of the output image is not float or double.


References: 1) D. Padfield. "Masked object registration in the Fourier domain." Transactions on Image Processing. 2) D. Padfield. "Masked FFT registration". In Proc. Computer Vision and Pattern Recognition, 2010.

\author : Dirk Padfield, GE Global Research, padfield@research.ge.com
\sa itk::simple::MaskedFFTNormalizedCorrelation for the procedural interface
\sa itk::MaskedFFTNormalizedCorrelationImageFilter for the Doxygen on the original ITK class.
     */
    class SITKBasicFilters_EXPORT MaskedFFTNormalizedCorrelationImageFilter : public ImageFilter {
    public:
      using Self = MaskedFFTNormalizedCorrelationImageFilter;

      /** Destructor */
      virtual ~MaskedFFTNormalizedCorrelationImageFilter();

      /** Default Constructor that takes no arguments and initializes
       * default parameters */
      MaskedFFTNormalizedCorrelationImageFilter();

      /** Define the pixels types supported by this filter */
      using PixelIDTypeList = BasicPixelIDTypeList;
\

      /**
       * Set and get the required number of overlapping pixels
       */
      SITK_RETURN_SELF_TYPE_HEADER SetRequiredNumberOfOverlappingPixels ( uint64_t RequiredNumberOfOverlappingPixels ) { this->m_RequiredNumberOfOverlappingPixels = RequiredNumberOfOverlappingPixels; return *this; }

      /**
       * Set and get the required number of overlapping pixels
       */
      uint64_t GetRequiredNumberOfOverlappingPixels() const { return this->m_RequiredNumberOfOverlappingPixels; }\

      /**
       * Set and get the required fraction of overlapping pixels
       */
      SITK_RETURN_SELF_TYPE_HEADER SetRequiredFractionOfOverlappingPixels ( float RequiredFractionOfOverlappingPixels ) { this->m_RequiredFractionOfOverlappingPixels = RequiredFractionOfOverlappingPixels; return *this; }

      /**
       * Set and get the required fraction of overlapping pixels
       */
      float GetRequiredFractionOfOverlappingPixels() const { return this->m_RequiredFractionOfOverlappingPixels; }

      /** Name of this class */
      std::string GetName() const { return std::string ("MaskedFFTNormalizedCorrelationImageFilter"); }

      /** Print ourselves out */
      std::string ToString() const;


      /** Execute the filter on the input image */

      Image Execute ( const Image & fixedImage, const Image & movingImage, const Image & fixedImageMask, const Image & movingImageMask );

    private:

      /** Setup for member function dispatching */

      using MemberFunctionType = Image (Self::*)( const Image * fixedImage, const Image * movingImage, const Image * fixedImageMask, const Image * movingImageMask );
      template <class TImageType> Image ExecuteInternal ( const Image * fixedImage, const Image * movingImage, const Image * fixedImageMask, const Image * movingImageMask );


      friend struct detail::MemberFunctionAddressor<MemberFunctionType>;

      std::unique_ptr<detail::MemberFunctionFactory<MemberFunctionType> > m_MemberFactory;


      uint64_t  m_RequiredNumberOfOverlappingPixels{0u};

      float  m_RequiredFractionOfOverlappingPixels{0.0};


    };

    /**\
     * \brief Calculate masked normalized cross correlation using FFTs.
     *
     * This function directly calls the execute method of MaskedFFTNormalizedCorrelationImageFilter
     * in order to support a procedural API
     *
     * \sa itk::simple::MaskedFFTNormalizedCorrelationImageFilter for the object oriented interface
     * @{
     */

     SITKBasicFilters_EXPORT Image MaskedFFTNormalizedCorrelation ( const Image & fixedImage, const Image & movingImage, const Image & fixedImageMask, const Image & movingImageMask, uint64_t requiredNumberOfOverlappingPixels = 0u, float requiredFractionOfOverlappingPixels = 0.0 );

     /** @} */
}
#endif
