Skip to content

Commit a173b9d

Browse files
committed
1 parent a86e08f commit a173b9d

5 files changed

Lines changed: 622 additions & 0 deletions

File tree

Lines changed: 177 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
1+
/*=========================================================================
2+
*
3+
* Copyright NumFOCUS
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* https://www.apache.org/licenses/LICENSE-2.0.txt
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*
17+
*=========================================================================*/
18+
#ifndef itkStructuralSimilarityImageFilter_h
19+
#define itkStructuralSimilarityImageFilter_h
20+
#include "itkImageToImageFilter.h"
21+
#include "itkNumericTraits.h"
22+
#include "itkArray.h"
23+
namespace itk
24+
{
25+
/**
26+
* \class StructuralSimilarityImageFilter
27+
* \brief Computes the Structural Similarity Index Measure (SSIM) between two images.
28+
*
29+
* This filter computes the local SSIM map and an overall scalar SSIM value
30+
* between two input images. The SSIM is defined as:
31+
*
32+
* \f[
33+
* \text{SSIM}(x,y) = [l(x,y)]^{\alpha} \cdot [c(x,y)]^{\beta} \cdot [s(x,y)]^{\gamma}
34+
* \f]
35+
*
36+
* where
37+
* \f[
38+
* l(x,y) = \frac{2\mu_x\mu_y + C_1}{\mu_x^2 + \mu_y^2 + C_1}, \quad
39+
* c(x,y) = \frac{2\sigma_x\sigma_y + C_2}{\sigma_x^2 + \sigma_y^2 + C_2}, \quad
40+
* s(x,y) = \frac{\sigma_{xy} + C_3}{\sigma_x\sigma_y + C_3}
41+
* \f]
42+
*
43+
* with \f$C_1 = (K_1 L)^2\f$, \f$C_2 = (K_2 L)^2\f$, \f$C_3 = C_2 / 2\f$.
44+
* \f$L\f$ is the dynamic range (defaults to 255), and \f$K_1\f$ and \f$K_2\f$
45+
* are small stability constants (defaults 0.01 and 0.03 respectively).
46+
*
47+
* The exponents \f$\alpha\f$, \f$\beta\f$, and \f$\gamma\f$ control the
48+
* relative importance of luminance, contrast, and structure. With the default
49+
* values of 1.0 the formula simplifies to the standard SSIM:
50+
*
51+
* \f[
52+
* \text{SSIM}(x,y) = \frac{(2\mu_x\mu_y + C_1)(2\sigma_{xy} + C_2)}{(\mu_x^2 + \mu_y^2 + C_1)(\sigma_x^2 + \sigma_y^2 + C_2)}
53+
* \f]
54+
*
55+
* The output image contains the per-pixel SSIM map. The scalar mean SSIM
56+
* across all pixels can be retrieved with GetSSIM().
57+
*
58+
* The filter is N-dimensional and multi-threaded.
59+
*
60+
* \par Parameters
61+
* - Radius: neighborhood radius for local statistics (default: 1 in each dimension, giving a 3x3 window in 2D).
62+
* - LuminanceWeight (\f$\alpha\f$), ContrastWeight (\f$\beta\f$), StructureWeight (\f$\gamma\f$):
63+
* exponents for the three components (all default to 1.0).
64+
* - DynamicRange (\f$L\f$): range of pixel values (default: 255.0).
65+
* - K1, K2: stabilization constants (defaults: 0.01, 0.03).
66+
*
67+
* \sa SimilarityIndexImageFilter
68+
*
69+
* \ingroup ImageCompare
70+
* \ingroup ITKImageCompare
71+
*/
72+
template <typename TInputImage, typename TOutputImage = TInputImage>
73+
class ITK_TEMPLATE_EXPORT StructuralSimilarityImageFilter : public ImageToImageFilter<TInputImage, TOutputImage>
74+
{
75+
public:
76+
ITK_DISALLOW_COPY_AND_MOVE(StructuralSimilarityImageFilter);
77+
/** Standard class type aliases. */
78+
using Self = StructuralSimilarityImageFilter;
79+
using Superclass = ImageToImageFilter<TInputImage, TOutputImage>;
80+
using Pointer = SmartPointer<Self>;
81+
using ConstPointer = SmartPointer<const Self>;
82+
/** Method for creation through the object factory. */
83+
itkNewMacro(Self);
84+
/** \see LightObject::GetNameOfClass() */
85+
itkOverrideGetNameOfClassMacro(StructuralSimilarityImageFilter);
86+
/** Image type aliases. */
87+
using InputImageType = TInputImage;
88+
using OutputImageType = TOutputImage;
89+
using InputPixelType = typename InputImageType::PixelType;
90+
using OutputPixelType = typename OutputImageType::PixelType;
91+
using InputImageRegionType = typename InputImageType::RegionType;
92+
using OutputImageRegionType = typename OutputImageType::RegionType;
93+
using SizeType = typename InputImageType::SizeType;
94+
using IndexType = typename InputImageType::IndexType;
95+
static constexpr unsigned int ImageDimension = InputImageType::ImageDimension;
96+
/** Floating point type for computations. */
97+
using RealType = typename NumericTraits<InputPixelType>::RealType;
98+
/** Neighborhood radius type. */
99+
using RadiusType = SizeType;
100+
using RadiusValueType = typename RadiusType::SizeValueType;
101+
/** Set/Get the neighborhood radius for local statistics computation. */
102+
virtual void
103+
SetRadius(const RadiusType & radius);
104+
virtual void
105+
SetRadius(RadiusValueType radius);
106+
itkGetConstReferenceMacro(Radius, RadiusType);
107+
/** Set the first input image. */
108+
void
109+
SetInput1(const InputImageType * image)
110+
{
111+
this->SetInput(image);
112+
}
113+
/** Set the second input image. */
114+
void
115+
SetInput2(const InputImageType * image);
116+
/** Get the first input image. */
117+
const InputImageType *
118+
GetInput1() const
119+
{
120+
return this->GetInput(0);
121+
}
122+
/** Get the second input image. */
123+
const InputImageType *
124+
GetInput2() const;
125+
/** Set/Get the luminance exponent (alpha). Default: 1.0. */
126+
itkSetMacro(LuminanceWeight, RealType);
127+
itkGetConstMacro(LuminanceWeight, RealType);
128+
/** Set/Get the contrast exponent (beta). Default: 1.0. */
129+
itkSetMacro(ContrastWeight, RealType);
130+
itkGetConstMacro(ContrastWeight, RealType);
131+
/** Set/Get the structure exponent (gamma). Default: 1.0. */
132+
itkSetMacro(StructureWeight, RealType);
133+
itkGetConstMacro(StructureWeight, RealType);
134+
/** Set/Get the dynamic range L of the pixel values. Default: 255.0. */
135+
itkSetMacro(DynamicRange, RealType);
136+
itkGetConstMacro(DynamicRange, RealType);
137+
/** Set/Get the K1 stabilization constant. Default: 0.01. */
138+
itkSetMacro(K1, RealType);
139+
itkGetConstMacro(K1, RealType);
140+
/** Set/Get the K2 stabilization constant. Default: 0.03. */
141+
itkSetMacro(K2, RealType);
142+
itkGetConstMacro(K2, RealType);
143+
/** Get the computed mean SSIM value (available after Update()). */
144+
itkGetConstMacro(SSIM, RealType);
145+
itkConceptMacro(InputHasNumericTraitsCheck, (Concept::HasNumericTraits<InputPixelType>));
146+
protected:
147+
StructuralSimilarityImageFilter();
148+
~StructuralSimilarityImageFilter() override = default;
149+
void
150+
PrintSelf(std::ostream & os, Indent indent) const override;
151+
void
152+
GenerateInputRequestedRegion() override;
153+
void
154+
BeforeThreadedGenerateData() override;
155+
void
156+
AfterThreadedGenerateData() override;
157+
void
158+
DynamicThreadedGenerateData(const OutputImageRegionType & outputRegionForThread) override;
159+
private:
160+
RadiusType m_Radius{};
161+
RealType m_LuminanceWeight{ 1.0 };
162+
RealType m_ContrastWeight{ 1.0 };
163+
RealType m_StructureWeight{ 1.0 };
164+
RealType m_DynamicRange{ 255.0 };
165+
RealType m_K1{ 0.01 };
166+
RealType m_K2{ 0.03 };
167+
RealType m_SSIM{};
168+
/** Thread-local accumulators for computing the global mean SSIM. */
169+
std::mutex m_Mutex{};
170+
RealType m_AccumulatedSSIM{};
171+
SizeValueType m_PixelCount{};
172+
};
173+
} // end namespace itk
174+
#ifndef ITK_MANUAL_INSTANTIATION
175+
# include "itkStructuralSimilarityImageFilter.hxx"
176+
#endif
177+
#endif

0 commit comments

Comments
 (0)