Ocean
FrameFilterPrewitt.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) Meta Platforms, Inc. and affiliates.
3  *
4  * This source code is licensed under the MIT license found in the
5  * LICENSE file in the root directory of this source tree.
6  */
7 
8 #ifndef META_OCEAN_CV_FRAME_FILTER_PREWITT_H
9 #define META_OCEAN_CV_FRAME_FILTER_PREWITT_H
10 
11 #include "ocean/cv/CV.h"
12 #include "ocean/cv/FrameChannels.h"
13 #include "ocean/cv/FrameFilter.h"
14 
15 #include "ocean/base/Worker.h"
16 
17 namespace Ocean
18 {
19 
20 namespace CV
21 {
22 
23 /**
24  * This class implements a Prewitt frame filter.
25  * The horizontal (0 degree) and vertical (90 degree - clockwise) 3x3 Prewitt box filter (not convolution filter) are defined as:
26  * <pre>
27  * horizontal: vertical (90 degree):
28  * | -1 0 1 | | -1 -1 -1 |
29  * | -1 0 1 | | 0 0 0 |
30  * | -1 0 1 | | 1 1 1 |
31  * </pre>
32  *
33  * The diagonal 3x3 Prewitt filters are defined as:
34  * <pre>
35  * 45 degree: 135 degree:
36  * | -1 -1 0 | | 0 -1 -1 |
37  * | -1 0 1 | | 1 0 -1 |
38  * | 0 1 1 | | 1 1 0 |
39  * </pre>
40  * @ingroup cv
41  */
42 class OCEAN_CV_EXPORT FrameFilterPrewitt : public FrameFilter
43 {
44  public:
45 
46  /**
47  * Horizontal and vertical Prewitt filter for images.
48  * If the target response data type is selected to be `int8_t`, each filter response is normalized by 1/6 to fit into the value range [-128, 127].<br>
49  * If the target response data type is selected to be `int16_t` no normalization will be applied.
50  * The border pixels are set to zero.
51  * @param source The source frame to which the Prewitt filter will be applied, with `tSourceChannels` channels, must be valid
52  * @param target The target response frame receiving the horizontal and vertical Prewitt responses, with `tSourceChannels * 2` channels, must be valid
53  * @param width The width of the frame in pixel, with range [3, infinity)
54  * @param height The height of the frame in pixel, with range [3, infinity)
55  * @param sourcePaddingElements Optional padding at the end of each source row in elements, with range [0, infinity)
56  * @param targetPaddingElements Optional padding at the end of each target row in elements, with range [0, infinity)
57  * @param worker Optional worker object to distribute the computational load
58  * @tparam TTarget The data type of the response values, either `int8_t` or `int16_t`
59  * @tparam tSourceChannels The number of channels of the source frame, with range [1, infinity)
60  */
61  template <typename TTarget, unsigned int tSourceChannels>
62  static inline void filterHorizontalVertical8BitPerChannel(const uint8_t* source, TTarget* target, const unsigned int width, const unsigned int height, const unsigned int sourcePaddingElements, const unsigned int targetPaddingElements, Worker* worker = nullptr);
63 
64  private:
65 
66  /**
67  * Applies the horizontal and vertical Prewitt filter to one row of a source frame.
68  * @param sourceRow The row of the source frame, must be valid
69  * @param targetRow The row of the target response frame, must be valid
70  * @param width The width of the source and target frame in pixel, with range [3, infinity)
71  * @param height The height of the source and target frame in pixel, with range [3, infinity)
72  * @param rowIndex The index of the row to which the filter is applied, with range [0, height - 1]
73  * @param sourceStrideElements The number of elements between the start of two consecutive source rows, with range [width * tSourceChannels, infinity)
74  * @param targetStrideElements The number of elements between the start of two consecutive target rows, with range [width * tTargetChannels, infinity)
75  * @tparam TSource The data type of the source frame, must be `uint8_t`
76  * @tparam TTarget The data type oft he target response frame, must be `int8_t` or `int16_t`
77  * @tparam tSourceChannels The number of channels the source frame has, with range [1, infinity)
78  * @tparam tTargetChannels The number of channels the target frame has, must be `tSourceChannels * 2`
79  */
80  template <typename TSource, typename TTarget, unsigned int tSourceChannels, unsigned int tTargetChannels>
81  static void filterHorizontalVerticalRow(const TSource* sourceRow, TTarget* targetRow, const unsigned int width, const unsigned int height, unsigned int rowIndex, const unsigned int sourceStrideElements, const unsigned int targetStrideElements);
82 };
83 
84 template <typename TTarget, unsigned int tSourceChannels>
85 inline void FrameFilterPrewitt::filterHorizontalVertical8BitPerChannel(const uint8_t* source, TTarget* target, const unsigned int width, const unsigned int height, const unsigned int sourcePaddingElements, const unsigned int targetPaddingElements, Worker* worker)
86 {
87  static_assert(std::is_same<TTarget, int8_t>::value || std::is_same<TTarget, int16_t>::value, "Invalid target data type!");
88  static_assert(tSourceChannels >= 1u, "Invalid channel number!");
89 
90  ocean_assert(source != nullptr && target != nullptr);
91  ocean_assert(width >= 3u && height >= 3u);
92 
93  //using TSource = uint8_t;
94  constexpr unsigned int tTargetChannels = tSourceChannels * 2u;
95 
96  FrameChannels::applyRowOperator<uint8_t, TTarget, tSourceChannels, tTargetChannels>(source, target, width, height, sourcePaddingElements, targetPaddingElements, &filterHorizontalVerticalRow<uint8_t, TTarget, tSourceChannels, tTargetChannels>, worker);
97 }
98 
99 template <typename TSource, typename TTarget, unsigned int tSourceChannels, unsigned int tTargetChannels>
100 void FrameFilterPrewitt::filterHorizontalVerticalRow(const TSource* sourceRow, TTarget* targetRow, const unsigned int width, const unsigned int height, unsigned int rowIndex, const unsigned int sourceStrideElements, const unsigned int /*targetStrideElements*/)
101 {
102  static_assert(std::is_same<TSource, uint8_t>::value, "Invalid source data type!");
103  static_assert(std::is_same<TTarget, int8_t>::value || std::is_same<TTarget, int16_t>::value, "Invalid target data type!");
104 
105  static_assert(tSourceChannels >= 1u, "Invalid source channel number!");
106  static_assert(tTargetChannels == tSourceChannels * 2u, "Invalid target channel number!");
107 
108  ocean_assert(width >= 3u && height >= 3u);
109 
110  if (rowIndex == 0u || rowIndex == height - 1u)
111  {
112  // setting the first row and last row to zero
113 
114  memset(targetRow, 0, width * tTargetChannels * sizeof(TTarget));
115  return;
116  }
117 
118  // setting first pixel to zero
119 
120  for (unsigned int n = 0u; n < tTargetChannels; ++n)
121  {
122  targetRow[n] = TTarget(0);
123  }
124 
125  targetRow += tTargetChannels;
126 
127  const uint8_t* source0 = sourceRow - sourceStrideElements;
128  const uint8_t* source1 = sourceRow;
129  const uint8_t* source2 = sourceRow + sourceStrideElements;
130 
131  for (unsigned int x = 1u; x < width - 1u; ++x)
132  {
133  if constexpr (std::is_same<TTarget, int8_t>::value)
134  {
135  for (unsigned int n = 0u; n < tSourceChannels; ++n)
136  {
137  // | -1 0 1 |
138  // | -1 0 1 |
139  // | -1 0 1 |
140  *targetRow++ = TTarget((*(source0 + tSourceChannels * 2u) - *(source0) + (*(source1 + tSourceChannels * 2u) - *(source1)) + *(source2 + tSourceChannels * 2u) - *(source2)) / 8);
141 
142  // | -1 -1 -1 |
143  // | 0 0 0 |
144  // | 1 1 1 |
145  *targetRow++ = TTarget((*(source2) + (*(source2 + tSourceChannels) - *(source0 + tSourceChannels)) + *(source2 + tSourceChannels * 2u) - *(source0) - *(source0 + tSourceChannels * 2u)) / 8);
146 
147  ++source0;
148  ++source1;
149  ++source2;
150  }
151  }
152  else
153  {
154  ocean_assert((std::is_same<TTarget, int16_t>::value));
155 
156  for (unsigned int n = 0u; n < tSourceChannels; ++n)
157  {
158  // | -1 0 1 |
159  // | -1 0 1 |
160  // | -1 0 1 |
161  *targetRow++ = TTarget(*(source0 + tSourceChannels * 2u) - *(source0) + (*(source1 + tSourceChannels * 2u) - *(source1)) + *(source2 + tSourceChannels * 2u) - *(source2));
162 
163  // | -1 -1 -1 |
164  // | 0 0 0 |
165  // | 1 1 1 |
166  *targetRow++ = TTarget(*(source2) + (*(source2 + tSourceChannels) - *(source0 + tSourceChannels)) + *(source2 + tSourceChannels * 2u) - *(source0) - *(source0 + tSourceChannels * 2u));
167 
168  ++source0;
169  ++source1;
170  ++source2;
171  }
172  }
173  }
174 
175  // setting last pixel to zero
176  for (unsigned int n = 0u; n < tTargetChannels; ++n)
177  {
178  targetRow[n] = TTarget(0);
179  }
180 }
181 
182 }
183 
184 }
185 
186 #endif // META_OCEAN_CV_FRAME_FILTER_PREWITT_H
This class implements the base class for all filter.
Definition: FrameFilter.h:29
This class implements a Prewitt frame filter.
Definition: FrameFilterPrewitt.h:43
static void filterHorizontalVertical8BitPerChannel(const uint8_t *source, TTarget *target, const unsigned int width, const unsigned int height, const unsigned int sourcePaddingElements, const unsigned int targetPaddingElements, Worker *worker=nullptr)
Horizontal and vertical Prewitt filter for images.
Definition: FrameFilterPrewitt.h:85
static void filterHorizontalVerticalRow(const TSource *sourceRow, TTarget *targetRow, const unsigned int width, const unsigned int height, unsigned int rowIndex, const unsigned int sourceStrideElements, const unsigned int targetStrideElements)
Applies the horizontal and vertical Prewitt filter to one row of a source frame.
Definition: FrameFilterPrewitt.h:100
This class implements a worker able to distribute function calls over different threads.
Definition: Worker.h:33
The namespace covering the entire Ocean framework.
Definition: Accessor.h:15