Skip to content

Commit 1096547

Browse files
authored
Merge pull request InsightSoftwareConsortium#5688 from N-Dekker/Use-initializer-lists-SobelOperator
Use initializer lists, constexpr-if and switch in SobelOperator::GenerateCoefficients()
2 parents 1bd405d + 35d6a3d commit 1096547

File tree

3 files changed

+48
-167
lines changed

3 files changed

+48
-167
lines changed

Modules/Core/Common/include/itkSobelOperator.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,10 @@ class ITK_TEMPLATE_EXPORT SobelOperator : public NeighborhoodOperator<TPixel, VD
101101

102102
itkOverrideGetNameOfClassMacro(SobelOperator);
103103

104+
static_assert(
105+
VDimension == 2 || VDimension == 3,
106+
"The ND version of the Sobel operator has not been implemented. Currently only 2D and 3D versions are available.");
107+
104108
/** Creates the operator with length only in the specified direction.
105109
* The radius of the operator will be 0 except along the axis on which
106110
* the operator will work.

Modules/Core/Common/include/itkSobelOperator.hxx

Lines changed: 44 additions & 156 deletions
Original file line numberDiff line numberDiff line change
@@ -28,190 +28,78 @@ SobelOperator<TPixel, VDimension, TAllocator>::Fill(const CoefficientVector & co
2828
{
2929
this->InitializeToZero();
3030

31-
if constexpr (VDimension == 2 || VDimension == 3)
32-
{
33-
// Note that this code is only good for 2d and 3d operators. Places the
34-
// coefficients in the exact center of the neighborhood
35-
const unsigned int center = this->GetCenterNeighborhoodIndex();
31+
// Note that this code is only good for 2d and 3d operators. Places the
32+
// coefficients in the exact center of the neighborhood
33+
const unsigned int center = this->GetCenterNeighborhoodIndex();
3634

37-
if constexpr (VDimension == 3)
35+
if constexpr (VDimension == 2)
36+
{
37+
unsigned int coeff_index = 0;
38+
for (int y = -1; y <= 1; ++y)
3839
{
39-
unsigned int coeff_index = 0;
40-
for (int z = -1; z <= 1; ++z)
40+
for (int x = -1; x <= 1; ++x)
4141
{
42-
for (int y = -1; y <= 1; ++y)
43-
{
44-
for (int x = -1; x <= 1; ++x)
45-
{
46-
const int pos = center + z * this->GetStride(2) + y * this->GetStride(1) + x * this->GetStride(0);
47-
48-
this->operator[](pos) = static_cast<TPixel>(coeff[coeff_index]);
49-
50-
++coeff_index;
51-
}
52-
}
42+
const int pos = center + y * this->GetStride(1) + x * this->GetStride(0);
43+
// Note, The following line copies the double precision
44+
// coefficients of SobelOperator to the pixel type
45+
// of the neighborhood operator which may not support
46+
// negative numbers, or floating point numbers.
47+
this->operator[](pos) = static_cast<TPixel>(coeff[coeff_index]);
48+
49+
++coeff_index;
5350
}
5451
}
55-
else // So now VDimension == 2
52+
}
53+
if constexpr (VDimension == 3)
54+
{
55+
unsigned int coeff_index = 0;
56+
for (int z = -1; z <= 1; ++z)
5657
{
57-
unsigned int coeff_index = 0;
5858
for (int y = -1; y <= 1; ++y)
5959
{
6060
for (int x = -1; x <= 1; ++x)
6161
{
62-
const int pos = center + y * this->GetStride(1) + x * this->GetStride(0);
63-
// Note, The following line copies the double precision
64-
// coefficients of SobelOperator to the pixel type
65-
// of the neighborhood operator which may not support
66-
// negative numbers, or floating point numbers.
62+
const int pos = center + z * this->GetStride(2) + y * this->GetStride(1) + x * this->GetStride(0);
63+
6764
this->operator[](pos) = static_cast<TPixel>(coeff[coeff_index]);
6865

6966
++coeff_index;
7067
}
7168
}
7269
}
7370
}
74-
else
75-
{
76-
itkExceptionStringMacro("The ND version of the Sobel operator is not yet implemented. Currently only the 2D and "
77-
"3D versions are available.");
78-
}
7971
}
8072

8173
template <typename TPixel, unsigned int VDimension, typename TAllocator>
8274
auto
8375
SobelOperator<TPixel, VDimension, TAllocator>::GenerateCoefficients() -> CoefficientVector
8476
{
85-
CoefficientVector coeff;
86-
constexpr std::size_t coeff_size{ (VDimension == 2) ? 9 : 27 };
87-
coeff.reserve(coeff_size);
88-
if (VDimension == 2 && this->GetDirection() == 0)
89-
{
90-
coeff.push_back(-1.0);
91-
coeff.push_back(0.0);
92-
coeff.push_back(1.0);
93-
coeff.push_back(-2.0);
94-
coeff.push_back(0.0);
95-
coeff.push_back(2);
96-
coeff.push_back(-1.0);
97-
coeff.push_back(0.0);
98-
coeff.push_back(1.0);
99-
}
100-
else if (VDimension == 2 && this->GetDirection() == 1)
101-
{
102-
coeff.push_back(-1.0);
103-
coeff.push_back(-2);
104-
coeff.push_back(-1.0);
105-
coeff.push_back(0.0);
106-
coeff.push_back(0.0);
107-
coeff.push_back(0.0);
108-
coeff.push_back(1.0);
109-
coeff.push_back(2);
110-
coeff.push_back(1.0);
111-
}
112-
else if (VDimension == 3 && this->GetDirection() == 0)
113-
{
114-
coeff.push_back(-1.0);
115-
coeff.push_back(0.0);
116-
coeff.push_back(1.0);
117-
coeff.push_back(-3.0);
118-
coeff.push_back(0.0);
119-
coeff.push_back(3.0);
120-
coeff.push_back(-1.0);
121-
coeff.push_back(0.0);
122-
coeff.push_back(1.0);
123-
124-
coeff.push_back(-3.0);
125-
coeff.push_back(0.0);
126-
coeff.push_back(3.0);
127-
coeff.push_back(-6.0);
128-
coeff.push_back(0.0);
129-
coeff.push_back(6.0);
130-
coeff.push_back(-3.0);
131-
coeff.push_back(0.0);
132-
coeff.push_back(3.0);
77+
const unsigned int direction = this->GetDirection();
13378

134-
coeff.push_back(-1.0);
135-
coeff.push_back(0.0);
136-
coeff.push_back(1.0);
137-
coeff.push_back(-3.0);
138-
coeff.push_back(0.0);
139-
coeff.push_back(3.0);
140-
coeff.push_back(-1.0);
141-
coeff.push_back(0.0);
142-
coeff.push_back(1.0);
143-
}
144-
else if (VDimension == 3 && this->GetDirection() == 1)
145-
{
146-
coeff.push_back(-1.0);
147-
coeff.push_back(-3.0);
148-
coeff.push_back(-1.0);
149-
coeff.push_back(0.0);
150-
coeff.push_back(0.0);
151-
coeff.push_back(0.0);
152-
coeff.push_back(1.0);
153-
coeff.push_back(3.0);
154-
coeff.push_back(1.0);
155-
156-
coeff.push_back(-3.0);
157-
coeff.push_back(-6.0);
158-
coeff.push_back(-3.0);
159-
coeff.push_back(0.0);
160-
coeff.push_back(0.0);
161-
coeff.push_back(0.0);
162-
coeff.push_back(3.0);
163-
coeff.push_back(6.0);
164-
coeff.push_back(3.0);
165-
166-
coeff.push_back(-1.0);
167-
coeff.push_back(-3.0);
168-
coeff.push_back(-1.0);
169-
coeff.push_back(0.0);
170-
coeff.push_back(0.0);
171-
coeff.push_back(0.0);
172-
coeff.push_back(1.0);
173-
coeff.push_back(3.0);
174-
coeff.push_back(1.0);
175-
}
176-
else if (VDimension == 3 && this->GetDirection() == 2)
79+
if constexpr (VDimension == 2)
17780
{
178-
coeff.push_back(-1.0);
179-
coeff.push_back(-3.0);
180-
coeff.push_back(-1.0);
181-
coeff.push_back(-3.0);
182-
coeff.push_back(-6.0);
183-
coeff.push_back(-3.0);
184-
coeff.push_back(-1.0);
185-
coeff.push_back(-3.0);
186-
coeff.push_back(-1.0);
187-
188-
coeff.push_back(0.0);
189-
coeff.push_back(0.0);
190-
coeff.push_back(0.0);
191-
coeff.push_back(0.0);
192-
coeff.push_back(0.0);
193-
coeff.push_back(0.0);
194-
coeff.push_back(0.0);
195-
coeff.push_back(0.0);
196-
coeff.push_back(0.0);
197-
198-
coeff.push_back(1.0);
199-
coeff.push_back(3.0);
200-
coeff.push_back(1.0);
201-
coeff.push_back(3.0);
202-
coeff.push_back(6.0);
203-
coeff.push_back(3.0);
204-
coeff.push_back(1.0);
205-
coeff.push_back(3.0);
206-
coeff.push_back(1.0);
81+
switch (direction)
82+
{
83+
case 0:
84+
return { -1, 0, 1, -2, 0, 2, -1, 0, 1 };
85+
case 1:
86+
return { -1, -2, -1, 0, 0, 0, 1, 2, 1 };
87+
}
20788
}
208-
else
89+
if constexpr (VDimension == 3)
20990
{
210-
itkExceptionStringMacro("The ND version of the Sobel operator has not been implemented. Currently only 2D and 3D "
211-
"versions are available.");
91+
switch (direction)
92+
{
93+
case 0:
94+
return { -1, 0, 1, -3, 0, 3, -1, 0, 1, -3, 0, 3, -6, 0, 6, -3, 0, 3, -1, 0, 1, -3, 0, 3, -1, 0, 1 };
95+
case 1:
96+
return { -1, -3, -1, 0, 0, 0, 1, 3, 1, -3, -6, -3, 0, 0, 0, 3, 6, 3, -1, -3, -1, 0, 0, 0, 1, 3, 1 };
97+
case 2:
98+
return { -1, -3, -1, -3, -6, -3, -1, -3, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 3, 1, 3, 6, 3, 1, 3, 1 };
99+
}
212100
}
213-
214-
return coeff;
101+
itkExceptionMacro("The direction value (" << direction << ") should be less than the dimensionality (" << VDimension
102+
<< ").");
215103
}
216104
} // namespace itk
217105

Modules/Core/Common/test/itkSobelOperatorTest.cxx

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@ itkSobelOperatorTest(int, char *[])
2626

2727
constexpr unsigned int Dimension2D{ 2 };
2828
constexpr unsigned int Dimension3D{ 3 };
29-
constexpr unsigned int Dimension4D{ 4 };
3029

3130
using PixelType = float;
3231

@@ -132,16 +131,6 @@ itkSobelOperatorTest(int, char *[])
132131
}
133132
}
134133

135-
{
136-
using SobelOperatorType = itk::SobelOperator<PixelType, Dimension4D>;
137-
SobelOperatorType sobelOperator;
138-
139-
constexpr unsigned long direction{ 0 };
140-
sobelOperator.SetDirection(direction);
141-
auto radius = itk::Size<Dimension4D>::Filled(1);
142-
ITK_TRY_EXPECT_EXCEPTION(sobelOperator.CreateToRadius(radius));
143-
}
144-
145134
std::cout << "Test finished." << std::endl;
146135
return EXIT_SUCCESS;
147136
}

0 commit comments

Comments
 (0)