Ocean
FrameFilterMedian.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_MEDIAN_H
9 #define META_OCEAN_CV_FRAME_FILTER_MEDIAN_H
10 
11 #include "ocean/cv/CV.h"
13 
14 #include "ocean/base/Frame.h"
15 #include "ocean/base/Median.h"
16 #include "ocean/base/Memory.h"
17 #include "ocean/base/Worker.h"
18 
19 #include "ocean/math/Numeric.h"
20 
21 namespace Ocean
22 {
23 
24 namespace CV
25 {
26 
27 /**
28  * This class implements a median filter.
29  * @ingroup cv
30  */
31 class OCEAN_CV_EXPORT FrameFilterMedian : protected FrameFilterSorted
32 {
33  public:
34 
35  /**
36  * The following comfort class provides comfortable functions simplifying prototyping applications but also increasing binary size of the resulting applications.
37  * Best practice is to avoid using these functions if binary size matters,<br>
38  * as for every comfort function a corresponding function exists with specialized functionality not increasing binary size significantly.<br>
39  */
40  class OCEAN_CV_EXPORT Comfort
41  {
42  public:
43 
44  /**
45  * Filters a frame with a median filter with arbitrary size (a square patch).
46  * @param source The source image to be filtered, must be valid
47  * @param target The target frame with same size and pixel format receiving the filtered result, must be valid
48  * @param filterSize Size of the filter edge in pixel, must be odd with range [1, infinity)
49  * @param worker Optional worker object to distribute the computation
50  * @return True, if succeeded
51  */
52  static bool filter(const Frame& source, Frame& target, const unsigned int filterSize, Worker* worker);
53 
54  /**
55  * Filters a frame with a median filter with arbitrary size (a square patch).
56  * @param frame The image to be filtered, must be valid
57  * @param filterSize Size of the filter edge in pixel, must be odd with range [1, infinity)
58  * @param worker Optional worker object to distribute the computation
59  * @return True, if succeeded
60  */
61  static bool filter(Frame& frame, const unsigned int filterSize, Worker* worker);
62  };
63 
64  public:
65 
66  /**
67  * Filters a frame with a median filter with arbitrary size (a square patch).
68  * @param source The source image to be filtered, must be valid
69  * @param target The target frame with same size and pixel format receiving the filtered result, must be valid
70  * @param width The width of the input frame in pixel, with range [filterSize / 2, infinity)
71  * @param height The height of the input frame in pixel, with range [filterSize / 2, infinity)
72  * @param sourcePaddingElements The number of padding elements at the end of each source row, in elements, with range [0, infinity)
73  * @param targetPaddingElements The number of padding elements at the end of each target row, in elements, with range [0, infinity)
74  * @param filterSize Size of the filter edge in pixel, must be odd with range [1, infinity)
75  * @param worker Optional worker object to distribute the computation
76  * @tparam T Data type of the data elements
77  * @tparam tChannels Number of data channels, with range [1, infinity)
78  */
79  template <typename T, unsigned int tChannels>
80  static void filter(const T* source, T* target, const unsigned int width, const unsigned int height, const unsigned int sourcePaddingElements, const unsigned int targetPaddingElements, const unsigned int filterSize, Worker* worker = nullptr);
81 
82  /**
83  * Filters a frame with a median filter with arbitrary size (a square patch).
84  * @param frame The image to be filtered, must be valid
85  * @param width The width of the input frame in pixel, with range [filterSize / 2, infinity)
86  * @param height The height of the input frame in pixel, with range [filterSize / 2, infinity)
87  * @param framePaddingElements The number of padding elements at the end of each frame row, in elements, with range [0, infinity)
88  * @param filterSize Size of the filter edge in pixel, must be odd with range [1, infinity)
89  * @param worker Optional worker object to distribute the computation
90  * @tparam T Data type of the data elements
91  * @tparam tChannels Number of data channels, with range [1, infinity)
92  */
93  template <typename T, unsigned int tChannels>
94  static void filter(T* frame, const unsigned int width, const unsigned int height, const unsigned int framePaddingElements, const unsigned int filterSize, Worker* worker = nullptr);
95 
96  protected:
97 
98  /**
99  * Filters a subset of an integer frame with a median filter with arbitrary size.
100  * @param source The source image to be filtered, must be valid
101  * @param target The target frame with same size and pixel format receiving the filtered result, must be valid
102  * @param width The width of the input frame in pixel, with range [filterSize / 2, infinity)
103  * @param height The height of the input frame in pixel, with range [filterSize / 2, infinity)
104  * @param sourcePaddingElements The number of padding elements at the end of each source row, in elements, with range [0, infinity)
105  * @param targetPaddingElements The number of padding elements at the end of each target row, in elements, with range [0, infinity)
106  * @param filterSize Size of the filter edge in pixel, must be odd with range [1, infinity)
107  * @param firstRow First row to be handled, with range [0, height - 1]
108  * @param numberRows Number of rows to be handled, with range [1, height - firstRow]
109  * @tparam T Data type of the data elements, must be an integer data type
110  * @tparam tChannels Number of data channels, with range [1, infinity)
111  */
112  template <typename T, unsigned int tChannels, typename THistogram>
113  static void filterIntegerSubset(const T* source, T* target, const unsigned int width, const unsigned int height, const unsigned int sourcePaddingElements, const unsigned int targetPaddingElements, const unsigned int filterSize, const unsigned int firstRow, const unsigned int numberRows);
114 
115  /**
116  * Filters a subset of a floating point frame with a median filter with arbitrary size.
117  * @param source The source image to be filtered, must be valid
118  * @param target The target frame with same size and pixel format receiving the filtered result, must be valid
119  * @param width The width of the input frame in pixel, with range [filterSize / 2, infinity)
120  * @param height The height of the input frame in pixel, with range [filterSize / 2, infinity)
121  * @param sourcePaddingElements The number of padding elements at the end of each source row, in elements, with range [0, infinity)
122  * @param targetPaddingElements The number of padding elements at the end of each target row, in elements, with range [0, infinity)
123  * @param filterSize Size of the filter edge in pixel, must be odd with range [1, infinity)
124  * @param firstRow First row to be handled, with range [0, height - 1]
125  * @param numberRows Number of rows to be handled, with range [1, height - firstRow]
126  * @tparam T Data type of the data elements, must be a valid data type
127  * @tparam tChannels Number of data channels, with range [1, infinity)
128  */
129  template <typename T, unsigned int tChannels>
130  static void filterFloatSubset(const T* source, T* target, const unsigned int width, const unsigned int height, const unsigned int sourcePaddingElements, const unsigned int targetPaddingElements, const unsigned int filterSize, const unsigned int firstRow, const unsigned int numberRows);
131 };
132 
133 template <typename T, unsigned int tChannels>
134 void FrameFilterMedian::filter(const T* source, T* target, const unsigned int width, const unsigned int height, const unsigned int sourcePaddingElements, const unsigned int targetPaddingElements, const unsigned int filterSize, Worker* worker)
135 {
136  static_assert(tChannels != 0u, "Invalid channel number!");
137 
138  ocean_assert(source != nullptr && target != nullptr && source != target);
139  ocean_assert(filterSize / 2u <= width && filterSize / 2u <= height);
140 
141  if constexpr (std::is_floating_point<T>::value || sizeof(T) > sizeof(uint16_t))
142  {
143  if (worker)
144  {
145  worker->executeFunction(Worker::Function::createStatic(&filterFloatSubset<T, tChannels>, source, target, width, height, sourcePaddingElements, targetPaddingElements, filterSize, 0u, 0u), 0u, height, 7u, 8u, 20u);
146  }
147  else
148  {
149  filterFloatSubset<T, tChannels>(source, target, width, height, sourcePaddingElements, targetPaddingElements, filterSize, 0u, height);
150  }
151  }
152  else
153  {
154  ocean_assert(uint64_t(filterSize * filterSize) < uint64_t(NumericT<uint16_t>::maxValue()));
155 
156  constexpr size_t histogramElements = 1 << sizeof(T) * 8;
157 
158  ocean_assert(sizeof(T) != sizeof(uint8_t) || histogramElements == 256);
159  ocean_assert(sizeof(T) != sizeof(uint16_t) || histogramElements == 65536);
160 
162 
163  if (worker)
164  {
165  worker->executeFunction(Worker::Function::createStatic(&filterIntegerSubset<T, tChannels, Histogram>, source, target, width, height, sourcePaddingElements, targetPaddingElements, filterSize, 0u, 0u), 0u, height, 7u, 8u, 20u);
166  }
167  else
168  {
169  filterIntegerSubset<T, tChannels, Histogram>(source, target, width, height, sourcePaddingElements, targetPaddingElements, filterSize, 0u, height);
170  }
171  }
172 }
173 
174 template <typename T, unsigned int tChannels>
175 void FrameFilterMedian::filter(T* frame, const unsigned int width, const unsigned int height, const unsigned int framePaddingElements, const unsigned int filterSize, Worker* worker)
176 {
177  static_assert(tChannels != 0u, "Invalid channel number!");
178 
179  ocean_assert(frame != nullptr);
180  ocean_assert(filterSize / 2u <= width && filterSize / 2u <= height);
181 
182  Memory memory(width * height * sizeof(T) * tChannels);
183 
184  constexpr unsigned int memoryPaddingElements = 0u;
185  filter<T, tChannels>(frame, memory.data<T>(), width, height, framePaddingElements, memoryPaddingElements, filterSize, worker);
186 
187  if (framePaddingElements == 0u)
188  {
189  memcpy(frame, memory.data(), memory.size());
190  }
191  else
192  {
193  const T* memoryData = memory.data<T>();
194 
195  for (unsigned int y = 0u; y < height; ++y)
196  {
197  memcpy(frame, memoryData, width * tChannels * sizeof(T));
198 
199  frame += width * tChannels + framePaddingElements;
200  memoryData += width * tChannels + memoryPaddingElements;
201  }
202  }
203 }
204 
205 template <typename T, unsigned int tChannels, typename THistogram>
206 void FrameFilterMedian::filterIntegerSubset(const T* source, T* target, const unsigned int width, const unsigned int height, const unsigned int sourcePaddingElements, const unsigned int targetPaddingElements, const unsigned int filterSize, const unsigned int firstRow, const unsigned int numberRows)
207 {
208  static_assert(!std::is_floating_point<T>::value, "Invalid data type!");
209  static_assert(tChannels != 0u, "Invalid channel number");
210 
211  ocean_assert(source != nullptr && target != nullptr);
212 
213  ocean_assert(filterSize >= 3u && filterSize % 2u == 1u);
214 
215  const unsigned int filterSize_2 = filterSize / 2u;
216  ocean_assert(filterSize_2 <= width && filterSize_2 <= height);
217 
218  const unsigned int endRow = firstRow + numberRows;
219 
220  const unsigned int sourceStrideElements = width * tChannels + sourcePaddingElements;
221  const unsigned int targetStrideElements = width * tChannels + targetPaddingElements;
222 
223  THistogram medianHistograms[tChannels];
224 
225  // fill initial histogram
226 
227  for (unsigned int y = clampLower(firstRow, filterSize_2); y <= clampUpper(firstRow, filterSize_2, height); ++y)
228  {
229  const T* sourceRow = source + y * sourceStrideElements;
230 
231  for (unsigned int x = 0u; x <= filterSize_2; ++x)
232  {
233  for (unsigned int n = 0u; n < tChannels; ++n)
234  {
235  medianHistograms[n].pushValue(*sourceRow++);
236  }
237  }
238  }
239 
240  ocean_assert(medianHistograms[0].values() >= (filterSize_2 + 1u) * (filterSize_2 + 1u));
241  ocean_assert(medianHistograms[0].values() <= (filterSize_2 + 1u) * filterSize);
242 
243  THistogram previousMedianHistograms[tChannels];
244 
245  for (unsigned int y = firstRow; y < endRow; ++y)
246  {
247  T* targetRow = target + y * targetStrideElements;
248 
249  // making a copy which we can use when we start with the next row
250  for (unsigned int n = 0u; n < tChannels; ++n)
251  {
252  previousMedianHistograms[n] = medianHistograms[n];
253  }
254 
255  for (unsigned int x = 0u; x < width; ++x)
256  {
257  for (unsigned int n = 0u; n < tChannels; ++n)
258  {
259  ocean_assert(medianHistograms[n]);
260  *targetRow++ = medianHistograms[n].medianValue();
261  }
262 
263  if (x != width - 1u)
264  {
265  ocean_assert(x + 1u < width);
266 
267  // horizontal histogram update
268 
269  for (unsigned int yy = clampLower(y, filterSize_2); yy <= clampUpper(y, filterSize_2, height); ++yy)
270  {
271  const T* sourceRow = source + yy * sourceStrideElements;
272 
273  const unsigned int xxLeft = x - filterSize_2;
274  const unsigned int xxRight = x + filterSize_2 + 1u;
275 
276  if (xxLeft < width) // handling negative cases: int(xxLeft) < 0
277  {
278  for (unsigned int n = 0u; n < tChannels; ++n)
279  {
280  const T popValue = sourceRow[xxLeft * tChannels + n];
281 
282  ocean_assert(medianHistograms[n].hasValue(popValue));
283  medianHistograms[n].popValue(popValue);
284  }
285  }
286 
287  if (xxRight < width)
288  {
289  for (unsigned int n = 0u; n < tChannels; ++n)
290  {
291  const T pushValue = sourceRow[xxRight * tChannels + n];
292 
293  medianHistograms[n].pushValue(pushValue);
294  }
295  }
296  }
297  }
298 
299  ocean_assert(medianHistograms[0].values() <= filterSize * filterSize);
300  }
301 
302  if (y != endRow - 1u)
303  {
304  ocean_assert(y + 1u < endRow);
305 
306  // vertical histogram update at the beginning of the row
307 
308  for (unsigned int n = 0u; n < tChannels; ++n)
309  {
310  medianHistograms[n] = previousMedianHistograms[n];
311  }
312 
313  const unsigned int yyTop = y - filterSize_2;
314  const unsigned int yyBottom = y + filterSize_2 + 1u;
315 
316  if (yyTop < height) // handling negative cases: int(yyTop) < 0
317  {
318  const T* sourceRow = source + yyTop * sourceStrideElements;
319 
320  for (unsigned int x = 0u; x <= filterSize_2; ++x)
321  {
322  for (unsigned int n = 0u; n < tChannels; ++n)
323  {
324  const T popValue = sourceRow[x * tChannels + n];
325 
326  ocean_assert(medianHistograms[n].hasValue(popValue));
327  medianHistograms[n].popValue(popValue);
328  }
329  }
330  }
331 
332  if (yyBottom < height)
333  {
334  const T* sourceRow = source + yyBottom * sourceStrideElements;
335 
336  for (unsigned int x = 0u; x <= filterSize_2; ++x)
337  {
338  for (unsigned int n = 0u; n < tChannels; ++n)
339  {
340  const T pushValue = sourceRow[x * tChannels + n];
341 
342  medianHistograms[n].pushValue(pushValue);
343  }
344  }
345  }
346  }
347  }
348 }
349 
350 #if 0 // keeping code for demonstration purpose
351 
352 template <typename T, unsigned int tChannels>
353 void FrameFilterMedian::filterFloatSubset(const T* source, T* target, const unsigned int width, const unsigned int height, const unsigned int sourcePaddingElements, const unsigned int targetPaddingElements, const unsigned int filterSize, const unsigned int firstRow, const unsigned int numberRows)
354 {
355  static_assert(tChannels != 0u, "Invalid channel number");
356 
357  ocean_assert(source != nullptr && target != nullptr);
358 
359  ocean_assert(filterSize >= 3u && filterSize % 2u == 1u);
360 
361  const unsigned int filterSize_2 = filterSize / 2u;
362  ocean_assert(filterSize_2 <= width && filterSize_2 <= height);
363 
364  const unsigned int endRow = firstRow + numberRows;
365 
366  const unsigned int sourceStrideElements = width * tChannels + sourcePaddingElements;
367  const unsigned int targetStrideElements = width * tChannels + targetPaddingElements;
368 
369  SortedElements<T> sortedElements[tChannels];
370 
371  // fill initial histogram
372 
373  for (unsigned int y = clampLower(firstRow, filterSize_2); y <= clampUpper(firstRow, filterSize_2, height); ++y)
374  {
375  const T* sourceRow = source + y * sourceStrideElements;
376 
377  for (unsigned int x = 0u; x <= filterSize_2; ++x)
378  {
379  for (unsigned int n = 0u; n < tChannels; ++n)
380  {
381  sortedElements[n].pushValue(*sourceRow++);
382  }
383  }
384  }
385 
386  ocean_assert(sortedElements[0].size() >= (filterSize_2 + 1u) * (filterSize_2 + 1u));
387  ocean_assert(sortedElements[0].size() <= (filterSize_2 + 1u) * filterSize);
388 
389  SortedElements<T> previousSortedElements[tChannels];
390 
391  for (unsigned int y = firstRow; y < endRow; ++y)
392  {
393  T* targetRow = target + y * targetStrideElements;
394 
395  // making a copy which we can use when we start with the next row
396  for (unsigned int n = 0u; n < tChannels; ++n)
397  {
398  previousSortedElements[n] = sortedElements[n];
399  }
400 
401  for (unsigned int x = 0u; x < width; ++x)
402  {
403  for (unsigned int n = 0u; n < tChannels; ++n)
404  {
405  ocean_assert(sortedElements[n].size() != 0);
406  *targetRow++ = sortedElements[n].medianValue();
407  }
408 
409  if (x != width - 1u)
410  {
411  ocean_assert(x + 1u < width);
412 
413  // horizontal histogram update
414 
415  for (unsigned int yy = clampLower(y, filterSize_2); yy <= clampUpper(y, filterSize_2, height); ++yy)
416  {
417  const T* sourceRow = source + yy * sourceStrideElements;
418 
419  const unsigned int xxLeft = x - filterSize_2;
420  const unsigned int xxRight = x + filterSize_2 + 1u;
421 
422  if (xxLeft < width && xxRight < width)
423  {
424  for (unsigned int n = 0u; n < tChannels; ++n)
425  {
426  const T pushValue = sourceRow[xxRight * tChannels + n];
427  const T popValue = sourceRow[xxLeft * tChannels + n];
428 
429  sortedElements[n].exchange(pushValue, popValue);
430  }
431  }
432  else
433  {
434  if (xxLeft < width) // handling negative cases: int(xxLeft) < 0
435  {
436  for (unsigned int n = 0u; n < tChannels; ++n)
437  {
438  const T popValue = sourceRow[xxLeft * tChannels + n];
439 
440  sortedElements[n].popValue(popValue);
441  }
442  }
443 
444  if (xxRight < width)
445  {
446  for (unsigned int n = 0u; n < tChannels; ++n)
447  {
448  const T pushValue = sourceRow[xxRight * tChannels + n];
449 
450  sortedElements[n].pushValue(pushValue);
451  }
452  }
453  }
454  }
455  }
456 
457  ocean_assert(sortedElements[0].size() <= filterSize * filterSize);
458  }
459 
460  if (y != endRow - 1u)
461  {
462  ocean_assert(y + 1u < endRow);
463 
464  // vertical histogram update at the beginning of the row
465 
466  for (unsigned int n = 0u; n < tChannels; ++n)
467  {
468  sortedElements[n] = previousSortedElements[n];
469  }
470 
471  const unsigned int yyTop = y - filterSize_2;
472  const unsigned int yyBottom = y + filterSize_2 + 1u;
473 
474  if (yyTop < height && yyBottom < height)
475  {
476  const T* sourceRowTop = source + yyTop * sourceStrideElements;
477  const T* sourceRowBottom = source + yyBottom * sourceStrideElements;
478 
479  for (unsigned int x = 0u; x <= filterSize_2; ++x)
480  {
481  for (unsigned int n = 0u; n < tChannels; ++n)
482  {
483  const T pushValue = sourceRowBottom[x * tChannels + n];
484  const T popValue = sourceRowTop[x * tChannels + n];
485 
486  sortedElements[n].exchange(pushValue, popValue);
487  }
488  }
489  }
490  else
491  {
492  if (yyTop < height) // handling negative cases: int(yyTop) < 0
493  {
494  const T* sourceRow = source + yyTop * sourceStrideElements;
495 
496  for (unsigned int x = 0u; x <= filterSize_2; ++x)
497  {
498  for (unsigned int n = 0u; n < tChannels; ++n)
499  {
500  const T popValue = sourceRow[x * tChannels + n];
501 
502  sortedElements[n].popValue(popValue);
503  }
504  }
505  }
506 
507  if (yyBottom < height)
508  {
509  const T* sourceRow = source + yyBottom * sourceStrideElements;
510 
511  for (unsigned int x = 0u; x <= filterSize_2; ++x)
512  {
513  for (unsigned int n = 0u; n < tChannels; ++n)
514  {
515  const T pushValue = sourceRow[x * tChannels + n];
516 
517  sortedElements[n].pushValue(pushValue);
518  }
519  }
520  }
521  }
522  }
523  }
524 }
525 
526 #endif
527 
528 template <typename T, unsigned int tChannels>
529 void FrameFilterMedian::filterFloatSubset(const T* source, T* target, const unsigned int width, const unsigned int height, const unsigned int sourcePaddingElements, const unsigned int targetPaddingElements, const unsigned int filterSize, const unsigned int firstRow, const unsigned int numberRows)
530 {
531  static_assert(std::is_floating_point<T>::value, "Invalid data type!");
532  static_assert(tChannels != 0u, "Invalid channel number");
533 
534  ocean_assert(source != nullptr && target != nullptr);
535  ocean_assert(firstRow + numberRows <= height);
536 
537  const unsigned int sourceStrideElements = width * tChannels + sourcePaddingElements;
538  const unsigned int targetStrideElements = width * tChannels + targetPaddingElements;
539 
540  const unsigned int filterSize_2 = filterSize / 2u;
541 
542  std::vector<T> elements;
543  elements.reserve(filterSize * filterSize);
544 
545  for (unsigned int y = firstRow; y < firstRow + numberRows; ++y)
546  {
547  T* targetRow = target + y * targetStrideElements;
548 
549  for (unsigned int x = 0u; x < width; ++x)
550  {
551  for (unsigned int n = 0u; n < tChannels; ++n)
552  {
553  elements.clear();
554 
555  for (unsigned int xx = max(0, int(x) - int(filterSize_2)); xx < min(x + filterSize_2 + 1u, width); ++xx)
556  {
557  for (unsigned int yy = max(0, int(y) - int(filterSize_2)); yy < min(y + filterSize_2 + 1u, height); ++yy)
558  {
559  ocean_assert(xx < width && yy < height);
560 
561  elements.emplace_back(source[yy * sourceStrideElements + xx * tChannels + n]);
562  }
563  }
564 
565  *targetRow++ = Median::median<T>(elements.data(), elements.size());
566  }
567  }
568  }
569 }
570 
571 }
572 
573 }
574 
575 #endif // META_OCEAN_CV_FRAME_FILTER_MEDIAN_H
The following comfort class provides comfortable functions simplifying prototyping applications but a...
Definition: FrameFilterMedian.h:41
static bool filter(Frame &frame, const unsigned int filterSize, Worker *worker)
Filters a frame with a median filter with arbitrary size (a square patch).
static bool filter(const Frame &source, Frame &target, const unsigned int filterSize, Worker *worker)
Filters a frame with a median filter with arbitrary size (a square patch).
This class implements a median filter.
Definition: FrameFilterMedian.h:32
static void filter(const T *source, T *target, const unsigned int width, const unsigned int height, const unsigned int sourcePaddingElements, const unsigned int targetPaddingElements, const unsigned int filterSize, Worker *worker=nullptr)
Filters a frame with a median filter with arbitrary size (a square patch).
Definition: FrameFilterMedian.h:134
static void filterIntegerSubset(const T *source, T *target, const unsigned int width, const unsigned int height, const unsigned int sourcePaddingElements, const unsigned int targetPaddingElements, const unsigned int filterSize, const unsigned int firstRow, const unsigned int numberRows)
Filters a subset of an integer frame with a median filter with arbitrary size.
Definition: FrameFilterMedian.h:206
static void filterFloatSubset(const T *source, T *target, const unsigned int width, const unsigned int height, const unsigned int sourcePaddingElements, const unsigned int targetPaddingElements, const unsigned int filterSize, const unsigned int firstRow, const unsigned int numberRows)
Filters a subset of a floating point frame with a median filter with arbitrary size.
Definition: FrameFilterMedian.h:353
This class implements a histogram for integer values.
Definition: FrameFilterSorted.h:42
This class implements a container holding sorted elements.
Definition: FrameFilterSorted.h:115
void pushValue(const T &value)
Pushes a new value into the container.
Definition: FrameFilterSorted.h:327
void exchange(const T &pushValue, const T &popValue)
Exchanges a value with another value.
Definition: FrameFilterSorted.h:345
void popValue(const T &value)
Pops a value from the container.
Definition: FrameFilterSorted.h:336
T medianValue() const
Returns the median value of this histogram.
Definition: FrameFilterSorted.h:406
This class implements the base class for all filters relying on sorted filter values.
Definition: FrameFilterSorted.h:31
static unsigned int clampLower(const unsigned int index, const unsigned int lowerOffset)
Returns the lower clamped offset to an index.
Definition: FrameFilterSorted.h:428
static unsigned int clampUpper(const unsigned int index, const unsigned int upperOffset, const unsigned int size)
Returns the upper clamped offset to an index.
Definition: FrameFilterSorted.h:433
This class implements an image histogram.
Definition: Histogram.h:32
static Caller< void > createStatic(typename StaticFunctionPointerMaker< void, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass >::Type function)
Creates a new caller container for a static function with no function parameter.
Definition: Caller.h:2876
This class implements Ocean's image class.
Definition: Frame.h:1792
This class implements an object able to allocate memory.
Definition: base/Memory.h:22
size_t size() const
Returns the size of the memory in bytes.
Definition: base/Memory.h:386
void * data()
Returns the pointer to the writable memory which is allocated by this object.
Definition: base/Memory.h:303
This class provides basic numeric functionalities.
Definition: Numeric.h:57
This class implements a worker able to distribute function calls over different threads.
Definition: Worker.h:33
bool executeFunction(const Function &function, const unsigned int first, const unsigned int size, const unsigned int firstIndex=(unsigned int)(-1), const unsigned int sizeIndex=(unsigned int)(-1), const unsigned int minimalIterations=1u, const unsigned int threadIndex=(unsigned int)(-1))
Executes a callback function separable by two function parameters.
The namespace covering the entire Ocean framework.
Definition: Accessor.h:15