From 5501978d0f180594060740c051603fce711cfd2d Mon Sep 17 00:00:00 2001 From: Pablo Hernandez-Cerdan Date: Thu, 9 Dec 2021 19:42:54 +0100 Subject: [PATCH 01/18] ENH: Create external module from the InsightJournal publication 692 FastBilateralFilter from https://www.insight-journal.org/browse/publication/692 Exported as-is. Memory consumption is reported to be high. Reviews: ``` This filter bring great improvement in speed, with difference to classic bilateral filter being invisible to the naked eye. Evidence: They provide a test image and compare output of their filter to the output of classic filter. The choice of the image is not the greatest (differences barely visible with the image quality used). Open Science: Souce code supplied, worked out-of-the-box, test images available. Reproducibility: The code worked when I exchanged it for classic bilateral filter in my own project. Suggestion: Add a test case for 3D images. Open source Contributions: The code is very usable. Use is well described, and it took me 5 minutes to test it and use it. Code Quality : Code was readable, but I did not check it thouroughly. Free comment : Classic bilateral filter takes too long, ~4 minutes for relatively small 3D image. This filter is the solution. ``` ``` The problem of denoising images without introducing any unwanted intensity transformations is quite challenging by itself. One way of reducing the negative effects of denoising is to use local processing instead of global one. Such localization can be thought even more abstractly as processing the local vicinity of the variable. A good example of such approach is the family of bilateral filters where classification of the vicinity applies to both an intensity range and spatial domain. As a consequense, processing with bilateral filters provides very good noise removal while still preserving edges and image features at finer scales which makes the family of bilateral filters very attarctive for image processing tasks. The ITK library does have a bilateral filter implemented. However that implementation is extremely slow. The author of this submission implemented the bilateral filter that is very very fast. Evidence: The author provides the manual, source code along with input/output images thus the work could easily be validated. Open Science: The work follows the Open Science spirit. The author does provide the both source code and images. The manual is well written and is very handy for the users. Reproducibility: The reviewer was easily able to reproduce the authors' work and the outputs are idetical to those provided by the author. After downloading the code, the compilation process went without any problems and the reviewer did not experienced any problems with running the executables either. It just worked as it was supposed to. Use of Open Source Software: The author did use Open Source Software and the code was contributed as the Open Source package too. Open source Contributions: The author does provide the code in the form that allows to easy compile and use it.In the manual the author described in details the algorithm basis and provided the examples with parameters which was very useful. The process took very short time. Code Quality : The author provides the source code which is easy to read. The reviewer used this code on Linux (Debian Lenny) platform with gcc 4.2.3 and did not experience any problems. The code runs very fast. The code follows a modern coding style and the ITK rules so the reviewer would recommend this submission to be included to the ITK lib. There also should be mentioned one very usefull advantage of the submitted code: the author preserve the class API which resemble the API of analogous filter from the ITK library. The reviewer considers this as a big plus. Quality of the data : Qualit of the data is good and it is easy to use. Interest: The field of the Signal and Image denoising, where preserving edges and finer features are the most required properties. Free comment : The reviewer made some performance tests which demonstarted that the FastBilateral filter from this submission performed 200 times as much vs itk:: BilateralImageFilter. So the reviewer is very happy while using this FastBilateral filterfilter and highly recommends to include it into the ITK library. ``` Comments: @dzenan: ``` I just now realized that for small sigmas, this filter requires immense amounts of memory! Domain sigma=1.0 with image size 448x448x15 requires 12GB of intermediate storage. ``` --- .../Filtering/FastBilateral/CMakeLists.txt | 13 + .../include/itkFastBilateralImageFilter.h | 195 ++++++++++ .../include/itkFastBilateralImageFilter.hxx | 337 ++++++++++++++++++ .../Filtering/FastBilateral/itk-module.cmake | 27 ++ ...tBilateralImageFilterTestOutput.mha.sha512 | 1 + .../FastBilateral/test/CMakeLists.txt | 16 + .../test/itkFastBilateralImageFilterTest.cxx | 100 ++++++ .../FastBilateral/wrapping/CMakeLists.txt | 3 + .../wrapping/itkFastBilateralImageFilter.wrap | 4 + 9 files changed, 696 insertions(+) create mode 100644 Modules/Filtering/FastBilateral/CMakeLists.txt create mode 100644 Modules/Filtering/FastBilateral/include/itkFastBilateralImageFilter.h create mode 100644 Modules/Filtering/FastBilateral/include/itkFastBilateralImageFilter.hxx create mode 100644 Modules/Filtering/FastBilateral/itk-module.cmake create mode 100644 Modules/Filtering/FastBilateral/test/Baseline/itkFastBilateralImageFilterTestOutput.mha.sha512 create mode 100644 Modules/Filtering/FastBilateral/test/CMakeLists.txt create mode 100644 Modules/Filtering/FastBilateral/test/itkFastBilateralImageFilterTest.cxx create mode 100644 Modules/Filtering/FastBilateral/wrapping/CMakeLists.txt create mode 100644 Modules/Filtering/FastBilateral/wrapping/itkFastBilateralImageFilter.wrap diff --git a/Modules/Filtering/FastBilateral/CMakeLists.txt b/Modules/Filtering/FastBilateral/CMakeLists.txt new file mode 100644 index 00000000000..5f6c50692cf --- /dev/null +++ b/Modules/Filtering/FastBilateral/CMakeLists.txt @@ -0,0 +1,13 @@ +cmake_minimum_required(VERSION 3.16.3) +project(FastBilateral) + +# set(FastBilateral_LIBRARIES FastBilateral) + +if(NOT ITK_SOURCE_DIR) + find_package(ITK REQUIRED) + list(APPEND CMAKE_MODULE_PATH ${ITK_CMAKE_DIR}) + include(ITKModuleExternal) +else() + set(ITK_DIR ${CMAKE_BINARY_DIR}) + itk_module_impl() +endif() diff --git a/Modules/Filtering/FastBilateral/include/itkFastBilateralImageFilter.h b/Modules/Filtering/FastBilateral/include/itkFastBilateralImageFilter.h new file mode 100644 index 00000000000..5938596491a --- /dev/null +++ b/Modules/Filtering/FastBilateral/include/itkFastBilateralImageFilter.h @@ -0,0 +1,195 @@ +/*========================================================================= + * + * 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 itkFastBilateralImageFilter_h +#define itkFastBilateralImageFilter_h + +#include "itkImageToImageFilter.h" +#include "itkImage.h" +#include "itkDiscreteGaussianImageFilter.h" +#include "itkImageRegionIterator.h" +#include "itkImageRegionConstIteratorWithIndex.h" +#include "itkLinearInterpolateImageFunction.h" + +namespace itk +{ +/** +* \class FastBilateralImageFilter +* \brief A fast approximation to the bilateral filter +* \ingroup FastBilateral +* +* This filter is a fast approximation to the bilateral filter. +* Blurring is performed on an image based on the distance of pixels in +* both space and intensity. +* +* The algorithm used was originally proposed by Paris and +* Durand [1]. +* +* Instead of calculating a kernel for every pixel in +* an image, this filter places the values of each pixel into a higher +* dimensional image determined by the position and intensity of a pixel. +* How many bins are used is determined by the sigma values provided +* to the filter. Larger sigmas will result in more aggresive downsampling +* and less running time overall. After the data of an image +* has been organized into bins, a DiscreteGaussianImageFilter is applied. +* Finally, the output image is constructed by interpolating the +* values of the output pixels from the blurred higher +* dimensional image. +* +* [1] Sylvain Paris and Frédo Durand, +* A Fast Approximation of the Bilateral Filter using a Signal Processing +* Approach, +* European Conference on Computer Vision (ECCV'06) +* +* \sa BilateralImageFilter +* \sa GaussianOperator +* \sa AnisotropicDiffusionImageFilter +* \sa Image +* \sa Neighborhood +* \sa NeighborhoodOperator +* +* \ingroup ImageEnhancement +* \ingroup ImageFeatureExtraction +* +* \todo Support for color images +* \todo Support for vector images +*/ + +template +class ITK_EXPORT FastBilateralImageFilter : + public ImageToImageFilter< TInputImage, TOutputImage > +{ +public: + ITK_DISALLOW_COPY_AND_MOVE(FastBilateralImageFilter); + + /** Standard class typedefs. */ + using Self = FastBilateralImageFilter; + using Superclass = ImageToImageFilter< TInputImage, TOutputImage >; + using Pointer = SmartPointer; + using ConstPointer = SmartPointer; + + /** Method for creation through the object factory. */ + itkNewMacro(Self); + + /** Run-time type information (and related methods). */ + itkTypeMacro(FastBilateralImageFilter, ImageToImageFilter); + + /** Dimensionality of the input image. Dimensionality of the output image + * is assumed to be the same. */ + static constexpr unsigned int ImageDimension = TInputImage::ImageDimension; + + /** Input image typedefs. */ + using InputImageType = TInputImage; + using InputImagePointer = typename TInputImage::Pointer; + using InputImageConstPointer = typename TInputImage::ConstPointer; + using InputImageSpacingType = typename TInputImage::SpacingType; + using InputImageSizeType = typename TInputImage::SizeType; + using InputImageIndexType = typename TInputImage::IndexType; + + /** Input image iterator type. */ + using InputImageConstIteratorType = ImageRegionConstIteratorWithIndex; + + /** Output image typedefs. */ + using OutputImageType = TOutputImage; + using OutputImagePointer = typename TOutputImage::Pointer; + + /** Output image iterator type. */ + using OutputImageIteratorType = ImageRegionIterator; + + /** Pixel types. */ + using OutputPixelType = typename TOutputImage::PixelType; + using InputPixelType = typename TInputImage::PixelType; + + /** Typedef for an array of doubles that specifies the DomainSigma + * in each spacial dimension. */ + using DomainSigmaArrayType = FixedArray; + + /** Standard get/set macros for filter parameters. + * DomainSigma is specified in the same units as the Image spacing. + * RangeSigma is specified in the units of intensity. */ + itkGetConstMacro(DomainSigma, const DomainSigmaArrayType); + itkSetMacro(DomainSigma, DomainSigmaArrayType); + itkGetConstMacro(RangeSigma, double); + itkSetMacro(RangeSigma, double); + + /** Convenience set method for setting all domain standard deviations to the + * same value. */ + void SetDomainSigma(const double v) + { + m_DomainSigma.Fill(v); + } + +protected: + + /** Default Constructor. Default value for DomainSigma is 4. Default + * value for RangeSigma is 50. These values were chosen match those of the + * BilateralImageFilter */ + FastBilateralImageFilter() + { + m_DomainSigma.Fill(4.0); + m_RangeSigma = 50.0; + } + + virtual ~FastBilateralImageFilter() {} + + /* + * The FastBilateralImageFilter needs a larger input requested + * region than the size of the output requested region. Like + * the BilateralImageFilter, the FastBilateralImageFilter needs + * an amount of padding in each dimension based on the domain sigma. + */ + virtual void GenerateInputRequestedRegion(); + + /** Standard pipline method */ + void GenerateData(); + + /** Method to print member variables to an output stream */ + void PrintSelf(std::ostream& os, Indent indent) const; + + /** The type of image to use as the higher dimensional grid. + * The blurring is performed on this image type. */ + using GridType = typename itk::Image; + + /** Grid types */ + using GridPixelType = typename GridType::PixelType; + using GridIndexType = typename GridType::IndexType; + using GridSizeType = typename GridType::SizeType; + using GridSizeValueType = typename Size::SizeValueType; + using GridRegionType = typename GridType::RegionType; + + /** Grid image iterator type. */ + using GridImageIteratorType = ImageRegionIterator; + using GridImageConstIteratorType = ImageRegionConstIterator; + + /** The type of blurring to use on the grid. */ + using BlurType = DiscreteGaussianImageFilter< GridType, GridType >; + + /** The type of interpolation done to calculate output pixels. */ + using InterpolatorType = LinearInterpolateImageFunction; + using InterpolatedIndexType = typename InterpolatorType::ContinuousIndexType; + + double m_RangeSigma; + DomainSigmaArrayType m_DomainSigma; +}; + +} // namespace itk + +#ifndef ITK_MANUAL_INSTANTIATION +#include "itkFastBilateralImageFilter.hxx" +#endif + +#endif // itkFastBilateralImageFilter diff --git a/Modules/Filtering/FastBilateral/include/itkFastBilateralImageFilter.hxx b/Modules/Filtering/FastBilateral/include/itkFastBilateralImageFilter.hxx new file mode 100644 index 00000000000..bc19414bf4d --- /dev/null +++ b/Modules/Filtering/FastBilateral/include/itkFastBilateralImageFilter.hxx @@ -0,0 +1,337 @@ +/*========================================================================= + * + * 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 itkFastBilateralImageFilter_hxx +#define itkFastBilateralImageFilter_hxx + +#include "itkFastBilateralImageFilter.h" + +#include "itkMinimumMaximumImageCalculator.h" +#include "itkImageDuplicator.h" +#include + +namespace itk +{ + +template +void +FastBilateralImageFilter +::GenerateInputRequestedRegion() +{ + // call the superclass' implementation of this method. this should + // copy the output requested region to the input requested region + Superclass::GenerateInputRequestedRegion(); + + // get pointers to the input and output + typename Superclass::InputImagePointer inputPtr = + const_cast< TInputImage *>( this->GetInput() ); + + if ( !inputPtr ) + { + return; + } + + // Pad the image by 2*sigma (pixel units) + // this is done to ensure that nearby pixels are still + // included in calculations + // When the filter does the downsampling pixels are placed into + // bins based on their position/sigma. Therefore, assuming + // that the input region includes a pixel that would be placed into a new bin + // on its own, that bin and the bin beside it would need to be populated. + // Each bin can contain at most ceil(sigma) pixels + InputImageSizeType radius; + for (size_t i = 0; i < ImageDimension; ++i) + { + radius[i] = + 2*std::ceil(m_DomainSigma[i] / (this->GetInput()->GetSpacing()[i])); + } + + // get a copy of the input requested region (should equal the output + // requested region) + typename TInputImage::RegionType inputRequestedRegion; + inputRequestedRegion = inputPtr->GetRequestedRegion(); + + // pad the input requested region by the operator radius + inputRequestedRegion.PadByRadius( radius ); + + // crop the input requested region at the input's largest possible region + if ( inputRequestedRegion.Crop(inputPtr->GetLargestPossibleRegion()) ) + { + inputPtr->SetRequestedRegion( inputRequestedRegion ); + return; + } + else + { + // Couldn't crop the region (requested region is outside the largest + // possible region). Throw an exception. + + // store what we tried to request (prior to trying to crop) + inputPtr->SetRequestedRegion( inputRequestedRegion ); + + // build an exception + InvalidRequestedRegionError e(__FILE__, __LINE__); + e.SetLocation(ITK_LOCATION); + e.SetDescription + ("Requested region is outside the largest possible region."); + e.SetDataObject(inputPtr); + throw e; + } +} + +template< class TInputImage, class TOutputImage > +void +FastBilateralImageFilter +::GenerateData() +{ + this->AllocateOutputs(); + InputImageConstPointer input = this->GetInput(); + OutputImagePointer output = this->GetOutput(); + + // Array to store domain sigmas, used during down-sampling and reconstruction + DomainSigmaArrayType domainSigmaInPixels; + + // Minimum intensity of the input image, + //used during down-sampling and reconstruction + InputPixelType intensityMin; + + // Define the GridType + // These are pointers to the source and destination of the blurring filter + // Data from the input will be sorted into the first two images while the + // second two images will provide the output data. + // The parameters are determined by the size of the input image and the + // values of m_DomainSigma and m_RangeSigma + typename GridType::Pointer gridImage = GridType::New(); + typename GridType::Pointer gridWeight; + typename GridType::Pointer gridImageOut; + typename GridType::Pointer gridWeightOut; + + // The amount of padding around the grid images, required so that + // interpolation is not done outside of the grid during reconstruction + int padding = 2; + + // Setup the higher dimensional grids (gridImage and gridWeight). + { + GridIndexType gridStartPos; + GridSizeType gridSize; + + // Convert domain sigmas from spacing units to pixel units + // for the blurring in the grid. + // The set method for m_DomainSigma uses spacing units to be + // consistent with the itkBilateralImageFilter implementation. + // When the data is placed into bins in the grid the + // itkDiscreteGaussianImageFilter will be run on the grid using + // imageSpacingOff. + InputImageSizeType inputSize = input->GetRequestedRegion().GetSize(); +// InputImageSizeType fullSize = input->GetLargestPossibleRegion().GetSize(); + + const InputImageSpacingType& spacing = input->GetSpacing(); + for (size_t i = 0; i < ImageDimension; ++i) + { + domainSigmaInPixels[i] = m_DomainSigma[i] / spacing[i]; + gridSize[i] = std::floor( (inputSize[i] - 1) / domainSigmaInPixels[i] ) + + 1 + 2*padding; + } + + // Determine min/max intensities to calculate grid size in the intensity axis + using MinMaxCalculatorType = MinimumMaximumImageCalculator< InputImageType >; + typename MinMaxCalculatorType::Pointer calculator = + MinMaxCalculatorType::New(); + + calculator->SetImage(input); + calculator->Compute(); + intensityMin = calculator->GetMinimum(); + InputPixelType intensityMax = calculator->GetMaximum(); + InputPixelType intensityDelta = + static_cast(intensityMax - intensityMin); + gridSize[ImageDimension] = + static_cast((intensityDelta/m_RangeSigma)+1+2*padding); + + for(size_t i = 0; i < ImageDimension+1; ++i) + { + gridStartPos[i] = 0; + } + + GridRegionType region; + region.SetSize(gridSize); + region.SetIndex(gridStartPos); + gridImage->SetRegions(region); + + } + + // Allocate the memory for pixel data + // We now have an empty grid. Two will be needed total, + // one will be a container for the down-sampled data and one + // will remember how many pixels were placed into each bin + gridImage->Allocate(); + // Init values of image to 0 + gridImage->FillBuffer(0.0); + + // Duplicate our grid image for the weight image + { + using DuplicatorType = ImageDuplicator; + typename DuplicatorType::Pointer duplicator = DuplicatorType::New(); + duplicator->SetInputImage(gridImage); + duplicator->Update(); + gridWeight = duplicator->GetOutput(); + } + + // Sort the input image in gridImage and keep track of weights in gridWeight + { + InputImageConstIteratorType iterInputImage + (input, input->GetRequestedRegion()); + GridIndexType gridIndices; + size_t i; + InputPixelType current; + InputPixelType intensityDelta; + InputImageIndexType index; + + // For every pixel in the input image, place it into a bin in the grid + // This is a scatter type operation and will be inefficient, as far as I + // know, there is no way to place the pixels into the grid using iterators + for ( iterInputImage.GoToBegin(); !iterInputImage.IsAtEnd(); + ++iterInputImage) + { + index = iterInputImage.GetIndex(); + current = iterInputImage.Get(); + // Determine the position in the grid to place the pixel + for ( i = 0; i < ImageDimension; ++i) + { + gridIndices[i] = static_cast + (index[i]/domainSigmaInPixels[i]+0.5+padding); + } + intensityDelta = current - intensityMin; + gridIndices[ImageDimension] = + static_cast(intensityDelta/m_RangeSigma+0.5+padding); + + // Update the bin and the weight + (gridImage->GetPixel(gridIndices)) += current; + (gridWeight->GetPixel(gridIndices)) += 1.0; + } + } + + // Perform blurring on gridImage and gridWeight + // outputs are pointed to by gridImageOut and gridWeightOut + { + + // This variance approximately corresponds to a 1D filter of [1 2 1] which is + // used in Paris and Durands C++ implementation to blur their down-sampled + // data. With this variance a kernel width larger than 5 is not necessary. + double variance = 1.59577; + int maxWidth = 5; + + // Setup the Gaussian filter + typename BlurType::Pointer gridImageBlurFilter = BlurType::New(); + typename BlurType::Pointer gridWeightBlurFilter = BlurType::New(); + + gridImageBlurFilter ->SetVariance(variance); + gridWeightBlurFilter->SetVariance(variance); + + gridImageBlurFilter ->SetUseImageSpacingOff(); + gridWeightBlurFilter->SetUseImageSpacingOff(); + + gridImageBlurFilter ->SetMaximumKernelWidth(maxWidth); + gridWeightBlurFilter->SetMaximumKernelWidth(maxWidth); + + gridImageBlurFilter ->SetInput(gridImage); + gridWeightBlurFilter->SetInput(gridWeight); + + gridImageOut = gridImageBlurFilter ->GetOutput(); + gridWeightOut = gridWeightBlurFilter->GetOutput(); + + gridImageBlurFilter ->Update(); + gridWeightBlurFilter->Update(); + } + + // Early division; in Paris and Durand's implementation early division can + // be done on the grid image, or interpolation on both the bin and the + // weights can be done then the division. Interpolation is an expensive + // operation so I've opted for the early division approach. + { + GridImageIteratorType iterGridImage + (gridImageOut, gridImageOut->GetLargestPossibleRegion()); + GridImageConstIteratorType iterGridWeight + (gridWeightOut, gridWeightOut->GetLargestPossibleRegion()); + + GridPixelType weight; + + for ( iterGridImage.GoToBegin(), iterGridWeight.GoToBegin(); + !iterGridImage.IsAtEnd(); ++iterGridImage, ++iterGridWeight) + { + if ( (weight = iterGridWeight.Get() ) != 0.0 ) + { + iterGridImage.Value() /= weight; + } + } + } + + // Perform interpolation in order to construct the output. + // For every pixel in the input image, determine where in the grid the pixel + // was placed and interpolate for the output pixel's value. + { + + OutputImageIteratorType iterOutputImage + (output, output->GetRequestedRegion()); + InputImageConstIteratorType iterInputImage + (input, output->GetRequestedRegion()); + + InterpolatedIndexType gridIndices; + size_t i; + InputPixelType current; + InputPixelType intensityDelta; + InputImageIndexType index; + typename InterpolatorType::Pointer interpolator = InterpolatorType::New(); + interpolator->SetInputImage(gridImageOut); + + for ( iterOutputImage.GoToBegin(), iterInputImage.GoToBegin(); + !iterOutputImage.IsAtEnd(); ++iterOutputImage, ++iterInputImage) + { + index = iterInputImage.GetIndex(); + current = iterInputImage.Get(); + // Determine the position in the grid to get the data from + for ( i = 0; i < ImageDimension; ++i) + { + gridIndices[i] = index[i] / domainSigmaInPixels[i] + padding; + } + + intensityDelta = current - intensityMin; + + gridIndices[ImageDimension] = + intensityDelta / m_RangeSigma + padding; + + iterOutputImage.Set( static_cast + (interpolator->EvaluateAtContinuousIndex(gridIndices)) + ); + + } + } +} + +template< class TInputImage, class TOutputImage > +void +FastBilateralImageFilter +::PrintSelf(std::ostream& os, Indent indent) const +{ + Superclass::PrintSelf(os,indent); + + os << indent << "DomainSigma: " << m_DomainSigma << std::endl; + os << indent << "RangeSigma: " << m_RangeSigma << std::endl; + +} + +} // namespace itk + +#endif diff --git a/Modules/Filtering/FastBilateral/itk-module.cmake b/Modules/Filtering/FastBilateral/itk-module.cmake new file mode 100644 index 00000000000..4250eb6e4d4 --- /dev/null +++ b/Modules/Filtering/FastBilateral/itk-module.cmake @@ -0,0 +1,27 @@ +# the top-level README is used for describing this module, just +# re-used it for documentation here +get_filename_component(MY_CURRENT_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH) +file(READ "${MY_CURRENT_DIR}/README.rst" DOCUMENTATION) + +# itk_module() defines the module dependencies in FastBilateral +# FastBilateral depends on ITKCommon +# The testing module in FastBilateral depends on ITKTestKernel +# and ITKMetaIO(besides FastBilateral and ITKCore) +# By convention those modules outside of ITK are not prefixed with +# ITK. + +# define the dependencies of the include module and the tests +itk_module(FastBilateral + DEPENDS + ITKCommon + ITKSmoothing + COMPILE_DEPENDS + ITKImageSources + TEST_DEPENDS + ITKTestKernel + ITKMetaIO + DESCRIPTION + "${DOCUMENTATION}" + EXCLUDE_FROM_DEFAULT + ENABLE_SHARED +) diff --git a/Modules/Filtering/FastBilateral/test/Baseline/itkFastBilateralImageFilterTestOutput.mha.sha512 b/Modules/Filtering/FastBilateral/test/Baseline/itkFastBilateralImageFilterTestOutput.mha.sha512 new file mode 100644 index 00000000000..c811785f3e7 --- /dev/null +++ b/Modules/Filtering/FastBilateral/test/Baseline/itkFastBilateralImageFilterTestOutput.mha.sha512 @@ -0,0 +1 @@ +34cdd2aafce413dcf7efc692a707d53b7b57ebb006d0fbc20ecb42343f8a078b2252eff2137b17d3ab583d133f780438e247241ebf213c3289bd9ba1525081b7 diff --git a/Modules/Filtering/FastBilateral/test/CMakeLists.txt b/Modules/Filtering/FastBilateral/test/CMakeLists.txt new file mode 100644 index 00000000000..414681bf366 --- /dev/null +++ b/Modules/Filtering/FastBilateral/test/CMakeLists.txt @@ -0,0 +1,16 @@ +itk_module_test() + +set(FastBilateralTests + itkFastBilateralImageFilterTest.cxx + ) + +CreateTestDriver(FastBilateral "${FastBilateral-Test_LIBRARIES}" "${FastBilateralTests}") + +itk_add_test(NAME itkFastBilateralImageFilterTest + COMMAND FastBilateralTestDriver + --compare + DATA{Baseline/itkFastBilateralImageFilterTestOutput.mha} + ${ITK_TEST_OUTPUT_DIR}/itkFastBilateralImageFilterTestOutput.mha + itkFastBilateralImageFilterTest + ${ITK_TEST_OUTPUT_DIR}/itkFastBilateralImageFilterTestOutput.mha + ) diff --git a/Modules/Filtering/FastBilateral/test/itkFastBilateralImageFilterTest.cxx b/Modules/Filtering/FastBilateral/test/itkFastBilateralImageFilterTest.cxx new file mode 100644 index 00000000000..b894a31cdd2 --- /dev/null +++ b/Modules/Filtering/FastBilateral/test/itkFastBilateralImageFilterTest.cxx @@ -0,0 +1,100 @@ +/*========================================================================= + * + * 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. + * + *=========================================================================*/ + +#include "itkFastBilateralImageFilter.h" + +#include "itkCommand.h" +#include "itkImageFileWriter.h" +#include "itkTestingMacros.h" + +namespace +{ +class ShowProgress : public itk::Command +{ +public: + itkNewMacro(ShowProgress); + + void + Execute(itk::Object * caller, const itk::EventObject & event) override + { + Execute((const itk::Object *)caller, event); + } + + void + Execute(const itk::Object * caller, const itk::EventObject & event) override + { + if (!itk::ProgressEvent().CheckEvent(&event)) + { + return; + } + const auto * processObject = dynamic_cast(caller); + if (!processObject) + { + return; + } + std::cout << " " << processObject->GetProgress(); + } +}; +} // namespace + +int +itkFastBilateralImageFilterTest(int argc, char * argv[]) +{ + if (argc < 2) + { + std::cerr << "Missing parameters." << std::endl; + std::cerr << "Usage: " << itkNameOfTestExecutableMacro(argv); + std::cerr << " outputImage"; + std::cerr << std::endl; + return EXIT_FAILURE; + } + const char * outputImageFileName = argv[1]; + + constexpr unsigned int Dimension = 2; + using PixelType = float; + using ImageType = itk::Image; + + using FilterType = itk::FastBilateralImageFilter; + FilterType::Pointer filter = FilterType::New(); + + ITK_EXERCISE_BASIC_OBJECT_METHODS(filter, FastBilateralImageFilter, ImageToImageFilter); + + // Create input image to avoid test dependencies. + ImageType::SizeType size; + size.Fill(128); + ImageType::Pointer image = ImageType::New(); + image->SetRegions(size); + image->Allocate(); + image->FillBuffer(1.1f); + + ShowProgress::Pointer showProgress = ShowProgress::New(); + filter->AddObserver(itk::ProgressEvent(), showProgress); + filter->SetInput(image); + + using WriterType = itk::ImageFileWriter; + WriterType::Pointer writer = WriterType::New(); + writer->SetFileName(outputImageFileName); + writer->SetInput(filter->GetOutput()); + writer->SetUseCompression(true); + + ITK_TRY_EXPECT_NO_EXCEPTION(writer->Update()); + + + std::cout << "Test finished." << std::endl; + return EXIT_SUCCESS; +} diff --git a/Modules/Filtering/FastBilateral/wrapping/CMakeLists.txt b/Modules/Filtering/FastBilateral/wrapping/CMakeLists.txt new file mode 100644 index 00000000000..70f80e40bd2 --- /dev/null +++ b/Modules/Filtering/FastBilateral/wrapping/CMakeLists.txt @@ -0,0 +1,3 @@ +itk_wrap_module(FastBilateral) +itk_auto_load_submodules() +itk_end_wrap_module() diff --git a/Modules/Filtering/FastBilateral/wrapping/itkFastBilateralImageFilter.wrap b/Modules/Filtering/FastBilateral/wrapping/itkFastBilateralImageFilter.wrap new file mode 100644 index 00000000000..1e025ddc796 --- /dev/null +++ b/Modules/Filtering/FastBilateral/wrapping/itkFastBilateralImageFilter.wrap @@ -0,0 +1,4 @@ +itk_wrap_class("itk::FastBilateralImageFilter" POINTER) + itk_wrap_image_filter("${WRAP_ITK_SCALAR}" 2) +itk_end_wrap_class() + From 42d8980abc66aa8744e234e8c0f30be27f458633 Mon Sep 17 00:00:00 2001 From: Pablo Hernandez-Cerdan Date: Thu, 9 Dec 2021 20:57:19 +0100 Subject: [PATCH 02/18] Add all the tests from the Insight Journal This includes uploading test data to my public folder in girder. https://data.kitware.com/#folder/5afde4038d777f15ebe1d6cb All tests passing --- ...BilateralImageFilterTest2Output.png.sha512 | 1 + ...BilateralImageFilterTest3Output.png.sha512 | 1 + .../FastBilateral/test/CMakeLists.txt | 22 +++++ .../FastBilateral/test/Input/cake_easy.png | Bin 0 -> 8363 bytes .../test/Input/cake_easy.png.sha512 | 1 + .../test/itkFastBilateralImageFilterTest2.cxx | 92 ++++++++++++++++++ .../test/itkFastBilateralImageFilterTest3.cxx | 91 +++++++++++++++++ 7 files changed, 208 insertions(+) create mode 100644 Modules/Filtering/FastBilateral/test/Baseline/itkFastBilateralImageFilterTest2Output.png.sha512 create mode 100644 Modules/Filtering/FastBilateral/test/Baseline/itkFastBilateralImageFilterTest3Output.png.sha512 create mode 100644 Modules/Filtering/FastBilateral/test/Input/cake_easy.png create mode 100644 Modules/Filtering/FastBilateral/test/Input/cake_easy.png.sha512 create mode 100644 Modules/Filtering/FastBilateral/test/itkFastBilateralImageFilterTest2.cxx create mode 100644 Modules/Filtering/FastBilateral/test/itkFastBilateralImageFilterTest3.cxx diff --git a/Modules/Filtering/FastBilateral/test/Baseline/itkFastBilateralImageFilterTest2Output.png.sha512 b/Modules/Filtering/FastBilateral/test/Baseline/itkFastBilateralImageFilterTest2Output.png.sha512 new file mode 100644 index 00000000000..54d7b3f915e --- /dev/null +++ b/Modules/Filtering/FastBilateral/test/Baseline/itkFastBilateralImageFilterTest2Output.png.sha512 @@ -0,0 +1 @@ +a672baa7da752bbc1644e63361b347008398db86f03ed03baa9822beccece5116489dc0ef4c5c059f31838cab282466cf1dd6ae5b9466724ff9d8854a676d33a diff --git a/Modules/Filtering/FastBilateral/test/Baseline/itkFastBilateralImageFilterTest3Output.png.sha512 b/Modules/Filtering/FastBilateral/test/Baseline/itkFastBilateralImageFilterTest3Output.png.sha512 new file mode 100644 index 00000000000..2a0e19fabf5 --- /dev/null +++ b/Modules/Filtering/FastBilateral/test/Baseline/itkFastBilateralImageFilterTest3Output.png.sha512 @@ -0,0 +1 @@ +eeaaa0902595818d403fa110221f59fa91b2844baf06332c1633227743fa201f3022fa2e0ad0580f186ae50ae32d973fcae6a876d8286181ba778e61dabfd771 diff --git a/Modules/Filtering/FastBilateral/test/CMakeLists.txt b/Modules/Filtering/FastBilateral/test/CMakeLists.txt index 414681bf366..f3043caa859 100644 --- a/Modules/Filtering/FastBilateral/test/CMakeLists.txt +++ b/Modules/Filtering/FastBilateral/test/CMakeLists.txt @@ -2,6 +2,8 @@ itk_module_test() set(FastBilateralTests itkFastBilateralImageFilterTest.cxx + itkFastBilateralImageFilterTest2.cxx + itkFastBilateralImageFilterTest3.cxx ) CreateTestDriver(FastBilateral "${FastBilateral-Test_LIBRARIES}" "${FastBilateralTests}") @@ -14,3 +16,23 @@ itk_add_test(NAME itkFastBilateralImageFilterTest itkFastBilateralImageFilterTest ${ITK_TEST_OUTPUT_DIR}/itkFastBilateralImageFilterTestOutput.mha ) + +itk_add_test(NAME itkFastBilateralImageFilterTest2 + COMMAND FastBilateralTestDriver + --compare + DATA{Baseline/itkFastBilateralImageFilterTest2Output.png} + ${ITK_TEST_OUTPUT_DIR}/itkFastBilateralImageFilterTest2Output.png + itkFastBilateralImageFilterTest2 + DATA{Input/cake_easy.png} + ${ITK_TEST_OUTPUT_DIR}/itkFastBilateralImageFilterTest2Output.png + ) + +itk_add_test(NAME itkFastBilateralImageFilterTest3 + COMMAND FastBilateralTestDriver + --compare + DATA{Baseline/itkFastBilateralImageFilterTest3Output.png} + ${ITK_TEST_OUTPUT_DIR}/itkFastBilateralImageFilterTest3Output.png + itkFastBilateralImageFilterTest3 + DATA{Input/cake_easy.png} + ${ITK_TEST_OUTPUT_DIR}/itkFastBilateralImageFilterTest3Output.png + ) diff --git a/Modules/Filtering/FastBilateral/test/Input/cake_easy.png b/Modules/Filtering/FastBilateral/test/Input/cake_easy.png new file mode 100644 index 0000000000000000000000000000000000000000..530a14c12c02cef3864870901d3f9a509323c461 GIT binary patch literal 8363 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 BW|aT{ literal 0 HcmV?d00001 diff --git a/Modules/Filtering/FastBilateral/test/Input/cake_easy.png.sha512 b/Modules/Filtering/FastBilateral/test/Input/cake_easy.png.sha512 new file mode 100644 index 00000000000..2074b776757 --- /dev/null +++ b/Modules/Filtering/FastBilateral/test/Input/cake_easy.png.sha512 @@ -0,0 +1 @@ +0aad3941e82b5cb077b791606abdb186c4284956f03b58a629f2434a98b5e4bf8efcc32a7aa66791b16c57cf4da5cb83d9801e2d7db3d0e58e1ada401ddbc20c diff --git a/Modules/Filtering/FastBilateral/test/itkFastBilateralImageFilterTest2.cxx b/Modules/Filtering/FastBilateral/test/itkFastBilateralImageFilterTest2.cxx new file mode 100644 index 00000000000..94f97d62aab --- /dev/null +++ b/Modules/Filtering/FastBilateral/test/itkFastBilateralImageFilterTest2.cxx @@ -0,0 +1,92 @@ +/*========================================================================= + * + * 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. + * + *=========================================================================*/ +#include +#include "itkFastBilateralImageFilter.h" +#include "itkImageFileReader.h" +#include "itkImageFileWriter.h" +#include "itkImageRegionIterator.h" +#include "itkTestingMacros.h" + +/** + * This test was originally taken from the tests for the itkBilateralImageFilter + * and modified for the itkFastBilateralImageFilter. + */ +int itkFastBilateralImageFilterTest2(int ac, char* av[] ) +{ + if(ac < 3) + { + std::cerr << "Usage: " << av[0] << " InputImage OutputImage\n"; + return EXIT_FAILURE; + } + + using PixelType = unsigned char; + const unsigned int dimension = 2; + using ImageType = itk::Image; + auto input = itk::ImageFileReader::New(); + input->SetFileName(av[1]); + + // Create a filter + using FilterType = itk::FastBilateralImageFilter; + + auto filter = FilterType::New(); + + filter->SetInput(input->GetOutput()); + + // these settings reduce the amount of noise by a factor of 10 + // when the original signal to noise level is 5 + filter->SetDomainSigma( 4.0 ); + filter->SetRangeSigma( 50.0 ); + + + // Test itkSetVectorMacro + double domainSigma[dimension]; + for (unsigned int i = 0; i < dimension; i++) + { + domainSigma[i] = 4.0; + } + filter->SetDomainSigma(domainSigma); + + // Test itkGetMacro + std::cout << "filter->GetDomainSigma(): " << filter->GetDomainSigma() << std::endl; + std::cout << "filter->GetRangeSigma(): " << filter->GetRangeSigma() << std::endl; + + try + { + input->Update(); + filter->Update(); + } + catch (itk::ExceptionObject& e) + { + std::cerr << "Exception detected: " << e.GetDescription(); + return -1; + } + catch (...) + { + std::cerr << "Some other exception occurred" << std::endl; + return -2; + } + + // Generate test image + itk::ImageFileWriter::Pointer writer; + writer = itk::ImageFileWriter::New(); + writer->SetInput( filter->GetOutput() ); + writer->SetFileName( av[2] ); + writer->Update(); + + return EXIT_SUCCESS; +} diff --git a/Modules/Filtering/FastBilateral/test/itkFastBilateralImageFilterTest3.cxx b/Modules/Filtering/FastBilateral/test/itkFastBilateralImageFilterTest3.cxx new file mode 100644 index 00000000000..240ccedc2a8 --- /dev/null +++ b/Modules/Filtering/FastBilateral/test/itkFastBilateralImageFilterTest3.cxx @@ -0,0 +1,91 @@ +/*========================================================================= + * + * 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. + * + *=========================================================================*/ + +#include +#include "itkFastBilateralImageFilter.h" +#include "itkImageFileReader.h" +#include "itkImageFileWriter.h" +#include "itkImageRegionIterator.h" +#include "itkTestingMacros.h" + + +/** + * This test was originally taken from the tests for the itkBilateralImageFilter + * and modified for the itkFastBilateralImageFilter. + */ +int itkFastBilateralImageFilterTest3(int ac, char* av[] ) +{ + if(ac < 3) + { + std::cerr << "Usage: " << av[0] << " InputImage BaselineImage\n"; + return -1; + } + + using PixelType = unsigned char; + using ImageType = itk::Image; + auto input = itk::ImageFileReader::New(); + input->SetFileName(av[1]); + + // Create a filter + using FilterType = itk::FastBilateralImageFilter; + + FilterType::Pointer filter1 = FilterType::New(); + filter1->SetInput(input->GetOutput()); + FilterType::Pointer filter2 = FilterType::New(); + filter2->SetInput(filter1->GetOutput()); + FilterType::Pointer filter3 = FilterType::New(); + filter3->SetInput(filter2->GetOutput()); + + // Instead of using a single agressive smoothing filter, use 3 + // less aggressive filters. + // + // These settings match the "wedding" cake image (cake_easy.png) where + // the signal to noise ratio is 5 (step heights near 100 units, + // noise sigma near 20 units). A single filter stage with these + // settings cuts the noise level in half. These three stages should + // reduce the amount of noise by a factor of 8. This is comparable to + // the noise reduction in using a single stage with parameters + // (4.0, 50.0). The difference is that with 3 less aggressive stages + // the edges are preserved better. + filter1->SetDomainSigma( 4.0 ); + filter1->SetRangeSigma( 20.0 ); + filter2->SetDomainSigma( 4.0 ); + filter2->SetRangeSigma( 20.0 ); + filter3->SetDomainSigma( 4.0 ); + filter3->SetRangeSigma( 20.0 ); + + try + { + input->Update(); + filter3->Update(); + } + catch (itk::ExceptionObject& e) + { + std::cerr << "Exception detected: " << e.GetDescription(); + return -1; + } + + // Generate test image + itk::ImageFileWriter::Pointer writer; + writer = itk::ImageFileWriter::New(); + writer->SetInput( filter3->GetOutput() ); + writer->SetFileName( av[2] ); + writer->Update(); + + return EXIT_SUCCESS; +} From a66f09233867782c49a63fb4d77cc3de495497dd Mon Sep 17 00:00:00 2001 From: Pablo Hernandez-Cerdan Date: Fri, 10 Dec 2021 00:03:23 +0100 Subject: [PATCH 03/18] ENH: Test creating a filter instance from python --- Modules/Filtering/FastBilateral/wrapping/test/CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 Modules/Filtering/FastBilateral/wrapping/test/CMakeLists.txt diff --git a/Modules/Filtering/FastBilateral/wrapping/test/CMakeLists.txt b/Modules/Filtering/FastBilateral/wrapping/test/CMakeLists.txt new file mode 100644 index 00000000000..31cb0555519 --- /dev/null +++ b/Modules/Filtering/FastBilateral/wrapping/test/CMakeLists.txt @@ -0,0 +1,2 @@ +itk_python_expression_add_test(NAME itkFastBilateralImageFilterPythonTest + EXPRESSION "instance = itk.FastBilateralImageFilter.New()") From bcadf7a6173cddae26d37e7904b2f8657989b92d Mon Sep 17 00:00:00 2001 From: Pablo Hernandez-Cerdan Date: Sat, 18 Dec 2021 12:54:43 +0100 Subject: [PATCH 04/18] COMP: Remove inclusion of .hxx files as headers For consistency with other external modules. See for example: https://github.com/InsightSoftwareConsortium/ITKTotalVariation/commit/8eb16733dd4383dcff99c85af65a420f7327be15 --- .../FastBilateral/include/itkFastBilateralImageFilter.hxx | 2 -- 1 file changed, 2 deletions(-) diff --git a/Modules/Filtering/FastBilateral/include/itkFastBilateralImageFilter.hxx b/Modules/Filtering/FastBilateral/include/itkFastBilateralImageFilter.hxx index bc19414bf4d..54db96e6c96 100644 --- a/Modules/Filtering/FastBilateral/include/itkFastBilateralImageFilter.hxx +++ b/Modules/Filtering/FastBilateral/include/itkFastBilateralImageFilter.hxx @@ -18,8 +18,6 @@ #ifndef itkFastBilateralImageFilter_hxx #define itkFastBilateralImageFilter_hxx -#include "itkFastBilateralImageFilter.h" - #include "itkMinimumMaximumImageCalculator.h" #include "itkImageDuplicator.h" #include From f17286c87b981e8361294d33039ed118115b8dbe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C5=BEenan=20Zuki=C4=87?= Date: Tue, 19 Mar 2024 09:16:41 -0400 Subject: [PATCH 05/18] STYLE: Pass style tests --- .../FastBilateral/include/itkFastBilateralImageFilter.h | 2 +- .../FastBilateral/include/itkFastBilateralImageFilter.hxx | 2 +- .../FastBilateral/test/itkFastBilateralImageFilterTest.cxx | 2 +- .../FastBilateral/test/itkFastBilateralImageFilterTest2.cxx | 2 +- .../FastBilateral/test/itkFastBilateralImageFilterTest3.cxx | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Modules/Filtering/FastBilateral/include/itkFastBilateralImageFilter.h b/Modules/Filtering/FastBilateral/include/itkFastBilateralImageFilter.h index 5938596491a..1d6688cdbb7 100644 --- a/Modules/Filtering/FastBilateral/include/itkFastBilateralImageFilter.h +++ b/Modules/Filtering/FastBilateral/include/itkFastBilateralImageFilter.h @@ -6,7 +6,7 @@ * 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 + * https://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, diff --git a/Modules/Filtering/FastBilateral/include/itkFastBilateralImageFilter.hxx b/Modules/Filtering/FastBilateral/include/itkFastBilateralImageFilter.hxx index 54db96e6c96..e41bc979f3c 100644 --- a/Modules/Filtering/FastBilateral/include/itkFastBilateralImageFilter.hxx +++ b/Modules/Filtering/FastBilateral/include/itkFastBilateralImageFilter.hxx @@ -6,7 +6,7 @@ * 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 + * https://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, diff --git a/Modules/Filtering/FastBilateral/test/itkFastBilateralImageFilterTest.cxx b/Modules/Filtering/FastBilateral/test/itkFastBilateralImageFilterTest.cxx index b894a31cdd2..7303fe61670 100644 --- a/Modules/Filtering/FastBilateral/test/itkFastBilateralImageFilterTest.cxx +++ b/Modules/Filtering/FastBilateral/test/itkFastBilateralImageFilterTest.cxx @@ -6,7 +6,7 @@ * 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 + * https://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, diff --git a/Modules/Filtering/FastBilateral/test/itkFastBilateralImageFilterTest2.cxx b/Modules/Filtering/FastBilateral/test/itkFastBilateralImageFilterTest2.cxx index 94f97d62aab..6150d54dcb5 100644 --- a/Modules/Filtering/FastBilateral/test/itkFastBilateralImageFilterTest2.cxx +++ b/Modules/Filtering/FastBilateral/test/itkFastBilateralImageFilterTest2.cxx @@ -6,7 +6,7 @@ * 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 + * https://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, diff --git a/Modules/Filtering/FastBilateral/test/itkFastBilateralImageFilterTest3.cxx b/Modules/Filtering/FastBilateral/test/itkFastBilateralImageFilterTest3.cxx index 240ccedc2a8..e4766fc9b62 100644 --- a/Modules/Filtering/FastBilateral/test/itkFastBilateralImageFilterTest3.cxx +++ b/Modules/Filtering/FastBilateral/test/itkFastBilateralImageFilterTest3.cxx @@ -6,7 +6,7 @@ * 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 + * https://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, From dfc2a9a4a99dcb8f57c35d3e12c93c7de7b39c1d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C5=BEenan=20Zuki=C4=87?= Date: Tue, 19 Mar 2024 09:56:31 -0400 Subject: [PATCH 06/18] STYLE: Apply clang-format --- .../include/itkFastBilateralImageFilter.h | 122 ++++---- .../include/itkFastBilateralImageFilter.hxx | 292 ++++++++---------- .../test/itkFastBilateralImageFilterTest2.cxx | 45 +-- .../test/itkFastBilateralImageFilterTest3.cxx | 67 ++-- 4 files changed, 253 insertions(+), 273 deletions(-) diff --git a/Modules/Filtering/FastBilateral/include/itkFastBilateralImageFilter.h b/Modules/Filtering/FastBilateral/include/itkFastBilateralImageFilter.h index 1d6688cdbb7..1f70fe8fefb 100644 --- a/Modules/Filtering/FastBilateral/include/itkFastBilateralImageFilter.h +++ b/Modules/Filtering/FastBilateral/include/itkFastBilateralImageFilter.h @@ -28,57 +28,56 @@ namespace itk { /** -* \class FastBilateralImageFilter -* \brief A fast approximation to the bilateral filter -* \ingroup FastBilateral -* -* This filter is a fast approximation to the bilateral filter. -* Blurring is performed on an image based on the distance of pixels in -* both space and intensity. -* -* The algorithm used was originally proposed by Paris and -* Durand [1]. -* -* Instead of calculating a kernel for every pixel in -* an image, this filter places the values of each pixel into a higher -* dimensional image determined by the position and intensity of a pixel. -* How many bins are used is determined by the sigma values provided -* to the filter. Larger sigmas will result in more aggresive downsampling -* and less running time overall. After the data of an image -* has been organized into bins, a DiscreteGaussianImageFilter is applied. -* Finally, the output image is constructed by interpolating the -* values of the output pixels from the blurred higher -* dimensional image. -* -* [1] Sylvain Paris and Frédo Durand, -* A Fast Approximation of the Bilateral Filter using a Signal Processing -* Approach, -* European Conference on Computer Vision (ECCV'06) -* -* \sa BilateralImageFilter -* \sa GaussianOperator -* \sa AnisotropicDiffusionImageFilter -* \sa Image -* \sa Neighborhood -* \sa NeighborhoodOperator -* -* \ingroup ImageEnhancement -* \ingroup ImageFeatureExtraction -* -* \todo Support for color images -* \todo Support for vector images -*/ - -template -class ITK_EXPORT FastBilateralImageFilter : - public ImageToImageFilter< TInputImage, TOutputImage > + * \class FastBilateralImageFilter + * \brief A fast approximation to the bilateral filter + * \ingroup FastBilateral + * + * This filter is a fast approximation to the bilateral filter. + * Blurring is performed on an image based on the distance of pixels in + * both space and intensity. + * + * The algorithm used was originally proposed by Paris and + * Durand [1]. + * + * Instead of calculating a kernel for every pixel in + * an image, this filter places the values of each pixel into a higher + * dimensional image determined by the position and intensity of a pixel. + * How many bins are used is determined by the sigma values provided + * to the filter. Larger sigmas will result in more aggresive downsampling + * and less running time overall. After the data of an image + * has been organized into bins, a DiscreteGaussianImageFilter is applied. + * Finally, the output image is constructed by interpolating the + * values of the output pixels from the blurred higher + * dimensional image. + * + * [1] Sylvain Paris and Frédo Durand, + * A Fast Approximation of the Bilateral Filter using a Signal Processing + * Approach, + * European Conference on Computer Vision (ECCV'06) + * + * \sa BilateralImageFilter + * \sa GaussianOperator + * \sa AnisotropicDiffusionImageFilter + * \sa Image + * \sa Neighborhood + * \sa NeighborhoodOperator + * + * \ingroup ImageEnhancement + * \ingroup ImageFeatureExtraction + * + * \todo Support for color images + * \todo Support for vector images + */ + +template +class ITK_EXPORT FastBilateralImageFilter : public ImageToImageFilter { public: ITK_DISALLOW_COPY_AND_MOVE(FastBilateralImageFilter); /** Standard class typedefs. */ using Self = FastBilateralImageFilter; - using Superclass = ImageToImageFilter< TInputImage, TOutputImage >; + using Superclass = ImageToImageFilter; using Pointer = SmartPointer; using ConstPointer = SmartPointer; @@ -128,21 +127,21 @@ class ITK_EXPORT FastBilateralImageFilter : /** Convenience set method for setting all domain standard deviations to the * same value. */ - void SetDomainSigma(const double v) - { + void + SetDomainSigma(const double v) + { m_DomainSigma.Fill(v); - } + } protected: - /** Default Constructor. Default value for DomainSigma is 4. Default * value for RangeSigma is 50. These values were chosen match those of the * BilateralImageFilter */ FastBilateralImageFilter() - { + { m_DomainSigma.Fill(4.0); m_RangeSigma = 50.0; - } + } virtual ~FastBilateralImageFilter() {} @@ -152,23 +151,26 @@ class ITK_EXPORT FastBilateralImageFilter : * the BilateralImageFilter, the FastBilateralImageFilter needs * an amount of padding in each dimension based on the domain sigma. */ - virtual void GenerateInputRequestedRegion(); + virtual void + GenerateInputRequestedRegion(); /** Standard pipline method */ - void GenerateData(); + void + GenerateData(); /** Method to print member variables to an output stream */ - void PrintSelf(std::ostream& os, Indent indent) const; + void + PrintSelf(std::ostream & os, Indent indent) const; /** The type of image to use as the higher dimensional grid. * The blurring is performed on this image type. */ - using GridType = typename itk::Image; + using GridType = typename itk::Image; /** Grid types */ using GridPixelType = typename GridType::PixelType; using GridIndexType = typename GridType::IndexType; using GridSizeType = typename GridType::SizeType; - using GridSizeValueType = typename Size::SizeValueType; + using GridSizeValueType = typename Size::SizeValueType; using GridRegionType = typename GridType::RegionType; /** Grid image iterator type. */ @@ -176,20 +178,20 @@ class ITK_EXPORT FastBilateralImageFilter : using GridImageConstIteratorType = ImageRegionConstIterator; /** The type of blurring to use on the grid. */ - using BlurType = DiscreteGaussianImageFilter< GridType, GridType >; + using BlurType = DiscreteGaussianImageFilter; /** The type of interpolation done to calculate output pixels. */ using InterpolatorType = LinearInterpolateImageFunction; using InterpolatedIndexType = typename InterpolatorType::ContinuousIndexType; - double m_RangeSigma; - DomainSigmaArrayType m_DomainSigma; + double m_RangeSigma; + DomainSigmaArrayType m_DomainSigma; }; } // namespace itk #ifndef ITK_MANUAL_INSTANTIATION -#include "itkFastBilateralImageFilter.hxx" +# include "itkFastBilateralImageFilter.hxx" #endif #endif // itkFastBilateralImageFilter diff --git a/Modules/Filtering/FastBilateral/include/itkFastBilateralImageFilter.hxx b/Modules/Filtering/FastBilateral/include/itkFastBilateralImageFilter.hxx index e41bc979f3c..bc2778a2d3e 100644 --- a/Modules/Filtering/FastBilateral/include/itkFastBilateralImageFilter.hxx +++ b/Modules/Filtering/FastBilateral/include/itkFastBilateralImageFilter.hxx @@ -27,21 +27,19 @@ namespace itk template void -FastBilateralImageFilter -::GenerateInputRequestedRegion() +FastBilateralImageFilter::GenerateInputRequestedRegion() { // call the superclass' implementation of this method. this should // copy the output requested region to the input requested region Superclass::GenerateInputRequestedRegion(); // get pointers to the input and output - typename Superclass::InputImagePointer inputPtr = - const_cast< TInputImage *>( this->GetInput() ); + typename Superclass::InputImagePointer inputPtr = const_cast(this->GetInput()); - if ( !inputPtr ) - { + if (!inputPtr) + { return; - } + } // Pad the image by 2*sigma (pixel units) // this is done to ensure that nearby pixels are still @@ -53,10 +51,9 @@ FastBilateralImageFilter // Each bin can contain at most ceil(sigma) pixels InputImageSizeType radius; for (size_t i = 0; i < ImageDimension; ++i) - { - radius[i] = - 2*std::ceil(m_DomainSigma[i] / (this->GetInput()->GetSpacing()[i])); - } + { + radius[i] = 2 * std::ceil(m_DomainSigma[i] / (this->GetInput()->GetSpacing()[i])); + } // get a copy of the input requested region (should equal the output // requested region) @@ -64,47 +61,45 @@ FastBilateralImageFilter inputRequestedRegion = inputPtr->GetRequestedRegion(); // pad the input requested region by the operator radius - inputRequestedRegion.PadByRadius( radius ); + inputRequestedRegion.PadByRadius(radius); // crop the input requested region at the input's largest possible region - if ( inputRequestedRegion.Crop(inputPtr->GetLargestPossibleRegion()) ) - { - inputPtr->SetRequestedRegion( inputRequestedRegion ); + if (inputRequestedRegion.Crop(inputPtr->GetLargestPossibleRegion())) + { + inputPtr->SetRequestedRegion(inputRequestedRegion); return; - } + } else - { + { // Couldn't crop the region (requested region is outside the largest // possible region). Throw an exception. // store what we tried to request (prior to trying to crop) - inputPtr->SetRequestedRegion( inputRequestedRegion ); + inputPtr->SetRequestedRegion(inputRequestedRegion); // build an exception InvalidRequestedRegionError e(__FILE__, __LINE__); e.SetLocation(ITK_LOCATION); - e.SetDescription - ("Requested region is outside the largest possible region."); + e.SetDescription("Requested region is outside the largest possible region."); e.SetDataObject(inputPtr); throw e; - } + } } -template< class TInputImage, class TOutputImage > +template void -FastBilateralImageFilter -::GenerateData() +FastBilateralImageFilter::GenerateData() { this->AllocateOutputs(); InputImageConstPointer input = this->GetInput(); - OutputImagePointer output = this->GetOutput(); + OutputImagePointer output = this->GetOutput(); // Array to store domain sigmas, used during down-sampling and reconstruction - DomainSigmaArrayType domainSigmaInPixels; + DomainSigmaArrayType domainSigmaInPixels; // Minimum intensity of the input image, - //used during down-sampling and reconstruction - InputPixelType intensityMin; + // used during down-sampling and reconstruction + InputPixelType intensityMin; // Define the GridType // These are pointers to the source and destination of the blurring filter @@ -123,51 +118,46 @@ FastBilateralImageFilter // Setup the higher dimensional grids (gridImage and gridWeight). { - GridIndexType gridStartPos; - GridSizeType gridSize; - - // Convert domain sigmas from spacing units to pixel units - // for the blurring in the grid. - // The set method for m_DomainSigma uses spacing units to be - // consistent with the itkBilateralImageFilter implementation. - // When the data is placed into bins in the grid the - // itkDiscreteGaussianImageFilter will be run on the grid using - // imageSpacingOff. - InputImageSizeType inputSize = input->GetRequestedRegion().GetSize(); -// InputImageSizeType fullSize = input->GetLargestPossibleRegion().GetSize(); - - const InputImageSpacingType& spacing = input->GetSpacing(); - for (size_t i = 0; i < ImageDimension; ++i) + GridIndexType gridStartPos; + GridSizeType gridSize; + + // Convert domain sigmas from spacing units to pixel units + // for the blurring in the grid. + // The set method for m_DomainSigma uses spacing units to be + // consistent with the itkBilateralImageFilter implementation. + // When the data is placed into bins in the grid the + // itkDiscreteGaussianImageFilter will be run on the grid using + // imageSpacingOff. + InputImageSizeType inputSize = input->GetRequestedRegion().GetSize(); + // InputImageSizeType fullSize = input->GetLargestPossibleRegion().GetSize(); + + const InputImageSpacingType & spacing = input->GetSpacing(); + for (size_t i = 0; i < ImageDimension; ++i) { - domainSigmaInPixels[i] = m_DomainSigma[i] / spacing[i]; - gridSize[i] = std::floor( (inputSize[i] - 1) / domainSigmaInPixels[i] ) - + 1 + 2*padding; + domainSigmaInPixels[i] = m_DomainSigma[i] / spacing[i]; + gridSize[i] = std::floor((inputSize[i] - 1) / domainSigmaInPixels[i]) + 1 + 2 * padding; } - // Determine min/max intensities to calculate grid size in the intensity axis - using MinMaxCalculatorType = MinimumMaximumImageCalculator< InputImageType >; - typename MinMaxCalculatorType::Pointer calculator = - MinMaxCalculatorType::New(); - - calculator->SetImage(input); - calculator->Compute(); - intensityMin = calculator->GetMinimum(); - InputPixelType intensityMax = calculator->GetMaximum(); - InputPixelType intensityDelta = - static_cast(intensityMax - intensityMin); - gridSize[ImageDimension] = - static_cast((intensityDelta/m_RangeSigma)+1+2*padding); - - for(size_t i = 0; i < ImageDimension+1; ++i) + // Determine min/max intensities to calculate grid size in the intensity axis + using MinMaxCalculatorType = MinimumMaximumImageCalculator; + typename MinMaxCalculatorType::Pointer calculator = MinMaxCalculatorType::New(); + + calculator->SetImage(input); + calculator->Compute(); + intensityMin = calculator->GetMinimum(); + InputPixelType intensityMax = calculator->GetMaximum(); + InputPixelType intensityDelta = static_cast(intensityMax - intensityMin); + gridSize[ImageDimension] = static_cast((intensityDelta / m_RangeSigma) + 1 + 2 * padding); + + for (size_t i = 0; i < ImageDimension + 1; ++i) { - gridStartPos[i] = 0; + gridStartPos[i] = 0; } - GridRegionType region; - region.SetSize(gridSize); - region.SetIndex(gridStartPos); - gridImage->SetRegions(region); - + GridRegionType region; + region.SetSize(gridSize); + region.SetIndex(gridStartPos); + gridImage->SetRegions(region); } // Allocate the memory for pixel data @@ -180,44 +170,40 @@ FastBilateralImageFilter // Duplicate our grid image for the weight image { - using DuplicatorType = ImageDuplicator; - typename DuplicatorType::Pointer duplicator = DuplicatorType::New(); - duplicator->SetInputImage(gridImage); - duplicator->Update(); - gridWeight = duplicator->GetOutput(); + using DuplicatorType = ImageDuplicator; + typename DuplicatorType::Pointer duplicator = DuplicatorType::New(); + duplicator->SetInputImage(gridImage); + duplicator->Update(); + gridWeight = duplicator->GetOutput(); } // Sort the input image in gridImage and keep track of weights in gridWeight { - InputImageConstIteratorType iterInputImage - (input, input->GetRequestedRegion()); - GridIndexType gridIndices; - size_t i; - InputPixelType current; - InputPixelType intensityDelta; - InputImageIndexType index; - - // For every pixel in the input image, place it into a bin in the grid - // This is a scatter type operation and will be inefficient, as far as I - // know, there is no way to place the pixels into the grid using iterators - for ( iterInputImage.GoToBegin(); !iterInputImage.IsAtEnd(); - ++iterInputImage) + InputImageConstIteratorType iterInputImage(input, input->GetRequestedRegion()); + GridIndexType gridIndices; + size_t i; + InputPixelType current; + InputPixelType intensityDelta; + InputImageIndexType index; + + // For every pixel in the input image, place it into a bin in the grid + // This is a scatter type operation and will be inefficient, as far as I + // know, there is no way to place the pixels into the grid using iterators + for (iterInputImage.GoToBegin(); !iterInputImage.IsAtEnd(); ++iterInputImage) { - index = iterInputImage.GetIndex(); - current = iterInputImage.Get(); - // Determine the position in the grid to place the pixel - for ( i = 0; i < ImageDimension; ++i) + index = iterInputImage.GetIndex(); + current = iterInputImage.Get(); + // Determine the position in the grid to place the pixel + for (i = 0; i < ImageDimension; ++i) { - gridIndices[i] = static_cast - (index[i]/domainSigmaInPixels[i]+0.5+padding); + gridIndices[i] = static_cast(index[i] / domainSigmaInPixels[i] + 0.5 + padding); } - intensityDelta = current - intensityMin; - gridIndices[ImageDimension] = - static_cast(intensityDelta/m_RangeSigma+0.5+padding); + intensityDelta = current - intensityMin; + gridIndices[ImageDimension] = static_cast(intensityDelta / m_RangeSigma + 0.5 + padding); - // Update the bin and the weight - (gridImage->GetPixel(gridIndices)) += current; - (gridWeight->GetPixel(gridIndices)) += 1.0; + // Update the bin and the weight + (gridImage->GetPixel(gridIndices)) += current; + (gridWeight->GetPixel(gridIndices)) += 1.0; } } @@ -225,33 +211,33 @@ FastBilateralImageFilter // outputs are pointed to by gridImageOut and gridWeightOut { - // This variance approximately corresponds to a 1D filter of [1 2 1] which is - // used in Paris and Durands C++ implementation to blur their down-sampled - // data. With this variance a kernel width larger than 5 is not necessary. - double variance = 1.59577; - int maxWidth = 5; + // This variance approximately corresponds to a 1D filter of [1 2 1] which is + // used in Paris and Durands C++ implementation to blur their down-sampled + // data. With this variance a kernel width larger than 5 is not necessary. + double variance = 1.59577; + int maxWidth = 5; - // Setup the Gaussian filter - typename BlurType::Pointer gridImageBlurFilter = BlurType::New(); - typename BlurType::Pointer gridWeightBlurFilter = BlurType::New(); + // Setup the Gaussian filter + typename BlurType::Pointer gridImageBlurFilter = BlurType::New(); + typename BlurType::Pointer gridWeightBlurFilter = BlurType::New(); - gridImageBlurFilter ->SetVariance(variance); - gridWeightBlurFilter->SetVariance(variance); + gridImageBlurFilter->SetVariance(variance); + gridWeightBlurFilter->SetVariance(variance); - gridImageBlurFilter ->SetUseImageSpacingOff(); - gridWeightBlurFilter->SetUseImageSpacingOff(); + gridImageBlurFilter->SetUseImageSpacingOff(); + gridWeightBlurFilter->SetUseImageSpacingOff(); - gridImageBlurFilter ->SetMaximumKernelWidth(maxWidth); - gridWeightBlurFilter->SetMaximumKernelWidth(maxWidth); + gridImageBlurFilter->SetMaximumKernelWidth(maxWidth); + gridWeightBlurFilter->SetMaximumKernelWidth(maxWidth); - gridImageBlurFilter ->SetInput(gridImage); - gridWeightBlurFilter->SetInput(gridWeight); + gridImageBlurFilter->SetInput(gridImage); + gridWeightBlurFilter->SetInput(gridWeight); - gridImageOut = gridImageBlurFilter ->GetOutput(); - gridWeightOut = gridWeightBlurFilter->GetOutput(); + gridImageOut = gridImageBlurFilter->GetOutput(); + gridWeightOut = gridWeightBlurFilter->GetOutput(); - gridImageBlurFilter ->Update(); - gridWeightBlurFilter->Update(); + gridImageBlurFilter->Update(); + gridWeightBlurFilter->Update(); } // Early division; in Paris and Durand's implementation early division can @@ -259,19 +245,17 @@ FastBilateralImageFilter // weights can be done then the division. Interpolation is an expensive // operation so I've opted for the early division approach. { - GridImageIteratorType iterGridImage - (gridImageOut, gridImageOut->GetLargestPossibleRegion()); - GridImageConstIteratorType iterGridWeight - (gridWeightOut, gridWeightOut->GetLargestPossibleRegion()); + GridImageIteratorType iterGridImage(gridImageOut, gridImageOut->GetLargestPossibleRegion()); + GridImageConstIteratorType iterGridWeight(gridWeightOut, gridWeightOut->GetLargestPossibleRegion()); - GridPixelType weight; + GridPixelType weight; - for ( iterGridImage.GoToBegin(), iterGridWeight.GoToBegin(); - !iterGridImage.IsAtEnd(); ++iterGridImage, ++iterGridWeight) + for (iterGridImage.GoToBegin(), iterGridWeight.GoToBegin(); !iterGridImage.IsAtEnd(); + ++iterGridImage, ++iterGridWeight) { - if ( (weight = iterGridWeight.Get() ) != 0.0 ) + if ((weight = iterGridWeight.Get()) != 0.0) { - iterGridImage.Value() /= weight; + iterGridImage.Value() /= weight; } } } @@ -281,53 +265,45 @@ FastBilateralImageFilter // was placed and interpolate for the output pixel's value. { - OutputImageIteratorType iterOutputImage - (output, output->GetRequestedRegion()); - InputImageConstIteratorType iterInputImage - (input, output->GetRequestedRegion()); - - InterpolatedIndexType gridIndices; - size_t i; - InputPixelType current; - InputPixelType intensityDelta; - InputImageIndexType index; - typename InterpolatorType::Pointer interpolator = InterpolatorType::New(); - interpolator->SetInputImage(gridImageOut); - - for ( iterOutputImage.GoToBegin(), iterInputImage.GoToBegin(); - !iterOutputImage.IsAtEnd(); ++iterOutputImage, ++iterInputImage) + OutputImageIteratorType iterOutputImage(output, output->GetRequestedRegion()); + InputImageConstIteratorType iterInputImage(input, output->GetRequestedRegion()); + + InterpolatedIndexType gridIndices; + size_t i; + InputPixelType current; + InputPixelType intensityDelta; + InputImageIndexType index; + typename InterpolatorType::Pointer interpolator = InterpolatorType::New(); + interpolator->SetInputImage(gridImageOut); + + for (iterOutputImage.GoToBegin(), iterInputImage.GoToBegin(); !iterOutputImage.IsAtEnd(); + ++iterOutputImage, ++iterInputImage) { - index = iterInputImage.GetIndex(); - current = iterInputImage.Get(); - // Determine the position in the grid to get the data from - for ( i = 0; i < ImageDimension; ++i) + index = iterInputImage.GetIndex(); + current = iterInputImage.Get(); + // Determine the position in the grid to get the data from + for (i = 0; i < ImageDimension; ++i) { - gridIndices[i] = index[i] / domainSigmaInPixels[i] + padding; + gridIndices[i] = index[i] / domainSigmaInPixels[i] + padding; } - intensityDelta = current - intensityMin; + intensityDelta = current - intensityMin; - gridIndices[ImageDimension] = - intensityDelta / m_RangeSigma + padding; - - iterOutputImage.Set( static_cast - (interpolator->EvaluateAtContinuousIndex(gridIndices)) - ); + gridIndices[ImageDimension] = intensityDelta / m_RangeSigma + padding; + iterOutputImage.Set(static_cast(interpolator->EvaluateAtContinuousIndex(gridIndices))); } } } -template< class TInputImage, class TOutputImage > +template void -FastBilateralImageFilter -::PrintSelf(std::ostream& os, Indent indent) const +FastBilateralImageFilter::PrintSelf(std::ostream & os, Indent indent) const { - Superclass::PrintSelf(os,indent); + Superclass::PrintSelf(os, indent); os << indent << "DomainSigma: " << m_DomainSigma << std::endl; os << indent << "RangeSigma: " << m_RangeSigma << std::endl; - } } // namespace itk diff --git a/Modules/Filtering/FastBilateral/test/itkFastBilateralImageFilterTest2.cxx b/Modules/Filtering/FastBilateral/test/itkFastBilateralImageFilterTest2.cxx index 6150d54dcb5..5d4241cddd2 100644 --- a/Modules/Filtering/FastBilateral/test/itkFastBilateralImageFilterTest2.cxx +++ b/Modules/Filtering/FastBilateral/test/itkFastBilateralImageFilterTest2.cxx @@ -26,13 +26,14 @@ * This test was originally taken from the tests for the itkBilateralImageFilter * and modified for the itkFastBilateralImageFilter. */ -int itkFastBilateralImageFilterTest2(int ac, char* av[] ) +int +itkFastBilateralImageFilterTest2(int ac, char * av[]) { - if(ac < 3) - { + if (ac < 3) + { std::cerr << "Usage: " << av[0] << " InputImage OutputImage\n"; return EXIT_FAILURE; - } + } using PixelType = unsigned char; const unsigned int dimension = 2; @@ -41,7 +42,7 @@ int itkFastBilateralImageFilterTest2(int ac, char* av[] ) input->SetFileName(av[1]); // Create a filter - using FilterType = itk::FastBilateralImageFilter; + using FilterType = itk::FastBilateralImageFilter; auto filter = FilterType::New(); @@ -49,16 +50,16 @@ int itkFastBilateralImageFilterTest2(int ac, char* av[] ) // these settings reduce the amount of noise by a factor of 10 // when the original signal to noise level is 5 - filter->SetDomainSigma( 4.0 ); - filter->SetRangeSigma( 50.0 ); + filter->SetDomainSigma(4.0); + filter->SetRangeSigma(50.0); // Test itkSetVectorMacro double domainSigma[dimension]; for (unsigned int i = 0; i < dimension; i++) - { - domainSigma[i] = 4.0; - } + { + domainSigma[i] = 4.0; + } filter->SetDomainSigma(domainSigma); // Test itkGetMacro @@ -66,27 +67,27 @@ int itkFastBilateralImageFilterTest2(int ac, char* av[] ) std::cout << "filter->GetRangeSigma(): " << filter->GetRangeSigma() << std::endl; try - { + { input->Update(); filter->Update(); - } - catch (itk::ExceptionObject& e) - { - std::cerr << "Exception detected: " << e.GetDescription(); + } + catch (itk::ExceptionObject & e) + { + std::cerr << "Exception detected: " << e.GetDescription(); return -1; - } + } catch (...) - { + { std::cerr << "Some other exception occurred" << std::endl; return -2; - } + } // Generate test image itk::ImageFileWriter::Pointer writer; - writer = itk::ImageFileWriter::New(); - writer->SetInput( filter->GetOutput() ); - writer->SetFileName( av[2] ); - writer->Update(); + writer = itk::ImageFileWriter::New(); + writer->SetInput(filter->GetOutput()); + writer->SetFileName(av[2]); + writer->Update(); return EXIT_SUCCESS; } diff --git a/Modules/Filtering/FastBilateral/test/itkFastBilateralImageFilterTest3.cxx b/Modules/Filtering/FastBilateral/test/itkFastBilateralImageFilterTest3.cxx index e4766fc9b62..fc1c48edf54 100644 --- a/Modules/Filtering/FastBilateral/test/itkFastBilateralImageFilterTest3.cxx +++ b/Modules/Filtering/FastBilateral/test/itkFastBilateralImageFilterTest3.cxx @@ -28,13 +28,14 @@ * This test was originally taken from the tests for the itkBilateralImageFilter * and modified for the itkFastBilateralImageFilter. */ -int itkFastBilateralImageFilterTest3(int ac, char* av[] ) +int +itkFastBilateralImageFilterTest3(int ac, char * av[]) { - if(ac < 3) - { + if (ac < 3) + { std::cerr << "Usage: " << av[0] << " InputImage BaselineImage\n"; return -1; - } + } using PixelType = unsigned char; using ImageType = itk::Image; @@ -42,49 +43,49 @@ int itkFastBilateralImageFilterTest3(int ac, char* av[] ) input->SetFileName(av[1]); // Create a filter - using FilterType = itk::FastBilateralImageFilter; + using FilterType = itk::FastBilateralImageFilter; FilterType::Pointer filter1 = FilterType::New(); - filter1->SetInput(input->GetOutput()); + filter1->SetInput(input->GetOutput()); FilterType::Pointer filter2 = FilterType::New(); - filter2->SetInput(filter1->GetOutput()); + filter2->SetInput(filter1->GetOutput()); FilterType::Pointer filter3 = FilterType::New(); - filter3->SetInput(filter2->GetOutput()); + filter3->SetInput(filter2->GetOutput()); - // Instead of using a single agressive smoothing filter, use 3 - // less aggressive filters. - // - // These settings match the "wedding" cake image (cake_easy.png) where - // the signal to noise ratio is 5 (step heights near 100 units, - // noise sigma near 20 units). A single filter stage with these - // settings cuts the noise level in half. These three stages should - // reduce the amount of noise by a factor of 8. This is comparable to - // the noise reduction in using a single stage with parameters - // (4.0, 50.0). The difference is that with 3 less aggressive stages - // the edges are preserved better. - filter1->SetDomainSigma( 4.0 ); - filter1->SetRangeSigma( 20.0 ); - filter2->SetDomainSigma( 4.0 ); - filter2->SetRangeSigma( 20.0 ); - filter3->SetDomainSigma( 4.0 ); - filter3->SetRangeSigma( 20.0 ); + // Instead of using a single agressive smoothing filter, use 3 + // less aggressive filters. + // + // These settings match the "wedding" cake image (cake_easy.png) where + // the signal to noise ratio is 5 (step heights near 100 units, + // noise sigma near 20 units). A single filter stage with these + // settings cuts the noise level in half. These three stages should + // reduce the amount of noise by a factor of 8. This is comparable to + // the noise reduction in using a single stage with parameters + // (4.0, 50.0). The difference is that with 3 less aggressive stages + // the edges are preserved better. + filter1->SetDomainSigma(4.0); + filter1->SetRangeSigma(20.0); + filter2->SetDomainSigma(4.0); + filter2->SetRangeSigma(20.0); + filter3->SetDomainSigma(4.0); + filter3->SetRangeSigma(20.0); try - { + { input->Update(); filter3->Update(); - } - catch (itk::ExceptionObject& e) - { - std::cerr << "Exception detected: " << e.GetDescription(); + } + catch (itk::ExceptionObject & e) + { + std::cerr << "Exception detected: " << e.GetDescription(); return -1; - } + } // Generate test image itk::ImageFileWriter::Pointer writer; writer = itk::ImageFileWriter::New(); - writer->SetInput( filter3->GetOutput() ); - writer->SetFileName( av[2] ); + writer->SetInput(filter3->GetOutput()); + writer->SetFileName(av[2]); writer->Update(); return EXIT_SUCCESS; From 5fbe87b6abd99ccaf96eb1bf66c265f868cd054d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C5=BEenan=20Zuki=C4=87?= Date: Tue, 19 Mar 2024 10:01:10 -0400 Subject: [PATCH 07/18] COMP: Fix clang compile warnings about missing override specifier Example warning: include/itkFastBilateralImageFilter.h:155:16: warning: 'GenerateInputRequestedRegion' overrides a member function but is not marked 'override' [-Winconsistent-missing-override] --- .../FastBilateral/include/itkFastBilateralImageFilter.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Modules/Filtering/FastBilateral/include/itkFastBilateralImageFilter.h b/Modules/Filtering/FastBilateral/include/itkFastBilateralImageFilter.h index 1f70fe8fefb..ba11520cdb2 100644 --- a/Modules/Filtering/FastBilateral/include/itkFastBilateralImageFilter.h +++ b/Modules/Filtering/FastBilateral/include/itkFastBilateralImageFilter.h @@ -151,16 +151,16 @@ class ITK_EXPORT FastBilateralImageFilter : public ImageToImageFilter Date: Sun, 26 Jan 2025 08:58:03 -0600 Subject: [PATCH 08/18] STYLE: Add itkVirtualGetNameOfClassMacro + itkOverrideGetNameOfClassMacro Added two new macro's, intended to replace the old 'itkTypeMacro' and 'itkTypeMacroNoParent'. The main aim is to be clearer about what those macro's do: add a virtual 'GetNameOfClass()' member function and override it. Unlike 'itkTypeMacro', 'itkOverrideGetNameOfClassMacro' does not have a 'superclass' parameter, as it was not used anyway. Note that originally 'itkTypeMacro' did not use its 'superclass' parameter either, looking at commit 699b66cb04d410e555656828e8892107add38ccb, Will Schroeder, June 27, 2001: https://github.com/InsightSoftwareConsortium/ITK/blob/699b66cb04d410e555656828e8892107add38ccb/Code/Common/itkMacro.h#L331-L337 --- .../FastBilateral/include/itkFastBilateralImageFilter.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/Filtering/FastBilateral/include/itkFastBilateralImageFilter.h b/Modules/Filtering/FastBilateral/include/itkFastBilateralImageFilter.h index ba11520cdb2..88b308fc547 100644 --- a/Modules/Filtering/FastBilateral/include/itkFastBilateralImageFilter.h +++ b/Modules/Filtering/FastBilateral/include/itkFastBilateralImageFilter.h @@ -85,7 +85,7 @@ class ITK_EXPORT FastBilateralImageFilter : public ImageToImageFilter Date: Sun, 26 Jan 2025 10:52:43 -0600 Subject: [PATCH 09/18] STYLE: Replace itkStaticConstMacro with static constexpr Use static constexpr directly now that C++11 conformance is required by all compilers. :%s/itkStaticConstMacro *( *\([^,]*\),[ \_s]*\([^,]*\),\_s*\([^)]*\)) */static constexpr \2 \1 = \3/ge 'itkStaticConstMacro(name, type, value)' became unconditionally identical to 'static constexpr type name = value' with ITK commit aec95193ab00e1322039911e1032da00f3a103b6 "ENH: Update compiler macros (#810)", maekclena, 7 May 2019. 'itkGetStaticConstMacro(name)' became unconditionally identical to '(Self::name)' with ITK commit 84e490b81e3f3c2b0edb89ae7b9de53bfc52f2b2 "Removing some outdated compiler conditionals", Hans Johnson, 31 July 2010. Most 'itkStaticConstMacro' calls were removed by ITK commit 5c14741e1e063a132ea7e7ee69c5bd0a4e49af74 --- .../FastBilateral/include/itkFastBilateralImageFilter.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Modules/Filtering/FastBilateral/include/itkFastBilateralImageFilter.h b/Modules/Filtering/FastBilateral/include/itkFastBilateralImageFilter.h index 88b308fc547..08ed21c1fb0 100644 --- a/Modules/Filtering/FastBilateral/include/itkFastBilateralImageFilter.h +++ b/Modules/Filtering/FastBilateral/include/itkFastBilateralImageFilter.h @@ -115,7 +115,7 @@ class ITK_EXPORT FastBilateralImageFilter : public ImageToImageFilter; + using DomainSigmaArrayType = FixedArray; /** Standard get/set macros for filter parameters. * DomainSigma is specified in the same units as the Image spacing. @@ -164,13 +164,13 @@ class ITK_EXPORT FastBilateralImageFilter : public ImageToImageFilter; + using GridType = typename itk::Image; /** Grid types */ using GridPixelType = typename GridType::PixelType; using GridIndexType = typename GridType::IndexType; using GridSizeType = typename GridType::SizeType; - using GridSizeValueType = typename Size::SizeValueType; + using GridSizeValueType = typename Size::SizeValueType; using GridRegionType = typename GridType::RegionType; /** Grid image iterator type. */ From cf712aabf140df38477247156278236df079b6be Mon Sep 17 00:00:00 2001 From: Hans Johnson Date: Sun, 26 Jan 2025 12:38:52 -0600 Subject: [PATCH 10/18] COMP: Replace SetUseImageSpacingOff -> UseImageSpacingOff The SetUseImageSpacingOff function was deprecated --- .../FastBilateral/include/itkFastBilateralImageFilter.hxx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Modules/Filtering/FastBilateral/include/itkFastBilateralImageFilter.hxx b/Modules/Filtering/FastBilateral/include/itkFastBilateralImageFilter.hxx index bc2778a2d3e..c3adeb011ae 100644 --- a/Modules/Filtering/FastBilateral/include/itkFastBilateralImageFilter.hxx +++ b/Modules/Filtering/FastBilateral/include/itkFastBilateralImageFilter.hxx @@ -224,8 +224,8 @@ FastBilateralImageFilter::GenerateData() gridImageBlurFilter->SetVariance(variance); gridWeightBlurFilter->SetVariance(variance); - gridImageBlurFilter->SetUseImageSpacingOff(); - gridWeightBlurFilter->SetUseImageSpacingOff(); + gridImageBlurFilter->UseImageSpacingOff(); + gridWeightBlurFilter->UseImageSpacingOff(); gridImageBlurFilter->SetMaximumKernelWidth(maxWidth); gridWeightBlurFilter->SetMaximumKernelWidth(maxWidth); From 8ab35e9c3d4d2e7374fb25dbbaff1fd9406924cc Mon Sep 17 00:00:00 2001 From: "Hans J. Johnson" Date: Tue, 14 Apr 2026 17:34:58 -0500 Subject: [PATCH 11/18] STYLE: Replace 'typedefs' with 'type aliases' in comments The code already uses C++ 'using' declarations. Update the corresponding comments to say 'type aliases' instead of the legacy 'typedefs' terminology. --- .../FastBilateral/include/itkFastBilateralImageFilter.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Modules/Filtering/FastBilateral/include/itkFastBilateralImageFilter.h b/Modules/Filtering/FastBilateral/include/itkFastBilateralImageFilter.h index 08ed21c1fb0..b23e898602e 100644 --- a/Modules/Filtering/FastBilateral/include/itkFastBilateralImageFilter.h +++ b/Modules/Filtering/FastBilateral/include/itkFastBilateralImageFilter.h @@ -75,7 +75,7 @@ class ITK_EXPORT FastBilateralImageFilter : public ImageToImageFilter; using Pointer = SmartPointer; @@ -91,7 +91,7 @@ class ITK_EXPORT FastBilateralImageFilter : public ImageToImageFilter; - /** Output image typedefs. */ + /** Output image type aliases. */ using OutputImageType = TOutputImage; using OutputImagePointer = typename TOutputImage::Pointer; From fb7413ff89dd053e9e52bf27be945ee6a30fa3c9 Mon Sep 17 00:00:00 2001 From: "Hans J. Johnson" Date: Wed, 22 Apr 2026 18:45:19 -0500 Subject: [PATCH 12/18] ENH: Convert from md5 to .cid tags. --- .../test/Baseline/itkFastBilateralImageFilterTest2Output.png.cid | 1 + .../Baseline/itkFastBilateralImageFilterTest2Output.png.sha512 | 1 - .../test/Baseline/itkFastBilateralImageFilterTest3Output.png.cid | 1 + .../Baseline/itkFastBilateralImageFilterTest3Output.png.sha512 | 1 - .../test/Baseline/itkFastBilateralImageFilterTestOutput.mha.cid | 1 + .../Baseline/itkFastBilateralImageFilterTestOutput.mha.sha512 | 1 - Modules/Filtering/FastBilateral/test/Input/cake_easy.png.cid | 1 + Modules/Filtering/FastBilateral/test/Input/cake_easy.png.sha512 | 1 - 8 files changed, 4 insertions(+), 4 deletions(-) create mode 100644 Modules/Filtering/FastBilateral/test/Baseline/itkFastBilateralImageFilterTest2Output.png.cid delete mode 100644 Modules/Filtering/FastBilateral/test/Baseline/itkFastBilateralImageFilterTest2Output.png.sha512 create mode 100644 Modules/Filtering/FastBilateral/test/Baseline/itkFastBilateralImageFilterTest3Output.png.cid delete mode 100644 Modules/Filtering/FastBilateral/test/Baseline/itkFastBilateralImageFilterTest3Output.png.sha512 create mode 100644 Modules/Filtering/FastBilateral/test/Baseline/itkFastBilateralImageFilterTestOutput.mha.cid delete mode 100644 Modules/Filtering/FastBilateral/test/Baseline/itkFastBilateralImageFilterTestOutput.mha.sha512 create mode 100644 Modules/Filtering/FastBilateral/test/Input/cake_easy.png.cid delete mode 100644 Modules/Filtering/FastBilateral/test/Input/cake_easy.png.sha512 diff --git a/Modules/Filtering/FastBilateral/test/Baseline/itkFastBilateralImageFilterTest2Output.png.cid b/Modules/Filtering/FastBilateral/test/Baseline/itkFastBilateralImageFilterTest2Output.png.cid new file mode 100644 index 00000000000..4644bf77b5a --- /dev/null +++ b/Modules/Filtering/FastBilateral/test/Baseline/itkFastBilateralImageFilterTest2Output.png.cid @@ -0,0 +1 @@ +bafkreiadhbzhtn4fsqlgw4lscdcwzkqbrs5gntgirpbobrdbwv6hskaozy diff --git a/Modules/Filtering/FastBilateral/test/Baseline/itkFastBilateralImageFilterTest2Output.png.sha512 b/Modules/Filtering/FastBilateral/test/Baseline/itkFastBilateralImageFilterTest2Output.png.sha512 deleted file mode 100644 index 54d7b3f915e..00000000000 --- a/Modules/Filtering/FastBilateral/test/Baseline/itkFastBilateralImageFilterTest2Output.png.sha512 +++ /dev/null @@ -1 +0,0 @@ -a672baa7da752bbc1644e63361b347008398db86f03ed03baa9822beccece5116489dc0ef4c5c059f31838cab282466cf1dd6ae5b9466724ff9d8854a676d33a diff --git a/Modules/Filtering/FastBilateral/test/Baseline/itkFastBilateralImageFilterTest3Output.png.cid b/Modules/Filtering/FastBilateral/test/Baseline/itkFastBilateralImageFilterTest3Output.png.cid new file mode 100644 index 00000000000..ad6fbbd4cf4 --- /dev/null +++ b/Modules/Filtering/FastBilateral/test/Baseline/itkFastBilateralImageFilterTest3Output.png.cid @@ -0,0 +1 @@ +bafkreibryts52hwb7mtu5lab6lvf36omn5jlpk6hmedue2itn7f3s5zrvm diff --git a/Modules/Filtering/FastBilateral/test/Baseline/itkFastBilateralImageFilterTest3Output.png.sha512 b/Modules/Filtering/FastBilateral/test/Baseline/itkFastBilateralImageFilterTest3Output.png.sha512 deleted file mode 100644 index 2a0e19fabf5..00000000000 --- a/Modules/Filtering/FastBilateral/test/Baseline/itkFastBilateralImageFilterTest3Output.png.sha512 +++ /dev/null @@ -1 +0,0 @@ -eeaaa0902595818d403fa110221f59fa91b2844baf06332c1633227743fa201f3022fa2e0ad0580f186ae50ae32d973fcae6a876d8286181ba778e61dabfd771 diff --git a/Modules/Filtering/FastBilateral/test/Baseline/itkFastBilateralImageFilterTestOutput.mha.cid b/Modules/Filtering/FastBilateral/test/Baseline/itkFastBilateralImageFilterTestOutput.mha.cid new file mode 100644 index 00000000000..5f6fabb3007 --- /dev/null +++ b/Modules/Filtering/FastBilateral/test/Baseline/itkFastBilateralImageFilterTestOutput.mha.cid @@ -0,0 +1 @@ +bafkreickuip2r2uejp3bzrizyvis7vs77edil3kkuh45rnye5tvfrjof6i diff --git a/Modules/Filtering/FastBilateral/test/Baseline/itkFastBilateralImageFilterTestOutput.mha.sha512 b/Modules/Filtering/FastBilateral/test/Baseline/itkFastBilateralImageFilterTestOutput.mha.sha512 deleted file mode 100644 index c811785f3e7..00000000000 --- a/Modules/Filtering/FastBilateral/test/Baseline/itkFastBilateralImageFilterTestOutput.mha.sha512 +++ /dev/null @@ -1 +0,0 @@ -34cdd2aafce413dcf7efc692a707d53b7b57ebb006d0fbc20ecb42343f8a078b2252eff2137b17d3ab583d133f780438e247241ebf213c3289bd9ba1525081b7 diff --git a/Modules/Filtering/FastBilateral/test/Input/cake_easy.png.cid b/Modules/Filtering/FastBilateral/test/Input/cake_easy.png.cid new file mode 100644 index 00000000000..e4277c4e156 --- /dev/null +++ b/Modules/Filtering/FastBilateral/test/Input/cake_easy.png.cid @@ -0,0 +1 @@ +bafkreigza53i5anoecoz4zufifwdpuoxc375zr5x5eussjdahzivtrzjfa diff --git a/Modules/Filtering/FastBilateral/test/Input/cake_easy.png.sha512 b/Modules/Filtering/FastBilateral/test/Input/cake_easy.png.sha512 deleted file mode 100644 index 2074b776757..00000000000 --- a/Modules/Filtering/FastBilateral/test/Input/cake_easy.png.sha512 +++ /dev/null @@ -1 +0,0 @@ -0aad3941e82b5cb077b791606abdb186c4284956f03b58a629f2434a98b5e4bf8efcc32a7aa66791b16c57cf4da5cb83d9801e2d7db3d0e58e1ada401ddbc20c From 5544e523e6f565fa3df6761e90d5ac3407303611 Mon Sep 17 00:00:00 2001 From: "Hans J. Johnson" Date: Tue, 28 Apr 2026 09:00:08 -0500 Subject: [PATCH 13/18] COMP: Drop standalone-build boilerplate from FastBilateral The upstream remote module's top-level CMakeLists.txt carried a dual-mode preamble that supports both standalone (find_package(ITK) + ITKModuleExternal) and in-tree (itk_module_impl) builds. Once the module lives under Modules/Filtering/, only the in-tree branch is reachable -- the standalone branch is dead code, the cmake_minimum_required and project() lines duplicate what ITK's root CMake already owns. Collapse the file to a single itk_module_impl() call, matching every other in-tree Modules/// module. Per the standalone-build cleanup convention documented in Utilities/Maintenance/RemoteModuleIngest/INGESTION_STRATEGY.md under "Standalone-build boilerplate cleanup (modes A/B)" and applied previously to GenericLabelInterpolator (PR #6135) and MGHIO (PR #6137). --- Modules/Filtering/FastBilateral/CMakeLists.txt | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/Modules/Filtering/FastBilateral/CMakeLists.txt b/Modules/Filtering/FastBilateral/CMakeLists.txt index 5f6c50692cf..9da2e833596 100644 --- a/Modules/Filtering/FastBilateral/CMakeLists.txt +++ b/Modules/Filtering/FastBilateral/CMakeLists.txt @@ -1,13 +1 @@ -cmake_minimum_required(VERSION 3.16.3) -project(FastBilateral) - -# set(FastBilateral_LIBRARIES FastBilateral) - -if(NOT ITK_SOURCE_DIR) - find_package(ITK REQUIRED) - list(APPEND CMAKE_MODULE_PATH ${ITK_CMAKE_DIR}) - include(ITKModuleExternal) -else() - set(ITK_DIR ${CMAKE_BINARY_DIR}) - itk_module_impl() -endif() +itk_module_impl() From 325fe1e414cbf5651befe7d5c0b8e58a1e196a7d Mon Sep 17 00:00:00 2001 From: "Hans J. Johnson" Date: Tue, 28 Apr 2026 09:00:19 -0500 Subject: [PATCH 14/18] COMP: Remove FastBilateral.remote.cmake; now in-tree The module now lives at Modules/Filtering/FastBilateral/. The configure-time fetch declaration in Modules/Remote/ would otherwise clone the (soon-to-be-archived) upstream and double-define the module. Mirrors the in-tree transition completed for GenericLabelInterpolator (PR #6135) and MGHIO (PR #6137). --- Modules/Remote/FastBilateral.remote.cmake | 54 ----------------------- 1 file changed, 54 deletions(-) delete mode 100644 Modules/Remote/FastBilateral.remote.cmake diff --git a/Modules/Remote/FastBilateral.remote.cmake b/Modules/Remote/FastBilateral.remote.cmake deleted file mode 100644 index 4e03b1204ad..00000000000 --- a/Modules/Remote/FastBilateral.remote.cmake +++ /dev/null @@ -1,54 +0,0 @@ -#-- # Grading Level Criteria Report -#-- EVALUATION DATE: 2024-03-19 -#-- EVALUATORS: [Dženan Zukić] -#-- -#-- ## Compliance level 5 star (AKA ITK main modules, or remote modules that could become core modules) -#-- - [ ] Widespread community dependance -#-- - [ ] Above 90% code coverage -#-- - [ ] CI dashboards and testing monitored rigorously -#-- - [x] Key API features are exposed in wrapping interface -#-- - [ ] All requirements of Levels 4,3,2,1 -#-- -#-- ## Compliance Level 4 star (Very high-quality code, perhaps small community dependance) -#-- - [ ] Meets all ITK code style standards -#-- - [X] No external requirements beyond those needed by ITK proper -#-- - [X] Builds and passes tests on all supported platforms within 1 month of each core tagged release -#-- - [X] Windows Shared Library Build with Visual Studio -#-- - [X] Mac with clang compiller -#-- - [X] Linux with gcc compiler -#-- - [ ] Active developer community dedicated to maintaining code-base -#-- - [ ] 75% code coverage demonstrated for testing suite -#-- - [X] Continuous integration testing performed -#-- - [X] All requirements of Levels 3,2,1 -#-- -#-- ## Compliance Level 3 star (Quality beta code) -#-- - [X] API executable interface is considered mostly stable and feature complete -#-- - [X] 10% C0-code coverage demonstrated for testing suite -#-- - [X] Some tests exist and pass on at least some platform -#-- - [X] All requirements of Levels 2,1 -#-- -#-- ## Compliance Level 2 star (Alpha code feature API development or niche community/execution environment dependance ) -#-- - [X] Compiles for at least 1 niche set of execution envirionments, and perhaps others -#-- (may depend on specific external tools like a java environment, or specific external libraries to work ) -#-- - [X] All requirements of Levels 1 -#-- -#-- ## Compliance Level 1 star (Pre-alpha features under development and code of unknown quality) -#-- - [X] Code complies on at least 1 platform -#-- -#-- ## Compliance Level 0 star ( Code/Feature of known poor-quality or deprecated status ) -#-- - [ ] Code reviewed and explicitly identified as not recommended for use -#-- -#-- ### Please document here any justification for the criteria above -# Code style enforced by clang-format on 2024-03-19 - -# Contact: Dženan Zukić -itk_fetch_module( - FastBilateral - "A Fast Approximation to the Bilateral Filter for ITK - -Insight Journal article: -https://doi.org/10.54294/noo5vc" - MODULE_COMPLIANCE_LEVEL 3 - GIT_REPOSITORY https://github.com/InsightSoftwareConsortium/ITKFastBilateral.git - GIT_TAG cba51ae59ae841405298784bc49b6f51a4adab03 - ) From dda62df617f81a0273ee0f280c0a3ccd27bb6afb Mon Sep 17 00:00:00 2001 From: "Hans J. Johnson" Date: Tue, 28 Apr 2026 09:01:06 -0500 Subject: [PATCH 15/18] ENH: Enable FastBilateral in CI via configure-ci Add -DModule_FastBilateral:BOOL=ON to the Pixi-Cxx configure-ci task so the in-tree module is exercised by the default CI matrix, matching the policy applied to AnisotropicDiffusionLBR, Montage, GenericLabelInterpolator, MGHIO, and StructuralSimilarity. The module declares EXCLUDE_FROM_DEFAULT in its itk-module.cmake, so this opt-in is required for it to be built and tested in CI. --- pyproject.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/pyproject.toml b/pyproject.toml index 75c5d814973..6ef5d8baa48 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -54,6 +54,7 @@ cmd = '''cmake -DCMAKE_CXX_COMPILER_LAUNCHER:STRING=ccache -DModule_AnisotropicDiffusionLBR:BOOL=ON -DModule_Montage:BOOL=ON + -DModule_FastBilateral:BOOL=ON -DModule_GenericLabelInterpolator:BOOL=ON -DModule_MGHIO:BOOL=ON -DITK_COMPUTER_MEMORY_SIZE:STRING=11 From ff6ae1c119927ee8da2cbe21c294fe37af78eaa3 Mon Sep 17 00:00:00 2001 From: "Hans J. Johnson" Date: Tue, 28 Apr 2026 09:05:14 -0500 Subject: [PATCH 16/18] COMP: Drop missing README.rst read in ingested FastBilateral The upstream itk-module.cmake reads README.rst at configure time to populate the module DESCRIPTION. Only the whitelisted code/test paths crossed the ingest boundary (no README.rst), so configure would fail with "file does not exist". Inline the description as a literal string consistent with the AnisotropicDiffusionLBR, GenericLabelInterpolator, and MGHIO ingest patterns, and add a Modules/Filtering/FastBilateral/README.md pointer to the archived upstream repository. --- Modules/Filtering/FastBilateral/README.md | 34 +++++++++++++++++++ .../Filtering/FastBilateral/itk-module.cmake | 16 +++++---- 2 files changed, 43 insertions(+), 7 deletions(-) create mode 100644 Modules/Filtering/FastBilateral/README.md diff --git a/Modules/Filtering/FastBilateral/README.md b/Modules/Filtering/FastBilateral/README.md new file mode 100644 index 00000000000..6271d8f27e8 --- /dev/null +++ b/Modules/Filtering/FastBilateral/README.md @@ -0,0 +1,34 @@ +# FastBilateral + +In-tree ITK module providing +`itk::FastBilateralImageFilter`, a fast approximation to the bilateral +filter that performs edge-preserving smoothing by accumulating samples +into a low-resolution intensity-spatial bilateral grid and then +interpolating back to the input grid. The approximation reduces the +asymptotic cost from `O(N * sigma_s^d * sigma_r)` for the brute-force +bilateral filter to roughly `O(N + L)` where `L` is the size of the +downsampled grid, making it tractable for 3D volumes. + +## Origin + +Ingested from the standalone remote module +[**InsightSoftwareConsortium/ITKFastBilateral**](https://github.com/InsightSoftwareConsortium/ITKFastBilateral) +on 2026-04-28, at upstream tag +[`v1.0.1`](https://github.com/InsightSoftwareConsortium/ITKFastBilateral/releases/tag/v1.0.1) +(commit `54931e8c`). The upstream repository will be archived read-only +after this PR merges; it remains reachable at the URL above. + +## What lives here + +- `include/itkFastBilateralImageFilter.h` — the templated filter. +- `include/itkFastBilateralImageFilter.hxx` — implementation. +- `test/` — three regression tests (Gaussian comparison, Insight Journal + cake/cake_easy fixtures) plus their CID-addressed baselines. +- `wrapping/` — Python wrapping declarations. + +## Reference + +- Sylvain Paris and Frédo Durand, *A Fast Approximation of the Bilateral + Filter using a Signal Processing Approach*, MIT CSAIL TR 2006-073 / + ECCV 2006. The Insight Journal write-up that this module is derived + from is at https://doi.org/10.54294/noo5vc. diff --git a/Modules/Filtering/FastBilateral/itk-module.cmake b/Modules/Filtering/FastBilateral/itk-module.cmake index 4250eb6e4d4..1c95fb7895f 100644 --- a/Modules/Filtering/FastBilateral/itk-module.cmake +++ b/Modules/Filtering/FastBilateral/itk-module.cmake @@ -1,7 +1,9 @@ -# the top-level README is used for describing this module, just -# re-used it for documentation here -get_filename_component(MY_CURRENT_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH) -file(READ "${MY_CURRENT_DIR}/README.rst" DOCUMENTATION) +set( + DOCUMENTATION + "A fast approximation to the bilateral filter for ITK, edge-preserving +smoothing using a low-resolution intensity-spatial bilateral grid. +See the Insight Journal article: https://doi.org/10.54294/noo5vc." +) # itk_module() defines the module dependencies in FastBilateral # FastBilateral depends on ITKCommon @@ -11,7 +13,8 @@ file(READ "${MY_CURRENT_DIR}/README.rst" DOCUMENTATION) # ITK. # define the dependencies of the include module and the tests -itk_module(FastBilateral +itk_module( + FastBilateral DEPENDS ITKCommon ITKSmoothing @@ -20,8 +23,7 @@ itk_module(FastBilateral TEST_DEPENDS ITKTestKernel ITKMetaIO - DESCRIPTION - "${DOCUMENTATION}" + DESCRIPTION "${DOCUMENTATION}" EXCLUDE_FROM_DEFAULT ENABLE_SHARED ) From dd215255629c88594b16ee631e6f8721af696168 Mon Sep 17 00:00:00 2001 From: "Hans J. Johnson" Date: Tue, 28 Apr 2026 12:57:12 -0500 Subject: [PATCH 17/18] STYLE: Apply gersemi and end-of-file-fixer to ingested FastBilateral Apply ITK's current pre-commit formatting set to the ingested CMake and wrapping files inherited from upstream. The upstream module pre-dates ITK's current gersemi/eof-fixer adoption; running them now lets the in-tree pre-commit gate pass cleanly on every push. Mode A step 6 of the ingestion strategy (Utilities/Maintenance/RemoteModuleIngest/INGESTION_STRATEGY.md). --- .../FastBilateral/test/CMakeLists.txt | 37 +++++++++++-------- .../wrapping/itkFastBilateralImageFilter.wrap | 1 - .../wrapping/test/CMakeLists.txt | 6 ++- 3 files changed, 26 insertions(+), 18 deletions(-) diff --git a/Modules/Filtering/FastBilateral/test/CMakeLists.txt b/Modules/Filtering/FastBilateral/test/CMakeLists.txt index f3043caa859..de611f2bd9d 100644 --- a/Modules/Filtering/FastBilateral/test/CMakeLists.txt +++ b/Modules/Filtering/FastBilateral/test/CMakeLists.txt @@ -1,38 +1,45 @@ itk_module_test() -set(FastBilateralTests +set( + FastBilateralTests itkFastBilateralImageFilterTest.cxx itkFastBilateralImageFilterTest2.cxx itkFastBilateralImageFilterTest3.cxx - ) +) -CreateTestDriver(FastBilateral "${FastBilateral-Test_LIBRARIES}" "${FastBilateralTests}") +createtestdriver(FastBilateral "${FastBilateral-Test_LIBRARIES}" "${FastBilateralTests}") -itk_add_test(NAME itkFastBilateralImageFilterTest - COMMAND FastBilateralTestDriver +itk_add_test( + NAME itkFastBilateralImageFilterTest + COMMAND + FastBilateralTestDriver --compare DATA{Baseline/itkFastBilateralImageFilterTestOutput.mha} ${ITK_TEST_OUTPUT_DIR}/itkFastBilateralImageFilterTestOutput.mha - itkFastBilateralImageFilterTest + itkFastBilateralImageFilterTest ${ITK_TEST_OUTPUT_DIR}/itkFastBilateralImageFilterTestOutput.mha - ) +) -itk_add_test(NAME itkFastBilateralImageFilterTest2 - COMMAND FastBilateralTestDriver +itk_add_test( + NAME itkFastBilateralImageFilterTest2 + COMMAND + FastBilateralTestDriver --compare DATA{Baseline/itkFastBilateralImageFilterTest2Output.png} ${ITK_TEST_OUTPUT_DIR}/itkFastBilateralImageFilterTest2Output.png - itkFastBilateralImageFilterTest2 + itkFastBilateralImageFilterTest2 DATA{Input/cake_easy.png} ${ITK_TEST_OUTPUT_DIR}/itkFastBilateralImageFilterTest2Output.png - ) +) -itk_add_test(NAME itkFastBilateralImageFilterTest3 - COMMAND FastBilateralTestDriver +itk_add_test( + NAME itkFastBilateralImageFilterTest3 + COMMAND + FastBilateralTestDriver --compare DATA{Baseline/itkFastBilateralImageFilterTest3Output.png} ${ITK_TEST_OUTPUT_DIR}/itkFastBilateralImageFilterTest3Output.png - itkFastBilateralImageFilterTest3 + itkFastBilateralImageFilterTest3 DATA{Input/cake_easy.png} ${ITK_TEST_OUTPUT_DIR}/itkFastBilateralImageFilterTest3Output.png - ) +) diff --git a/Modules/Filtering/FastBilateral/wrapping/itkFastBilateralImageFilter.wrap b/Modules/Filtering/FastBilateral/wrapping/itkFastBilateralImageFilter.wrap index 1e025ddc796..93531e004da 100644 --- a/Modules/Filtering/FastBilateral/wrapping/itkFastBilateralImageFilter.wrap +++ b/Modules/Filtering/FastBilateral/wrapping/itkFastBilateralImageFilter.wrap @@ -1,4 +1,3 @@ itk_wrap_class("itk::FastBilateralImageFilter" POINTER) itk_wrap_image_filter("${WRAP_ITK_SCALAR}" 2) itk_end_wrap_class() - diff --git a/Modules/Filtering/FastBilateral/wrapping/test/CMakeLists.txt b/Modules/Filtering/FastBilateral/wrapping/test/CMakeLists.txt index 31cb0555519..a661a403dc4 100644 --- a/Modules/Filtering/FastBilateral/wrapping/test/CMakeLists.txt +++ b/Modules/Filtering/FastBilateral/wrapping/test/CMakeLists.txt @@ -1,2 +1,4 @@ -itk_python_expression_add_test(NAME itkFastBilateralImageFilterPythonTest - EXPRESSION "instance = itk.FastBilateralImageFilter.New()") +itk_python_expression_add_test( + NAME itkFastBilateralImageFilterPythonTest + EXPRESSION "instance = itk.FastBilateralImageFilter.New()" +) From d3a0668921b229f08a9f0ba9969ecacdf1a2e234 Mon Sep 17 00:00:00 2001 From: "Hans J. Johnson" Date: Tue, 28 Apr 2026 15:20:17 -0500 Subject: [PATCH 18/18] STYLE: Address greptile review feedback on ingested FastBilateral Apply tip-of-branch fixups for style/quality issues greptile flagged on upstream-inherited code, in keeping with the ingestion strategy of not rewriting upstream history for non-ghostflow concerns: - itkFastBilateralImageFilter.h: - template -> template - virtual ~Filter() {} -> ~Filter() override = default - drop redundant 'const' from itkGetConstMacro(DomainSigma, ...) - itkFastBilateralImageFilter.hxx: - mark immutable locals (padding, variance, maxWidth) const - itkFastBilateralImageFilterTest2.cxx: - return EXIT_FAILURE instead of -1 / -2 - fix misleading "Test itkSetVectorMacro" comment (the macro called is itkSetMacro on a fixed-size array) - itkFastBilateralImageFilterTest3.cxx: - return EXIT_FAILURE instead of -1 - move writer->Update() inside the try-catch block so I/O exceptions are reported the same way as filter exceptions --- .../include/itkFastBilateralImageFilter.h | 6 +++--- .../include/itkFastBilateralImageFilter.hxx | 6 +++--- .../test/itkFastBilateralImageFilterTest2.cxx | 6 +++--- .../test/itkFastBilateralImageFilterTest3.cxx | 18 +++++++++--------- 4 files changed, 18 insertions(+), 18 deletions(-) diff --git a/Modules/Filtering/FastBilateral/include/itkFastBilateralImageFilter.h b/Modules/Filtering/FastBilateral/include/itkFastBilateralImageFilter.h index b23e898602e..fa01afbc288 100644 --- a/Modules/Filtering/FastBilateral/include/itkFastBilateralImageFilter.h +++ b/Modules/Filtering/FastBilateral/include/itkFastBilateralImageFilter.h @@ -69,7 +69,7 @@ namespace itk * \todo Support for vector images */ -template +template class ITK_EXPORT FastBilateralImageFilter : public ImageToImageFilter { public: @@ -120,7 +120,7 @@ class ITK_EXPORT FastBilateralImageFilter : public ImageToImageFilter::GenerateData() // The amount of padding around the grid images, required so that // interpolation is not done outside of the grid during reconstruction - int padding = 2; + const int padding = 2; // Setup the higher dimensional grids (gridImage and gridWeight). { @@ -214,8 +214,8 @@ FastBilateralImageFilter::GenerateData() // This variance approximately corresponds to a 1D filter of [1 2 1] which is // used in Paris and Durands C++ implementation to blur their down-sampled // data. With this variance a kernel width larger than 5 is not necessary. - double variance = 1.59577; - int maxWidth = 5; + const double variance = 1.59577; + const int maxWidth = 5; // Setup the Gaussian filter typename BlurType::Pointer gridImageBlurFilter = BlurType::New(); diff --git a/Modules/Filtering/FastBilateral/test/itkFastBilateralImageFilterTest2.cxx b/Modules/Filtering/FastBilateral/test/itkFastBilateralImageFilterTest2.cxx index 5d4241cddd2..fc6b155aaba 100644 --- a/Modules/Filtering/FastBilateral/test/itkFastBilateralImageFilterTest2.cxx +++ b/Modules/Filtering/FastBilateral/test/itkFastBilateralImageFilterTest2.cxx @@ -54,7 +54,7 @@ itkFastBilateralImageFilterTest2(int ac, char * av[]) filter->SetRangeSigma(50.0); - // Test itkSetVectorMacro + // Test itkSetMacro with a fixed-size array double domainSigma[dimension]; for (unsigned int i = 0; i < dimension; i++) { @@ -74,12 +74,12 @@ itkFastBilateralImageFilterTest2(int ac, char * av[]) catch (itk::ExceptionObject & e) { std::cerr << "Exception detected: " << e.GetDescription(); - return -1; + return EXIT_FAILURE; } catch (...) { std::cerr << "Some other exception occurred" << std::endl; - return -2; + return EXIT_FAILURE; } // Generate test image diff --git a/Modules/Filtering/FastBilateral/test/itkFastBilateralImageFilterTest3.cxx b/Modules/Filtering/FastBilateral/test/itkFastBilateralImageFilterTest3.cxx index fc1c48edf54..7ddf887c343 100644 --- a/Modules/Filtering/FastBilateral/test/itkFastBilateralImageFilterTest3.cxx +++ b/Modules/Filtering/FastBilateral/test/itkFastBilateralImageFilterTest3.cxx @@ -34,7 +34,7 @@ itkFastBilateralImageFilterTest3(int ac, char * av[]) if (ac < 3) { std::cerr << "Usage: " << av[0] << " InputImage BaselineImage\n"; - return -1; + return EXIT_FAILURE; } using PixelType = unsigned char; @@ -70,23 +70,23 @@ itkFastBilateralImageFilterTest3(int ac, char * av[]) filter3->SetDomainSigma(4.0); filter3->SetRangeSigma(20.0); + // Generate test image + itk::ImageFileWriter::Pointer writer; + writer = itk::ImageFileWriter::New(); + writer->SetInput(filter3->GetOutput()); + writer->SetFileName(av[2]); + try { input->Update(); filter3->Update(); + writer->Update(); } catch (itk::ExceptionObject & e) { std::cerr << "Exception detected: " << e.GetDescription(); - return -1; + return EXIT_FAILURE; } - // Generate test image - itk::ImageFileWriter::Pointer writer; - writer = itk::ImageFileWriter::New(); - writer->SetInput(filter3->GetOutput()); - writer->SetFileName(av[2]); - writer->Update(); - return EXIT_SUCCESS; }