Line | Branch | Exec | Source |
---|---|---|---|
1 | // SPDX-FileCopyrightText: 2023 - 2025 Arm Limited and/or its affiliates <open-source-office@arm.com> | ||
2 | // | ||
3 | // SPDX-License-Identifier: Apache-2.0 | ||
4 | |||
5 | #include "kleidicv/ctypes.h" | ||
6 | #include "kleidicv/filters/filter_2d_neon.h" | ||
7 | #include "kleidicv/filters/median_blur.h" | ||
8 | #include "kleidicv/filters/process_filter_2d.h" | ||
9 | #include "kleidicv/kleidicv.h" | ||
10 | #include "kleidicv/neon.h" | ||
11 | #include "kleidicv/workspace/border_3x3.h" | ||
12 | #include "kleidicv/workspace/border_5x5.h" | ||
13 | #include "kleidicv/workspace/border_7x7.h" | ||
14 | #include "median_blur_sorting_network_3x3.h" | ||
15 | #include "median_blur_sorting_network_5x5.h" | ||
16 | #include "median_blur_sorting_network_7x7.h" | ||
17 | |||
18 | namespace kleidicv::neon { | ||
19 | |||
20 | // Primary template for Median Blur filters. | ||
21 | template <typename ScalarType, size_t KernelSize> | ||
22 | class MedianBlurSortingNetwork; | ||
23 | |||
24 | template <typename ScalarType> | ||
25 | class VectorizedComparator { | ||
26 | public: | ||
27 | using SourceVectorType = typename VecTraits<ScalarType>::VectorType; | ||
28 | |||
29 | 4255498 | static void compare_and_swap(SourceVectorType& left, SourceVectorType& right, | |
30 | Monostate&) { | ||
31 | 4255498 | SourceVectorType max_value = vmaxq(left, right); | |
32 | 4255498 | SourceVectorType min_value = vminq(left, right); | |
33 | 4255498 | left = min_value; | |
34 | 4255498 | right = max_value; | |
35 | 4255498 | } | |
36 | |||
37 | 470532 | static void min(SourceVectorType& left, SourceVectorType& right, Monostate&) { | |
38 | 470532 | left = vminq(left, right); | |
39 | 470532 | } | |
40 | |||
41 | 456960 | static void max(SourceVectorType& left, SourceVectorType& right, Monostate&) { | |
42 | 456960 | right = vmaxq(left, right); | |
43 | 456960 | } | |
44 | 16064 | static SourceVectorType get_min(SourceVectorType& left, | |
45 | SourceVectorType& right, Monostate&) { | ||
46 | 16064 | return vminq(left, right); | |
47 | } | ||
48 | 16064 | static SourceVectorType get_max(SourceVectorType& left, | |
49 | SourceVectorType& right, Monostate&) { | ||
50 | 16064 | return vmaxq(left, right); | |
51 | } | ||
52 | }; | ||
53 | |||
54 | template <typename ScalarType> | ||
55 | class ScalarComparator { | ||
56 | public: | ||
57 | 15767992 | static void compare_and_swap(ScalarType& left, ScalarType& right, | |
58 | Monostate&) { | ||
59 |
14/14✓ Branch 0 taken 1125597 times.
✓ Branch 1 taken 636683 times.
✓ Branch 2 taken 1755194 times.
✓ Branch 3 taken 994482 times.
✓ Branch 4 taken 1680122 times.
✓ Branch 5 taken 968778 times.
✓ Branch 6 taken 1679672 times.
✓ Branch 7 taken 969228 times.
✓ Branch 8 taken 1117913 times.
✓ Branch 9 taken 639447 times.
✓ Branch 10 taken 1115893 times.
✓ Branch 11 taken 641467 times.
✓ Branch 12 taken 1555010 times.
✓ Branch 13 taken 888506 times.
|
15767992 | if (left > right) { |
60 | 5738591 | std::swap(left, right); | |
61 | 5738591 | } | |
62 | 15767992 | } | |
63 | |||
64 | 1702384 | static void min(ScalarType& left, ScalarType& right, Monostate&) { | |
65 | 1702384 | left = std::min(left, right); | |
66 | 1702384 | } | |
67 | |||
68 | 1648288 | static void max(ScalarType& left, ScalarType& right, Monostate&) { | |
69 | 1648288 | right = std::max(left, right); | |
70 | 1648288 | } | |
71 | 34560 | static ScalarType get_min(ScalarType& left, ScalarType& right, Monostate&) { | |
72 | 34560 | return std::min(left, right); | |
73 | } | ||
74 | 34560 | static ScalarType get_max(ScalarType& left, ScalarType& right, Monostate&) { | |
75 | 34560 | return std::max(left, right); | |
76 | } | ||
77 | }; | ||
78 | |||
79 | // Template for Median Blur 3x3 filters. | ||
80 | template <typename ScalarType> | ||
81 | class MedianBlurSortingNetwork<ScalarType, 3> { | ||
82 | public: | ||
83 | using SourceType = ScalarType; | ||
84 | using DestinationType = SourceType; | ||
85 | using SourceVectorType = typename VecTraits<SourceType>::VectorType; | ||
86 | using DestinationVectorType = typename VecTraits<DestinationType>::VectorType; | ||
87 | |||
88 | template <typename KernelWindowFunctor> | ||
89 | 1076 | void vector_path(KernelWindowFunctor& KernelWindow, | |
90 | DestinationVectorType& output_vec) const { | ||
91 | 1076 | Monostate ctx; | |
92 | 1076 | sorting_network3x3_single_row<VectorizedComparator<ScalarType>>( | |
93 | 1076 | KernelWindow, output_vec, ctx); | |
94 | 1076 | } | |
95 | |||
96 | template <typename KernelWindowFunctor> | ||
97 | 3478 | void vector_path_for_dual_row_handling( | |
98 | KernelWindowFunctor& KernelWindow, DestinationVectorType& output_vec_0, | ||
99 | DestinationVectorType& output_vec_1) const { | ||
100 | 3478 | Monostate ctx; | |
101 | 3478 | sorting_network3x3_dual_rows<VectorizedComparator<ScalarType>>( | |
102 | 3478 | KernelWindow, output_vec_0, output_vec_1, ctx); | |
103 | 3478 | } | |
104 | |||
105 | template <typename KernelWindowFunctor> | ||
106 | 1168 | void scalar_path(KernelWindowFunctor& KernelWindow, | |
107 | DestinationType& output_vec) const { | ||
108 | 1168 | Monostate ctx; | |
109 | 1168 | sorting_network3x3_single_row<ScalarComparator<ScalarType>>( | |
110 | 1168 | KernelWindow, output_vec, ctx); | |
111 | 1168 | } | |
112 | |||
113 | template <typename KernelWindowFunctor> | ||
114 | 8056 | void scalar_path_for_dual_row_handling(KernelWindowFunctor& KernelWindow, | |
115 | DestinationType& output_vec0, | ||
116 | DestinationType& output_vec1) const { | ||
117 | 8056 | Monostate ctx; | |
118 | 8056 | sorting_network3x3_dual_rows<ScalarComparator<ScalarType>>( | |
119 | 8056 | KernelWindow, output_vec0, output_vec1, ctx); | |
120 | 8056 | } | |
121 | }; // end of class MedianBlurSortingNetwork<ScalarType, 3> | ||
122 | |||
123 | // Template for Median Blur 5x5 filters. | ||
124 | template <typename ScalarType> | ||
125 | class MedianBlurSortingNetwork<ScalarType, 5> { | ||
126 | public: | ||
127 | using SourceType = ScalarType; | ||
128 | using DestinationType = SourceType; | ||
129 | using SourceVectorType = typename VecTraits<SourceType>::VectorType; | ||
130 | using DestinationVectorType = typename VecTraits<DestinationType>::VectorType; | ||
131 | |||
132 | template <typename KernelWindowFunctor> | ||
133 | 11308 | void vector_path(KernelWindowFunctor& KernelWindow, | |
134 | DestinationVectorType& output_vec) const { | ||
135 | 11308 | Monostate ctx; | |
136 | 22616 | sorting_network5x5<VectorizedComparator<ScalarType>>(KernelWindow, | |
137 | 11308 | output_vec, ctx); | |
138 | 11308 | } | |
139 | |||
140 | template <typename KernelWindowFunctor> | ||
141 | 32136 | void scalar_path(KernelWindowFunctor& KernelWindow, | |
142 | DestinationType& dst) const { | ||
143 | 32136 | Monostate ctx; | |
144 | 32136 | sorting_network5x5<ScalarComparator<ScalarType>>(KernelWindow, dst, ctx); | |
145 | 32136 | } | |
146 | }; // end of class MedianBlurSortingNetwork<ScalarType, 5> | ||
147 | |||
148 | // Template for Median Blur 7x7 filters. | ||
149 | template <typename ScalarType> | ||
150 | class MedianBlurSortingNetwork<ScalarType, 7> { | ||
151 | public: | ||
152 | using SourceType = ScalarType; | ||
153 | using DestinationType = SourceType; | ||
154 | using SourceVectorType = typename VecTraits<SourceType>::VectorType; | ||
155 | using DestinationVectorType = typename VecTraits<DestinationType>::VectorType; | ||
156 | |||
157 | template <typename KernelWindowFunctor> | ||
158 | 13572 | void vector_path(KernelWindowFunctor& KernelWindow, | |
159 | DestinationVectorType& dst) const { | ||
160 | 13572 | Monostate ctx; | |
161 | 13572 | sorting_network7x7<VectorizedComparator<ScalarType>>(KernelWindow, dst, | |
162 | ctx); | ||
163 | 13572 | } | |
164 | |||
165 | template <typename KernelWindowFunctor> | ||
166 | 54096 | void scalar_path(KernelWindowFunctor& KernelWindow, | |
167 | DestinationType& dst) const { | ||
168 | 54096 | Monostate ctx; | |
169 | 54096 | sorting_network7x7<ScalarComparator<ScalarType>>(KernelWindow, dst, ctx); | |
170 | 54096 | } | |
171 | }; // end of class MedianBlurSortingNetworkSortingNetwork<ScalarType, 7> | ||
172 | |||
173 | template <typename T> | ||
174 | 1610 | kleidicv_error_t median_blur_sorting_network_stripe( | |
175 | const T* src, size_t src_stride, T* dst, size_t dst_stride, size_t width, | ||
176 | size_t height, size_t y_begin, size_t y_end, size_t channels, | ||
177 | size_t kernel_width, [[maybe_unused]] size_t kernel_height, | ||
178 | FixedBorderType border_type) { | ||
179 | 1610 | Rectangle rect{width, height}; | |
180 | 1610 | Rows<const T> src_rows{src, src_stride, channels}; | |
181 | 1610 | Rows<T> dst_rows{dst, dst_stride, channels}; | |
182 | |||
183 |
14/14✓ Branch 0 taken 64 times.
✓ Branch 1 taken 130 times.
✓ Branch 2 taken 98 times.
✓ Branch 3 taken 159 times.
✓ Branch 4 taken 98 times.
✓ Branch 5 taken 159 times.
✓ Branch 6 taken 98 times.
✓ Branch 7 taken 159 times.
✓ Branch 8 taken 64 times.
✓ Branch 9 taken 130 times.
✓ Branch 10 taken 64 times.
✓ Branch 11 taken 130 times.
✓ Branch 12 taken 98 times.
✓ Branch 13 taken 159 times.
|
1610 | if (kernel_width == 3) { |
184 | 584 | MedianBlurSortingNetwork<T, 3> median_filter; | |
185 | 584 | Filter2D3x3<MedianBlurSortingNetwork<T, 3>> filter{median_filter}; | |
186 | 1168 | process_filter2d_by_dual_rows(rect, y_begin, y_end, src_rows, dst_rows, | |
187 | 584 | border_type, filter); | |
188 | 584 | return KLEIDICV_OK; | |
189 | 584 | } | |
190 | |||
191 |
14/14✓ Branch 0 taken 66 times.
✓ Branch 1 taken 64 times.
✓ Branch 2 taken 84 times.
✓ Branch 3 taken 75 times.
✓ Branch 4 taken 84 times.
✓ Branch 5 taken 75 times.
✓ Branch 6 taken 84 times.
✓ Branch 7 taken 75 times.
✓ Branch 8 taken 66 times.
✓ Branch 9 taken 64 times.
✓ Branch 10 taken 66 times.
✓ Branch 11 taken 64 times.
✓ Branch 12 taken 84 times.
✓ Branch 13 taken 75 times.
|
1026 | if (kernel_width == 5) { |
192 | 534 | MedianBlurSortingNetwork<T, 5> median_filter; | |
193 | 534 | Filter2D5x5<MedianBlurSortingNetwork<T, 5>> filter{median_filter}; | |
194 | 1068 | process_filter2d(rect, y_begin, y_end, src_rows, dst_rows, border_type, | |
195 | 534 | filter); | |
196 | 534 | return KLEIDICV_OK; | |
197 | 534 | } | |
198 | |||
199 | 492 | MedianBlurSortingNetwork<T, 7> median_filter; | |
200 | 492 | Filter2D7x7<MedianBlurSortingNetwork<T, 7>> filter{median_filter}; | |
201 | 984 | process_filter2d(rect, y_begin, y_end, src_rows, dst_rows, border_type, | |
202 | 492 | filter); | |
203 | 492 | return KLEIDICV_OK; | |
204 | 1610 | } | |
205 | |||
206 | #define KLEIDICV_INSTANTIATE_TEMPLATE(type) \ | ||
207 | template KLEIDICV_TARGET_FN_ATTRS kleidicv_error_t \ | ||
208 | median_blur_sorting_network_stripe<type>( \ | ||
209 | const type* src, size_t src_stride, type* dst, size_t dst_stride, \ | ||
210 | size_t width, size_t height, size_t y_begin, size_t y_end, \ | ||
211 | size_t channels, size_t kernel_width, size_t kernel_height, \ | ||
212 | FixedBorderType border_type) | ||
213 | |||
214 | KLEIDICV_INSTANTIATE_TEMPLATE(int8_t); | ||
215 | KLEIDICV_INSTANTIATE_TEMPLATE(uint8_t); | ||
216 | KLEIDICV_INSTANTIATE_TEMPLATE(int16_t); | ||
217 | KLEIDICV_INSTANTIATE_TEMPLATE(uint16_t); | ||
218 | KLEIDICV_INSTANTIATE_TEMPLATE(int32_t); | ||
219 | KLEIDICV_INSTANTIATE_TEMPLATE(uint32_t); | ||
220 | KLEIDICV_INSTANTIATE_TEMPLATE(float); | ||
221 | |||
222 | } // namespace kleidicv::neon | ||
223 |