Ocean
Loading...
Searching...
No Matches
Histogram.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_HISTOGRAM_H
9#define META_OCEAN_CV_HISTOGRAM_H
10
11#include "ocean/cv/CV.h"
12
13#include "ocean/base/Frame.h"
14#include "ocean/base/Worker.h"
15
16#include "ocean/math/Lookup2.h"
17#include "ocean/math/Math.h"
18
19#include <array>
20
21namespace Ocean
22{
23
24namespace CV
25{
26
27/**
28 * This class implements an image histogram.
29 * @ingroup cv
30 */
31class OCEAN_CV_EXPORT Histogram
32{
33 public:
34
35 /**
36 * This class implements the base class for all histogram objects holding 8 bit per data channel.
37 * @tparam tChannels Defines the number of channels of the histogram
38 */
39 template <unsigned int tChannels>
41 {
42 public:
43
44 /**
45 * Returns the bin value of a specific channel and bin.
46 * This function uses a template parameter to define the channel and the bin.<br>
47 * @tparam tChannel Data channel, with range [0, tChannels)
48 * @tparam tIndex Index of the bin
49 * @return Bin value
50 */
51 template <unsigned int tChannel, uint8_t tIndex>
52 inline unsigned int bin() const;
53
54 /**
55 * Returns the bin value of a specific channel and bin.
56 * This function uses a template parameter to define the channel.<br>
57 * @param index The index of the bin, with range [0, 255]
58 * @tparam tChannel Data channel, with range [0, tChannels - 1]
59 * @return Bin value
60 */
61 template <unsigned int tChannel>
62 inline unsigned int bin(const uint8_t index) const;
63
64 /**
65 * Returns the bin value of a specific channel and bin.
66 * @param channel Data channel, with range [0, tChannels)
67 * @param index The index of the bin, with range [0, 255]
68 * @return Bin value
69 */
70 inline unsigned int bin(const unsigned int channel, const uint8_t index) const;
71
72 /**
73 * Returns the sum of all channels stored for a specific bin.
74 * @param index The index of the bin, with range [0, 255]
75 * @return Sum of all channels
76 */
77 inline unsigned int sumBin(const uint8_t index) const;
78
79 /**
80 * Returns the 256 histogram values for a specific channel.
81 * @tparam tChannel Channel for that the histogram is requested, with range [0, tChannels)
82 * @return Channel histogram
83 */
84 template <unsigned int tChannel>
85 inline const unsigned int* bins() const;
86
87 /**
88 * Returns the 256 histogram values for a specific channel.
89 * @param channel The channel for that the histogram is requested, with range [0, tChannels)
90 * @return Channel histogram
91 */
92 inline const unsigned int* bins(const unsigned int channel) const;
93
94 /**
95 * Determines the highest value within the histogram for a specific channel.
96 * @tparam tChannel Channel for that the highest value has to be found, with range [0, tChannels)
97 * @return Highest value inside the specified channel
98 */
99 template <unsigned int tChannel>
100 unsigned int determineHighestValue() const;
101
102 /**
103 * Determines the highest value within the histogram for a specific channel.
104 * @param channel The channel for that the highest value has to be found, with range [0, tChannels)
105 * @return Highest value inside the specified channel
106 */
107 unsigned int determineHighestValue(const unsigned int channel) const;
108
109 /**
110 * Determines the highest value within the entire histogram.
111 * @return Highest histogram value
112 */
113 unsigned int determineHighestValue() const;
114
115 /**
116 * Determines the first bin that is not zero for a specific channel.
117 * @param channel Histogram channel in that the search is invoked, with range [0, tChannels)
118 * @return First non-zero bin, otherwise -1
119 */
120 unsigned int determineStartBin(const unsigned int channel) const;
121
122 /**
123 * Determines the last bin that is not zero for a specific channel.
124 * @param channel Histogram channel in that the search is invoked, with range [0, tChannels)
125 * @return Last non-zero bin, otherwise -1
126 */
127 unsigned int determineEndBin(const unsigned int channel) const;
128
129 /**
130 * Normalizes the entire histogram by application of the highest histogram value.
131 * @param newMaximalValue Normalization value that will be the maximal value inside the entire histogram after normalization
132 */
133 inline void normalize(const unsigned int newMaximalValue);
134
135 /**
136 * Normalizes one channel of the histogram by application of the highest value of the channel.
137 * @param channel Histogram channel that will be normalized, with range [0, tChannels)
138 * @param newMaximalValue Normalization value that will be the maximal value inside the histogram channel after normalization
139 */
140 inline void normalize(const unsigned int channel, const unsigned int newMaximalValue);
141
142 /**
143 * Clears the entire histogram and sets all bins to zero.
144 */
145 void clear();
146
147 /**
148 * Returns whether all bins inside the histogram are zero.
149 * @return True, if so
150 */
151 inline bool isNull() const;
152
153 /**
154 * Returns whether two histogram objects are identical according to their histogram bins.
155 * @param histogram Second histogram object
156 * @return True, if so
157 */
158 inline bool operator==(const HistogramBase8BitPerChannel<tChannels>& histogram) const;
159
160 /**
161 * Returns whether two histogram objects are not identical according to their histogram bins.
162 * @param histogram Second histogram object
163 * @return True, if so
164 */
165 inline bool operator!=(const HistogramBase8BitPerChannel<tChannels>& histogram) const;
166
167 /**
168 * Adds the histogram bins of a second histogram to this histogram.
169 * @param histogram Second histogram that is added to this one
170 * @return Reference to this histogram object
171 */
173
174 /**
175 * Returns all histogram bins of this histogram.
176 * The bins are stored channel by channel (first the 256 bins of the first channel, than the next 256 bins of the next channel, ...)
177 * @return Histogram bins
178 */
179 inline const unsigned int* operator()() const;
180
181 protected:
182
183 /**
184 * Creates an empty histogram object and sets all histogram bins to zero.
185 */
187
188 /**
189 * Explicitly sets a value of a specific histogram bin.
190 * @param channel Histogram channel for that the bin has to be set
191 * @param index The index of the bin to be set
192 * @param value Value to be set as new histogram bin value
193 */
194 void setBin(const unsigned int channel, const uint8_t index, const unsigned int value);
195
196 protected:
197
198 /// The histogram bins.
199 unsigned int histogramBins[256u * tChannels];
200 };
201
202 /**
203 * This class implements a standard histogram object storing 8 bit per channel.
204 * @tparam tChannels Defines the number of channels of the histogram
205 */
206 template <unsigned int tChannels>
208 {
209 public:
210
211 /**
212 * Creates a new histogram object and sets all histogram bins to zero.
213 */
215
216 /**
217 * Increments a specific bin of this histogram (by one).
218 * @param index The index of the bin
219 * @tparam tChannel Histogram channel in that the bin is stored
220 */
221 template <unsigned int tChannel>
222 inline void incrementBin(const uint8_t index);
223
224 /**
225 * Increments a specific bin of this histogram (by one).
226 * @param channel Histogram channel in that the bin is stored
227 * @param index The index of the bin
228 */
229 inline void incrementBin(const unsigned int channel, const uint8_t index);
230
231 /**
232 * Increments all channels of a specific histogram bin (by one).
233 * The given pixel value must provide as much channels as defined for this histogram (by tChannels).<br>
234 * @param pixel Pixel that is used to store all histogram channels
235 */
236 inline void increment(const uint8_t* pixel);
237
238 /**
239 * Adds to histogram objects and returns the new histogram.
240 * @param histogram Second histogram object that is used to create the new sum histogram
241 * @return Resulting new sum histogram object
242 */
244 };
245
246 /**
247 * This class implements an integral histogram object.
248 * This histogram holds the sum of all previous bins in each bin of the histogram.<br>
249 * @tparam tChannels Defines the number of channels of the histogram
250 */
251 template <unsigned int tChannels>
253 {
254 public:
255
256 /**
257 * Creates a new integral histogram object and sets all histogram bins to zero.
258 */
260
261 /**
262 * Creates a new integral histogram by application of a standard histogram.
263 * The bins of the standard histogram are used to calculate the integral histogram bins.
264 * @param histogram Standard histogram that will be converted into this integral histogram object
265 */
267
268 /**
269 * Inverts this (normalized) integral histogram so that the inverted histogram can be used as lookup object.
270 * Beware: This histogram has to be normalized to the maximal bin value of 0xFF before!<br>
271 * @return Inverted integral histogram of this object
272 * @see HistogramBase8BitPerChannel::normalize().
273 */
274 IntegralHistogram8BitPerChannel invert() const;
275 };
276
277 private:
278
279 /**
280 * This class implements a simple lookup table.
281 * @tparam tChannels Defines the number of channels of the table
282 */
283 template <unsigned int tChannels>
285 {
286 public:
287
288 /**
289 * Creates a default lookup table providing the identity lookup result.
290 */
292
293 /**
294 * Creates a new lookup table by a given normalized integral histogram used as start position and an inverted normalized integral histogram used as end position.
295 * Beware: Both provided integral histograms have to be normalized to the maximal bin value of 0xFF before!<br>
296 * @param normalizedHistogram The normalized integral histogram that is used to create the intermediate lookup value
297 * @param invertedNormalizedHistogram The inverted normalized integral histogram that is used to translate the intermediate lookup value into the final lookup result
298 */
300
301 /**
302 * Lookup function providing the lookup value for a specific channel and bin.
303 * @param index The index of the lookup bin
304 * @tparam tChannel Channel in that the lookup bin in located
305 * @return Lookup value
306 */
307 template <unsigned int tChannel>
308 uint8_t lookup(const uint8_t index) const;
309
310 /**
311 * Lookup function providing the lookup value for a specific channel and bin.
312 * @param index The index of the lookup bin
313 * @param channel The channel in that the lookup bin in located
314 * @return Lookup value
315 */
316 uint8_t lookup(const unsigned int channel, const uint8_t index) const;
317
318 protected:
319
320 /// The lookup data.
321 uint8_t lookupData[256u * tChannels];
322 };
323
324 public:
325
326 /**
327 * Determines the standard histogram for a given frame.
328 * @param frame The frame for that the histogram has to be determined
329 * @param width The width of the given frame in pixel
330 * @param height The height of the given frame in pixel
331 * @param framePaddingElements Optional number of padding elements of the input frame, range: [0, infinity)
332 * @param worker Optional worker object to distributed the computation
333 * @return Resulting standard histogram object
334 * @tparam tChannels Number of channels of the given frame, with range [1, infinity)
335 */
336 template <unsigned int tChannels>
337 static Histogram8BitPerChannel<tChannels> determineHistogram8BitPerChannel(const uint8_t* frame, const unsigned int width, const unsigned int height, const unsigned int framePaddingElements, Worker* worker = nullptr);
338
339 /**
340 * Determines the standard histogram in a sub region of a given frame.
341 * @param frame The frame for that the histogram has to be determined
342 * @param width The width of the given frame in pixel
343 * @param height The height of the given frame in pixel
344 * @param subframeLeft Horizontal start position of the sub region within the frame, in pixel with range [0, width)
345 * @param subframeTop Vertical start position of the sub region within the frame, in pixel with range [0, height)
346 * @param subframeWidth The width of the sub region, in pixel with range [1, width - subframeLeft]
347 * @param subframeHeight The height of the sub region, in pixel with range [1, height - subframeTop]
348 * @param worker Optional worker object to distributed the computation
349 * @param framePaddingElements Optional number of padding elements of the input frame, range: [0, infinity), default: 0
350 * @return Resulting standard histogram object
351 * @tparam tChannels Number of channels of the given frame, with range [1, infinity)
352 */
353 template <unsigned int tChannels>
354 static Histogram8BitPerChannel<tChannels> determineHistogram8BitPerChannel(const uint8_t* frame, const unsigned int width, const unsigned int height, const unsigned int subframeLeft, const unsigned int subframeTop, const unsigned int subframeWidth, const unsigned int subframeHeight, const unsigned int framePaddingElements, Worker* worker = nullptr);
355
356 /**
357 * Applies a histogram equalization for a given frame.
358 * The frame is equalized by application of the integral histogram of the original frame.<br>
359 * @param frame The frame that will be equalized according the histogram
360 * @param factor Interpolation factor between the original and the fully equalized frame, with range [0, 1]: 0 means the original frame is taken by 100 percent while 1 means that the equalized frame is taken by 100 percent
361 * @param worker Optional worker object to distribute the computation
362 * @return True, if succeeded
363 */
364 static bool equalization(Frame& frame, const Scalar factor = 1, Worker* worker = nullptr);
365
366 /**
367 * Applies a histogram equalization for a given frame.
368 * The frame is equalized by application of the integral histogram of the original frame.<br>
369 * @param source The source frame for that an equalized target frame will be created
370 * @param target The target frame receiving the equalization result
371 * @param factor Interpolation factor between the original and the fully equalized frame, with range [0, 1]: 0 means the original frame is taken by 100 percent while 1 means that the equalized frame is taken by 100 percent
372 * @param worker Optional worker object to distribute the computation
373 * @return True, if succeeded
374 */
375 static bool equalization(const Frame& source, Frame& target, const Scalar factor = 1, Worker* worker = nullptr);
376
377 /**
378 * Adjusts the color of a frame according to a given reference frame.
379 * The function applies a forward and backward mapping of the normalized integral histograms of both frames.<br>
380 * The frame types of the frame and the given reference frame must be identical.
381 * @param frame The frame for that the color values will be adjusted
382 * @param reference Reference frame providing the color statistics for the new frame
383 * @param worker Optional worker object to distribute the computation
384 * @return True, if succeeded
385 */
386 static bool adjustColorToReference(Frame& frame, const Frame& reference, Worker* worker = nullptr);
387
388 /**
389 * Adjusts the color of a frame according to a given reference frame while using corresponding bins for the adjustments only (not the entire frame information).
390 * The function applies a forward and backward mapping of the normalized integral histograms of both frames.<br>
391 * The frame types of the frame and the given reference frame must be identical.
392 * @param frame The frame for that the color values will be adjusted
393 * @param reference Reference frame providing the color statistics for the new frame
394 * @param horizontalBins The number of horizontal bins to use, with range [1, min(frame.width(), reference.with())]
395 * @param verticalBins The number of vertical bins to use, with range [1, min(frame.height(), reference.height())]
396 * @param worker Optional worker object to distribute the computation
397 * @return True, if succeeded
398 */
399 static bool adjustColorToReference(Frame& frame, const Frame& reference, const unsigned int horizontalBins, const unsigned int verticalBins, Worker* worker = nullptr);
400
401 /**
402 * Adjusts the color of a frame according to a given reference frame while using corresponding bins for the adjustments only (not the entire frame information).
403 * The function applies a forward and backward mapping of the normalized integral histograms of both frames.<br>
404 * The frame types of the frame and the given reference frame must be identical.
405 * @param frame The frame for that the color values will be adjusted
406 * @param frameWidth The width of the frame in pixel, with range [1, infinity)
407 * @param frameHeight The height of the frame in pixel, with range [1, infinity)
408 * @param reference Reference frame providing the color statistics for the new frame
409 * @param referenceWidth The width of the reference frame in pixel, with range [1, infinity)
410 * @param referenceHeight The height of the reference frame in pixel, with range [1, infinity)
411 * @param horizontalBins The number of horizontal bins to use, with range [1, min(frameWidth, referenceWidth)]
412 * @param verticalBins The number of vertical bins to use, with range [1, min(frameHeight, referenceHeight)]
413 * @param framePaddingElements The number of padding elements at the end of each frame row, in elements, with range [0, infinity)
414 * @param referencePaddingElements The number of padding elements at the end of each reference row, in elements, with range [0, infinity)
415 * @param worker Optional worker object to distribute the computation
416 * @return True, if succeeded
417 * @tparam tChannels Number of channels of the frame, with range [1, infinity)
418 */
419 template <unsigned int tChannels>
420 static bool adjustColorToReference(uint8_t* frame, const unsigned int frameWidth, const unsigned int frameHeight, const uint8_t* reference, const unsigned int referenceWidth, const unsigned int referenceHeight, const unsigned int horizontalBins, const unsigned int verticalBins, const unsigned int framePaddingElements, const unsigned int referencePaddingElements, Worker* worker = nullptr);
421
422 /**
423 * Adjusts the color of a frame according to a given reference frame.
424 * The function applies a forward and backward mapping of the normalized integral histograms of both frames.
425 * The frame types of the source frame and the given reference frame must be identical.<br>
426 * @param source The source frame that is used to create the target frame
427 * @param target The target frame with adjusted color information
428 * @param reference Reference frame providing the color statistics for the new frame
429 * @param worker Optional worker object to distribute the computation
430 * @return True, if succeeded
431 */
432 static bool adjustColorToReference(const Frame& source, Frame& target, const Frame& reference, Worker* worker = nullptr);
433
434 /**
435 * Applies a histogram equalization for a given frame.
436 * The frame is equalized by application of the integral histogram of the original frame.<br>
437 * @param frame The frame that will be equalized according the histogram
438 * @param width The width of the frame in pixel, with range [1, infinity)
439 * @param height The height of the frame in pixel, with range [1, infinity)
440 * @param factor Interpolation factor between the original and the fully equalized frame, with range [0, 1]: 0 means the original frame is taken by 100 percent while 1 means that the equalized frame is taken by 100 percent
441 * @param framePaddingElements The number of padding elements at the end of each frame row, in elements, with range [0, infinity)
442 * @param worker Optional worker object to distribute the computation
443 * @return True, if succeeded
444 * @tparam tChannels Number of channels of the frame, with range [1, infinity)
445 */
446 template <unsigned int tChannels>
447 static inline bool equalization(uint8_t* frame, const unsigned int width, const unsigned int height, const Scalar factor, const unsigned int framePaddingElements, Worker* worker = nullptr);
448
449 /**
450 * Applies a histogram equalization for a given frame.
451 * The frame is equalized by application of the integral histogram of the original frame.<br>
452 * @param source The source frame for that an equalized target frame will be created
453 * @param target The target frame receiving the equalization result
454 * @param width The width of the source and target frame in pixel
455 * @param height The height of the source and target frame in pixel
456 * @param factor Interpolation factor between the original and the fully equalized frame, with range [0, 1]: 0 means the original frame is taken by 100 percent while 1 means that the equalized frame is taken by 100 percent
457 * @param sourcePaddingElements The number of padding elements at the end of each source row, in elements, with range [0, infinity)
458 * @param targetPaddingElements The number of padding elements at the end of each target row, in elements, with range [0, infinity)
459 * @param worker Optional worker object to distribute the computation
460 * @return True, if succeeded
461 * @tparam tChannels Number of channels of the source and target frame, with range [1, infinity)
462 */
463 template <unsigned int tChannels>
464 static inline bool equalization(const uint8_t* source, uint8_t* target, const unsigned int width, const unsigned int height, const Scalar factor, const unsigned int sourcePaddingElements, const unsigned int targetPaddingElements, Worker* worker = nullptr);
465
466 /**
467 * Applies a histogram equalization for a given frame.
468 * The frame is equalized by application of the integral histogram of the original frame.<br>
469 * @param frame The frame that will be equalized according the histogram
470 * @param width The width of the frame in pixel
471 * @param height The height of the frame in pixel
472 * @param normalizedIntegral Already determined normalized integral histogram of the given frame
473 * @param factor Interpolation factor between the original and the fully equalized frame, with range [0, 1]: 0 means the original frame is taken by 100 percent while 1 means that the equalized frame is taken by 100 percent
474 * @param framePaddingElements The number of padding elements at the end of each frame row, in elements, with range [0, infinity)
475 * @param worker Optional worker object to distribute the computation
476 * @return True, if succeeded
477 * @tparam tChannels Number of channels of the frame, with range [1, infinity)
478 */
479 template <unsigned int tChannels>
480 static inline bool equalization(uint8_t* frame, const unsigned int width, const unsigned int height, const IntegralHistogram8BitPerChannel<tChannels>& normalizedIntegral, const Scalar factor, const unsigned int framePaddingElements, Worker* worker = nullptr);
481
482 /**
483 * Applies a histogram equalization in a sub region of a given frame.
484 * The frame is equalized by application of the integral histogram of the original frame.<br>
485 * @param frame The frame that will be equalized according the histogram
486 * @param width The width of the frame in pixel
487 * @param height The height of the frame in pixel
488 * @param subframeLeft Horizontal start position of the sub region within the frame, in pixel with range [0, width)
489 * @param subframeTop Vertical start position of the sub region within the frame, in pixel with range [0, heigh)
490 * @param subframeWidth The width of the sub region, in pixel with range [1, width - subframeLeft]
491 * @param subframeHeight The height of the sub region, in pixel with range [1, height - subframeTop]
492 * @param normalizedIntegral Already determined normalized integral histogram of the given frame
493 * @param factor Interpolation factor between the original and the fully equalized frame, with range [0, 1]: 0 means the original frame is taken by 100 percent while 1 means that the equalized frame is taken by 100 percent
494 * @param framePaddingElements The number of padding elements at the end of each frame row, in elements, with range [0, infinity)
495 * @param worker Optional worker object to distribute the computation
496 * @return True, if succeeded
497 * @tparam tChannels Number of channels of the frame, with range [1, infinity)
498 */
499 template <unsigned int tChannels>
500 static bool equalization(uint8_t* frame, const unsigned int width, const unsigned int height, const unsigned int subframeLeft, const unsigned int subframeTop, const unsigned int subframeWidth, const unsigned int subframeHeight, const IntegralHistogram8BitPerChannel<tChannels>& normalizedIntegral, const Scalar factor, const unsigned int framePaddingElements, Worker* worker = nullptr);
501
502 /**
503 * Applies a histogram equalization for a given frame.
504 * The frame is equalized by application of the integral histogram of the original frame.<br>
505 * @param source The source frame for that an equalized target frame will be created
506 * @param target The target frame receiving the equalization result
507 * @param width The width of the source and target frame in pixel
508 * @param height The height of the source and target frame in pixel
509 * @param normalizedIntegral Already determined normalized integral histogram of the given source frame
510 * @param factor Interpolation factor between the original and the fully equalized frame, with range [0, 1]: 0 means the original frame is taken by 100 percent while 1 means that the equalized frame is taken by 100 percent
511 * @param sourcePaddingElements The number of padding elements at the end of each source row, in elements, with range [0, infinity)
512 * @param targetPaddingElements The number of padding elements at the end of each target row, in elements, with range [0, infinity)
513 * @param worker Optional worker object to distribute the computation
514 * @return True, if succeeded
515 * @tparam tChannels Number of channels of the source and target frame, with range [1, infinity)
516 */
517 template <unsigned int tChannels>
518 static inline bool equalization(const uint8_t* source, uint8_t* target, const unsigned int width, const unsigned int height, const IntegralHistogram8BitPerChannel<tChannels>& normalizedIntegral, const Scalar factor, const unsigned int sourcePaddingElements, const unsigned int targetPaddingElements, Worker* worker = nullptr);
519
520 /**
521 * Applies a histogram equalization for a given frame.
522 * The frame is equalized by application of the integral histogram of the original frame.<br>
523 * @param source The source frame for that an equalized target frame will be created
524 * @param target The target frame receiving the equalization result
525 * @param width The width of the source and target frame in pixel
526 * @param height The height of the source and target frame in pixel
527 * @param subframeLeft Horizontal start position of the sub region within the frame, in pixel with range [0, width)
528 * @param subframeTop Vertical start position of the sub region within the frame, in pixel with range [0, heigh)
529 * @param subframeWidth The width of the sub region, in pixel with range [1, width - subframeLeft]
530 * @param subframeHeight The height of the sub region, in pixel with range [1, height - subframeTop]
531 * @param normalizedIntegral Already determined normalized integral histogram of the given source frame
532 * @param factor Interpolation factor between the original and the fully equalized frame, with range [0, 1]: 0 means the original frame is taken by 100 percent while 1 means that the equalized frame is taken by 100 percent
533 * @param sourcePaddingElements The number of padding elements at the end of each source row, in elements, with range [0, infinity)
534 * @param targetPaddingElements The number of padding elements at the end of each target row, in elements, with range [0, infinity)
535 * @param worker Optional worker object to distribute the computation
536 * @return True, if succeeded
537 * @tparam tChannels Number of channels of the source and target frame, with range [1, infinity)
538 */
539 template <unsigned int tChannels>
540 static bool equalization(const uint8_t* source, uint8_t* target, const unsigned int width, const unsigned int height, const unsigned int subframeLeft, const unsigned int subframeTop, const unsigned int subframeWidth, const unsigned int subframeHeight, const IntegralHistogram8BitPerChannel<tChannels>& normalizedIntegral, const Scalar factor, const unsigned int sourcePaddingElements, const unsigned int targetPaddingElements, Worker* worker = nullptr);
541
542 /**
543 * Adjusts the color of a frame according to a given reference frame.
544 * The function applies a forward and backward mapping of the normalized integral histograms of both frames.
545 * @param frame The frame for that the color values will be adjusted
546 * @param frameWidth The width of the frame in pixel
547 * @param frameHeight The height of the frame in pixel
548 * @param reference Reference frame providing the color statistics for the new frame
549 * @param referenceWidth The width of the reference frame in pixel
550 * @param referenceHeight The height of the reference frame in pixel
551 * @param framePaddingElements The number of padding elements at the end of each frame row, in elements, with range [0, infinity)
552 * @param referencePaddingElements The number of padding elements at the end of each reference row, in elements, with range [0, infinity)
553 * @param worker Optional worker object to distribute the computation
554 * @return True, if succeeded
555 * @tparam tChannels Number of channels of the frame, with range [1, infinity)
556 */
557 template <unsigned int tChannels>
558 static bool adjustColorToReference(uint8_t* frame, const unsigned int frameWidth, const unsigned int frameHeight, const uint8_t* reference, const unsigned int referenceWidth, const unsigned int referenceHeight, const unsigned int framePaddingElements, const unsigned int referencePaddingElements, Worker* worker = nullptr);
559
560 /**
561 * Adjusts the color of a frame according to a given reference frame.
562 * The function applies a forward and backward mapping of the normalized integral histograms of both frames.
563 * The frame types of the source frame and the given reference frame must be identical.<br>
564 * @param source The source frame that is used to create the target frame
565 * @param target The target frame with adjusted color information
566 * @param sourceWidth The width of the source and target frame in pixel
567 * @param sourceHeight The height of the source and target frame in pixel
568 * @param reference Reference frame providing the color statistics for the new frame
569 * @param referenceWidth The width of the reference frame in pixel
570 * @param referenceHeight The height of the reference frame in pixel
571 * @param sourcePaddingElements The number of padding elements at the end of each source row, in elements, with range [0, infinity)
572 * @param targetPaddingElements The number of padding elements at the end of each target row, in elements, with range [0, infinity)
573 * @param referencePaddingElements The number of padding elements at the end of each reference row, in elements, with range [0, infinity)
574 * @param worker Optional worker object to distribute the computation
575 * @return True, if succeeded
576 * @tparam tChannels Number of channels of the frame, with range [1, infinity)
577 */
578 template <unsigned int tChannels>
579 static bool adjustColorToReference(const uint8_t* source, uint8_t* target, const unsigned int sourceWidth, const unsigned int sourceHeight, const uint8_t* reference, const unsigned int referenceWidth, const unsigned int referenceHeight, const unsigned int sourcePaddingElements, const unsigned int targetPaddingElements, const unsigned int referencePaddingElements, Worker* worker = nullptr);
580
581 /**
582 * Adjusts the color of a frame according to a given reference frame.
583 * The function applies a forward and backward mapping of the normalized integral histograms of both frames.
584 * @param frame The frame for that the color values will be adjusted
585 * @param width The width of the frame in pixel
586 * @param height The height of the frame in pixel
587 * @param invertedNormalizedReferenceIntegral Already determined inverted and normalized integral histogram of the reference frame
588 * @param framePaddingElements The number of padding elements at the end of each frame row, in elements, with range [0, infinity)
589 * @param worker Optional worker object to distribute the computation
590 * @return True, if succeeded
591 * @tparam tChannels Number of channels of the frame, with range [1, infinity)
592 */
593 template <unsigned int tChannels>
594 static inline bool adjustColorToReference(uint8_t* frame, const unsigned int width, const unsigned int height, const IntegralHistogram8BitPerChannel<tChannels>& invertedNormalizedReferenceIntegral, const unsigned int framePaddingElements, Worker* worker = nullptr);
595
596 /**
597 * Adjusts the color of a frame according to a given reference frame.
598 * The function applies a forward and backward mapping of the normalized integral histograms of both frames.
599 * @param frame The frame for that the color values will be adjusted
600 * @param width The width of the frame in pixel
601 * @param height The height of the frame in pixel
602 * @param subframeLeft Horizontal start position of the sub region within the frame, in pixel with range [0, width)
603 * @param subframeTop Vertical start position of the sub region within the frame, in pixel with range [0, heigh)
604 * @param subframeWidth The width of the sub region, in pixel with range [1, width - subframeLeft]
605 * @param subframeHeight The height of the sub region, in pixel with range [1, height - subframeTop]
606 * @param invertedNormalizedReferenceIntegral Already determined inverted and normalized integral histogram of the reference frame
607 * @param framePaddingElements The number of padding elements at the end of each frame row, in elements, with range [0, infinity)
608 * @param worker Optional worker object to distribute the computation
609 * @return True, if succeeded
610 * @tparam tChannels Number of channels of the frame, with range [1, infinity)
611 */
612 template <unsigned int tChannels>
613 static bool adjustColorToReference(uint8_t* frame, const unsigned int width, const unsigned int height, const unsigned int subframeLeft, const unsigned int subframeTop, const unsigned int subframeWidth, const unsigned int subframeHeight, const IntegralHistogram8BitPerChannel<tChannels>& invertedNormalizedReferenceIntegral, const unsigned int framePaddingElements, Worker* worker = nullptr);
614
615 /**
616 * Adjusts the color of a frame according to a given reference frame.
617 * The function applies a forward and backward mapping of the normalized integral histograms of both frames.
618 * The frame types of the source frame and the given reference frame must be identical.<br>
619 * @param source The source frame that is used to create the target frame
620 * @param target The target frame with adjusted color information
621 * @param width The width of the source and target frame in pixel
622 * @param height The height of the source and target frame in pixel
623 * @param invertedNormalizedReferenceIntegral Already determined inverted and normalized integral histogram of the reference frame
624 * @param sourcePaddingElements The number of padding elements at the end of each source row, in elements, with range [0, infinity)
625 * @param targetPaddingElements The number of padding elements at the end of each target row, in elements, with range [0, infinity)
626 * @param worker Optional worker object to distribute the computation
627 * @return True, if succeeded
628 * @tparam tChannels Number of channels of the frame, with range [1, infinity)
629 */
630 template <unsigned int tChannels>
631 static inline bool adjustColorToReference(const uint8_t* source, uint8_t* target, const unsigned int width, const unsigned int height, const IntegralHistogram8BitPerChannel<tChannels>& invertedNormalizedReferenceIntegral, const unsigned int sourcePaddingElements, const unsigned int targetPaddingElements, Worker* worker = nullptr);
632
633 /**
634 * Adjusts the color of a frame according to a given reference frame.
635 * The function applies a forward and backward mapping of the normalized integral histograms of both frames.
636 * The frame types of the source frame and the given reference frame must be identical.<br>
637 * @param source The source frame that is used to create the target frame
638 * @param target The target frame with adjusted color information
639 * @param width The width of the source and target frame in pixel
640 * @param height The height of the source and target frame in pixel
641 * @param subframeLeft Horizontal start position of the sub region within the frame, in pixel with range [0, width)
642 * @param subframeTop Vertical start position of the sub region within the frame, in pixel with range [0, heigh)
643 * @param subframeWidth The width of the sub region, in pixel with range [1, width - subframeLeft]
644 * @param subframeHeight The height of the sub region, in pixel with range [1, height - subframeTop]
645 * @param invertedNormalizedReferenceIntegral Already determined inverted and normalized integral histogram of the reference frame
646 * @param sourcePaddingElements The number of padding elements at the end of each source row, in elements, with range [0, infinity)
647 * @param targetPaddingElements The number of padding elements at the end of each target row, in elements, with range [0, infinity)
648 * @param worker Optional worker object to distribute the computation
649 * @return True, if succeeded
650 * @tparam tChannels Number of channels of the frame, with range [1, infinity)
651 */
652 template <unsigned int tChannels>
653 static bool adjustColorToReference(const uint8_t* source, uint8_t* target, const unsigned int width, const unsigned int height, const unsigned int subframeLeft, const unsigned int subframeTop, const unsigned int subframeWidth, const unsigned int subframeHeight, const IntegralHistogram8BitPerChannel<tChannels>& invertedNormalizedReferenceIntegral, const unsigned int sourcePaddingElements, const unsigned int targetPaddingElements, Worker* worker = nullptr);
654
655 private:
656
657 /**
658 * Determines the standard histogram in a subset of a given frame.
659 * @param frame The frame for that the histogram has to be determined, must be valid
660 * @param width The width of the given frame in pixel, with range [1, infinity)
661 * @param height The height of the given frame in pixel, with range [1, infinity)
662 * @param histogram Resulting histogram
663 * @param lock Optional lock object that needs to be defined if this function is executed in parallel
664 * @param firstColumn First column to be handled
665 * @param numberColumns Number of columns to be handled
666 * @param framePaddingElements Optional number of padding elements of the input frame, range: [0, infinity)
667 * @param firstRow First row to be handled, with range [0, infinity)
668 * @param numberRows Number of rows to be handled, with range [1, height - firstRow]
669 * @tparam tChannels Number of channels of the given frame, with range [1, infinity)
670 */
671 template <unsigned int tChannels>
672 static void determineHistogram8BitPerChannelSubset(const uint8_t* frame, const unsigned int width, const unsigned int height, Histogram8BitPerChannel<tChannels>* histogram, Lock* lock, const unsigned int firstColumn, const unsigned int numberColumns, const unsigned int framePaddingElements, const unsigned int firstRow, const unsigned int numberRows);
673
674 /**
675 * Applies a histogram equalization in a subset of a given frame.
676 * The frame is equalized by application of the integral histogram of the original frame.<br>
677 * @param frame The frame that will be equalized according the histogram
678 * @param width The width of the frame in pixel
679 * @param height The height of the frame in pixel
680 * @param normalizedIntegral Already determined normalized integral histogram of the given frame
681 * @param factor Interpolation factor, with range [0, 256]
682 * @param firstColumn First column to be handled
683 * @param numberColumns Number of columns to be handled
684 * @param framePaddingElements Optional number of padding elements of the input frame, range: [0, infinity)
685 * @param firstRow First row to be handled
686 * @param numberRows Number of rows to be handled
687 * @tparam tChannels Number of channels of the frame, with range [1, infinity)
688 */
689 template <unsigned int tChannels>
690 static void equalizationSubset(uint8_t* frame, const unsigned int width, const unsigned int height, const IntegralHistogram8BitPerChannel<tChannels>* normalizedIntegral, const unsigned int factor, const unsigned int firstColumn, const unsigned int numberColumns, const unsigned int framePaddingElements, const unsigned int firstRow, const unsigned int numberRows);
691
692 /**
693 * Applies a histogram equalization in a subset of a given frame.
694 * The frame is equalized by application of the integral histogram of the original frame.<br>
695 * @param source The source frame for that an equalized target frame will be created
696 * @param target The target frame receiving the equalization result
697 * @param width The width of the source and target frame in pixel
698 * @param height The height of the source and target frame in pixel
699 * @param normalizedIntegral Already determined normalized integral histogram of the given frame
700 * @param factor Interpolation factor, with range [0, 256]
701 * @param firstColumn First column to be handled
702 * @param numberColumns Number of columns to be handled
703 * @param sourcePaddingElements Optional number of padding elements of the source frame, range: [0, infinity)
704 * @param targetPaddingElements Optional number of padding elements of the target frame, range: [0, infinity)
705 * @param firstRow First row to be handled
706 * @param numberRows Number of rows to be handled
707 * @tparam tChannels Number of channels of the source and target frame, with range [1, infinity)
708 */
709 template <unsigned int tChannels>
710 static void equalizationOfTargetSubset(const uint8_t* source, uint8_t* target, const unsigned int width, const unsigned int height, const IntegralHistogram8BitPerChannel<tChannels>* normalizedIntegral, const unsigned int factor, const unsigned int firstColumn, const unsigned int numberColumns, const unsigned int sourcePaddingElements, const unsigned int targetPaddingElements, const unsigned int firstRow, const unsigned int numberRows);
711
712 /**
713 * Adjusts the color in a subset of a frame according to a given reference frame.
714 * The function applies a forward and backward mapping of the normalized integral histograms of both frames.
715 * @param frame The frame for that the color values will be adjusted
716 * @param width The width of the frame in pixel
717 * @param height The height of the frame in pixel
718 * @param lookupTable Lookup table defining the adjustment of the color
719 * @param firstColumn First column to be handled
720 * @param numberColumns Number of columns to be handled
721 * @param framePaddingElements Optional number of padding elements of the input frame, range: [0, infinity)
722 * @param firstRow First row to be handled
723 * @param numberRows Number of rows to be handled
724 * @tparam tChannels Number of channels of the frame, with range [1, infinity)
725 */
726 template <unsigned int tChannels>
727 static void adjustColorToReferenceSubset(uint8_t* frame, const unsigned int width, const unsigned int height, const LookupTable8BitPerChannel<tChannels>* lookupTable, const unsigned int firstColumn, const unsigned int numberColumns, const unsigned int framePaddingElements, const unsigned int firstRow, const unsigned int numberRows);
728
729 /**
730 * Adjusts the color of a frame according to a given reference frame.
731 * The function applies a forward and backward mapping of the normalized integral histograms of both frames.
732 * The frame types of the source frame and the given reference frame must be identical.<br>
733 * @param source The source frame that is used to create the target frame
734 * @param target The target frame with adjusted color information
735 * @param width The width of the source and target frame in pixel
736 * @param height The height of the source and target frame in pixel
737 * @param lookupTable Lookup table defining the adjustment of the color
738 * @param firstColumn First column to be handled
739 * @param numberColumns Number of columns to be handled
740 * @param sourcePaddingElements Optional number of padding elements of the source frame, range: [0, infinity)
741 * @param targetPaddingElements Optional number of padding elements of the target frame, range: [0, infinity)
742 * @param firstRow First row to be handled
743 * @param numberRows Number of rows to be handled
744 * @tparam tChannels Number of channels of the frame, with range [1, infinity)
745 */
746 template <unsigned int tChannels>
747 static void adjustColorToReferenceOfTargetSubset(const uint8_t* source, uint8_t* target, const unsigned int width, const unsigned int height, const LookupTable8BitPerChannel<tChannels>* lookupTable, const unsigned int firstColumn, const unsigned int numberColumns, const unsigned int sourcePaddingElements, const unsigned int targetPaddingElements, const unsigned int firstRow, const unsigned int numberRows);
748};
749
750/**
751 * Implementation of Contrast-Limited Adaptive Histogram Equalization (CLAHE).
752 * @ingroup cv
753 */
755{
756 public:
757
758 /// Number of bins in the tile histograms
759 static constexpr unsigned int histogramSize = 256u;
760
761 /// Tile histogram
762 typedef std::array<unsigned int, histogramSize> TileHistogram;
763
764 /// Image partitioning and tile boundary lookup
766
767 public:
768
769 /**
770 * Histogram equalization a la CLAHE
771 * @param source Pointer to the data of the source frame that will be processed, must be valid and 8-bit unsigned, 1-channel (`FrameType::FORMAT_Y8`)
772 * @param width The width of the source and target frames, range: [horizontalTiles, infinity)
773 * @param height The height of the source and target frames, range: [verticalTiles, infinity)
774 * @param target Destination location for the result, must be valid and 8-bit unsigned, 1-channel (`FrameType::FORMAT_Y8`) and have the same size as the source
775 * @param clipLimit Global scaling factor to determine the tile clip limit, `tileClipLimit = clipLimit * N`, where `N = (tileSize / histogramSize)` is the number of pixels per bin if all pixels are distributed evenly over the histogram (average), range: [0, infinity), default: 40
776 * @param horizontalTiles Number of tiles the source image will be split horizontally, range: [2, width], default: 8
777 * @param verticalTiles Number of tiles the source image will be split vertically, range: [2, height], default: 8
778 * @param sourcePaddingElements Number of padding elements in the source data, range: [0, infinity), default: 0
779 * @param targetPaddingElements Number of padding elements in the target data, range: [0, infinity), default: 0
780 * @param worker Optional worker instance for parallel execution, default: nullptr
781 */
782 static void equalization8BitPerChannel(const uint8_t* const source, const unsigned int width, const unsigned height, uint8_t* const target, const Scalar clipLimit = Scalar(40), const unsigned int horizontalTiles = 8u, const unsigned int verticalTiles = 8u, const unsigned int sourcePaddingElements = 0u, const unsigned int targetPaddingElements = 0u, Worker* worker = nullptr);
783
784 protected:
785
786 /**
787 * Computation of a lookup table required to normalize an image histogram (used per tile)
788 * @param source Pointer to the data of the source frame that will be processed, must be valid and 8-bit unsigned, 1-channel (`FrameType::FORMAT_Y8`)
789 * @param width The width of the source and target frames, range: [1, infinity)
790 * @param height The height of the source and target frames, range: [1, infinity)
791 * @param lookupTable Storage location for the computed lookup table, must be initialized, expected size: 256
792 * @param clipLimit Scaling factor to determine the tile clip limit, `tileClipLimit = clipLimit * N`, where `N = (tileSize / histogramSize)` is the number of pixels per bin if all pixels are distributed evenly over the histogram (average), range: [0, infinity)
793 * @param sourcePaddingElements Number of padding elements in the source data, range: [0, infinity), default: 0
794 */
795 static inline void computeLookupTable(const uint8_t* source, const unsigned int width, const unsigned int height, uint8_t* const lookupTable, const Scalar clipLimit, const unsigned int sourcePaddingElements = 0u);
796
797 /**
798 * Computation of per-tile lookup tables required to normalize an image histogram given a partitioned image
799 * @param source Pointer to the data of the source frame that will be processed, must be valid and 8-bit unsigned, 1-channel (`FrameType::FORMAT_Y8`)
800 * @param lookupCenter2 Defines how the source frame is partitioned, image size and number of bins will be extracted from this object, must be valid
801 * @param tileLookupTables Storage location for the computed lookup tables; will be initialized internally to size N x 256, where N = the total number of bins
802 * @param clipLimit Scaling factor to determine the tile clip limit, `tileClipLimit = clipLimit * N`, where `N = (tileSize / histogramSize)` is the number of pixels per bin if all pixels are distributed evenly over the histogram (average), range: [0, infinity)
803 * @param sourcePaddingElements Number of padding elements in the source data, range: [0, infinity), default: 0
804 * @param worker Optional worker instance for parallel execution, default: nullptr
805 */
806 static void computeTileLookupTables(const uint8_t* const source, const TileLookupCenter2& lookupCenter2, std::vector<uint8_t>& tileLookupTables, const Scalar clipLimit, const unsigned int sourcePaddingElements = 0u, Worker* worker = nullptr);
807
808 /**
809 * Computation of the bilinear interpolation parameters for the low bins of an image pixel
810 * If `isHorizontal == true`, this function computes the horizontal interpolation parameters, i.e., the left bins and left interpolation factors, otherwise it will compute the top bins and interpolation factors. For the horizontal parameters (`isHorizontal == true`), the right counterparts can be computed as:
811 *
812 * `rightBins[i] = lowBins[i] + 1u`
813 * `rightFactors_fixed7[i] = 128u - lowFactors_fixed7[i]`
814 *
815 * and, similarly, for the vertical parameters (`isHorizontal == false`).
816 *
817 * Note: 128u is the fixed-point, 7-bit precision equivalent of 1.0f
818 *
819 * @param lookupCenter2 Defines how the source frame is partitioned, image size and number of bins will be extracted from this object, must be valid, number of bins (`binsX()`) must >= 2
820 * @param isHorizontal If true, it will compute the horizontal interpolation parameters, otherwise the vertical parameters will be computed
821 * @param lowBins Stores the indices of the closest lower (lower = left if `isHorizontal == true`, otherwise lower = top) bins of a pixel location, must be initialized before calling this function, expected size: image width if `isHorizontal == true`, otherwise image height
822 * @param lowFactors_fixed7 Stores the horizontal (if `isHorizontal == true`) or vertical (if `isHorizontal == false`) interpolation factors for the lower bins (as 8-bit fixed point numbers with 7-bit precision, i.e. range: [0, 1]), must be initialized before calling this function, expected size: image width if `isHorizontal == true`, otherwise image height
823 */
824 static void computeLowBilinearInterpolationFactors7BitPrecision(const TileLookupCenter2& lookupCenter2, const bool isHorizontal, Index32* lowBins, uint8_t* lowFactors_fixed7);
825
826 /**
827 * Histogram normalization by bilinearly interpolating pixels using the CLAHE per-tile lookup tables
828 * @param source Pointer to the data of the source frame that will be processed, must be valid and 8-bit unsigned, 1-channel (`FrameType::FORMAT_Y8`)
829 * @param lookupCenter2 Defines how the source frame is partitioned, image size and number of bins will be extracted from this object, must be valid
830 * @param target Pointer to the data of the target frame, must be valid and 8-bit unsigned, 1-channel (`FrameType::FORMAT_Y8`)
831 * @param tileLookupTables Storage location for the computed lookup tables; will be initialized internally to size N x 256, where N = the total number of bins
832 * @param sourcePaddingElements Number of padding elements in the source data, range: [0, infinity), default: 0
833 * @param targetPaddingElements Number of padding elements in the target data, range: [0, infinity), default: 0
834 * @param worker Optional worker instance for parallel execution, default: nullptr
835 */
836 static void bilinearInterpolation(const uint8_t* const source, const TileLookupCenter2& lookupCenter2, uint8_t* const target, const std::vector<uint8_t>& tileLookupTables, const unsigned int sourcePaddingElements = 0u, const unsigned int targetPaddingElements = 0u, Worker* worker = nullptr);
837
838 /**
839 * Helper function for the computation of per-tile lookup tables required to normalize an image histogram given a partitioned image
840 * @param source Pointer to the data of the source frame that will be processed, must be valid and 8-bit unsigned, 1-channel (`FrameType::FORMAT_Y8`)
841 * @param lookupCenter2 Defines how the source frame is partitioned, image size and number of bins will be extracted from this object, must be valid
842 * @param tileLookupTables Storage location for the computed lookup tables; will be initialized internally to size N x 256, where N = the total number of bins
843 * @param clipLimit Scaling factor to determine the tile clip limit, `tileClipLimit = clipLimit * N`, where `N = (tileSize / histogramSize)` is the number of pixels per bin if all pixels are distributed evenly over the histogram (average), range: [0, infinity)
844 * @param sourcePaddingElements Number of padding elements in the source data, range: [0, infinity), default: 0
845 * @param firstTile Index of first tile to process, range: [0, N), where N is the total number of tiles
846 * @param tileCount Number of tiles to process, range: [1, N], such `firstTile + tileCount < N` where N is the total number of tiles
847 */
848 static void computeTileLookupTablesSubset(const uint8_t* const source, const TileLookupCenter2* lookupCenter2, uint8_t* const tileLookupTables, const Scalar clipLimit, const unsigned int sourcePaddingElements = 0u, const unsigned int firstTile = 0u, const unsigned int tileCount = 0u);
849
850 /**
851 * Integer-based (fixed-point arithmetic) helper function for the histogram normalization by bilinearly interpolating pixels using the CLAHE per-tile lookup tables
852 * @param source Pointer to the data of the source frame that will be processed, must be valid and 8-bit unsigned, 1-channel (`FrameType::FORMAT_Y8`)
853 * @param lookupCenter2 Defines how the source frame is partitioned, image size and number of bins will be extracted from this object, must be valid
854 * @param target Pointer to the data of the target frame, must be valid and 8-bit unsigned, 1-channel (`FrameType::FORMAT_Y8`)
855 * @param tileLookupTables Storage location for the computed lookup tables; will be initialized internally to size N x 256, where N = the total number of bins
856 * @param leftBins Stores the indices of the closest bins left of a horizontal pixel location, must be initialized, expected size: image width
857 * @param leftFactors_fixed7 Stores the horizontal interpolation factors for the left bins (as fixed-point number with 7-bit precision), must be initialized, expected size: image width
858 * @param sourcePaddingElements Number of padding elements in the source data, range: [0, infinity), default: 0
859 * @param targetPaddingElements Number of padding elements in the target data, range: [0, infinity), default: 0
860 * @param rowStart First image row to process, range: [0, height)
861 * @param rowCount Number of rows to process, range: [0, height - rowStart)
862 */
863 static void bilinearInterpolation7BitPrecisionSubset(const uint8_t* const source, const TileLookupCenter2* lookupCenter2, uint8_t* const target, const uint8_t* const tileLookupTables, const Index32* const leftBins, const uint8_t* const leftFactors_fixed7, const unsigned int sourcePaddingElements = 0u, const unsigned int targetPaddingElements = 0u, const unsigned int rowStart = 0u, const unsigned int rowCount = 0u);
864
865#if defined(OCEAN_HARDWARE_NEON_VERSION) && OCEAN_HARDWARE_NEON_VERSION >= 10
866
867 /**
868 * Helper function for the histogram normalization by bilinearly interpolating pixels using the CLAHE per-tile lookup tables
869 * @param source Pointer to the data of the source frame that will be processed, must be valid and 8-bit unsigned, 1-channel (`FrameType::FORMAT_Y8`)
870 * @param lookupCenter2 Defines how the source frame is partitioned, image size and number of bins will be extracted from this object, must be valid
871 * @param target Pointer to the data of the target frame, must be valid and 8-bit unsigned, 1-channel (`FrameType::FORMAT_Y8`)
872 * @param tileLookupTables Storage location for the computed lookup tables; will be initialized internally to size N x 256, where N = the total number of bins
873 * @param leftBins Stores the indices of the closest bins left of a horizontal pixel location, must be initialized, expected size: image width
874 * @param leftFactors_fixed7 Stores the horizontal interpolation factors for the left bins (as fixed-point number with 7-bit precision), must be initialized, expected size: image width
875 * @param topBins Stores the indices of the closest vertical bins above a pixel location, must be initialized, expected size: image height
876 * @param topFactors_fixed7 Stores the vertical interpolation factors for the top bins (as fixed-point number with 7-bit precision), must be initialized, expected size: image height
877 * @param sourcePaddingElements Number of padding elements in the source data, range: [0, infinity), default: 0
878 * @param targetPaddingElements Number of padding elements in the target data, range: [0, infinity), default: 0
879 * @param tileStart First tile to process, range: [0, N), where N = number of tiles
880 * @param tileCount Number of tiles to process, range: [0, N - tileStart)
881 */
882 static void bilinearInterpolationNEON7BitPrecisionSubset(const uint8_t* const source, const TileLookupCenter2* lookupCenter2, uint8_t* const target, const uint8_t* const tileLookupTables, const Index32* const leftBins, const uint8_t* const leftFactors_fixed7, const Index32* const topBins, const uint8_t* const topFactors_fixed7, const unsigned int sourcePaddingElements = 0u, const unsigned int targetPaddingElements = 0u, const unsigned int tileStart = 0u, const unsigned int tileCount = 0u);
883
884#endif // OCEAN_HARDWARE_NEON_VERSION >= 10
885};
886
887inline void ContrastLimitedAdaptiveHistogram::computeLookupTable(const uint8_t* source, const unsigned int width, const unsigned int height, uint8_t* const lookupTable, const Scalar clipLimit, const unsigned int sourcePaddingElements)
888{
889 ocean_assert(source != nullptr);
890 ocean_assert(width != 0u && height != 0u);
891 ocean_assert(lookupTable != nullptr);
892 ocean_assert(clipLimit >= Scalar(0));
893
894 const unsigned int sourceArea = width * height;
895 const unsigned int sourceStrideElements = width + sourcePaddingElements;
896 const uint8_t* const sourceEnd = source + height * sourceStrideElements;
897
898 // Histogram computation
899 TileHistogram histogram;
900 memset(histogram.data(), 0u, histogram.size() * sizeof(TileHistogram::value_type));
901 const unsigned int widthEnd = width >= 4u ? width - 4u : 0u;
902
903 for (unsigned int y = 0u; y < height; ++y)
904 {
905 unsigned int x = 0u;
906
907 while (x < widthEnd)
908 {
909 ocean_assert_and_suppress_unused(source + x + 3u < sourceEnd, sourceEnd);
910 histogram[source[x + 0u]]++;
911 histogram[source[x + 1u]]++;
912 histogram[source[x + 2u]]++;
913 histogram[source[x + 3u]]++;
914
915 x += 4u;
916 }
917
918 while (x < width)
919 {
920 ocean_assert(source + x < sourceEnd);
921 histogram[source[x]]++;
922
923 ++x;
924 }
925
926 source += sourceStrideElements;
927 }
928
929 // Clip histogram peaks and redistribute area exceeding the clip limit
930 ocean_assert(histogramSize != 0u);
931 const unsigned int scaledClipLimit = std::max(1u, (unsigned int)(clipLimit * float(sourceArea) / float(histogramSize)));
932 unsigned int clippedArea = 0u;
933
934 for (unsigned int i = 0u; i < histogramSize; ++i)
935 {
936 if (histogram[i] > scaledClipLimit)
937 {
938 clippedArea += histogram[i] - scaledClipLimit;
939 histogram[i] = scaledClipLimit;
940 }
941 }
942
943 if (clippedArea != 0u)
944 {
945 const unsigned int redistribution = clippedArea / histogramSize;
946 const unsigned int residual = clippedArea - (redistribution * histogramSize);
947
948 for (unsigned int i = 0u; i < residual; ++i)
949 {
950 histogram[i] += (redistribution + 1u);
951 }
952
953 for (unsigned int i = residual; i < histogramSize; ++i)
954 {
955 histogram[i] += redistribution;
956 }
957 }
958
959 // Normalize histogram (CDF + normalization)
960 ocean_assert(sourceArea != 0u);
961 const float normalizationFactor = float(histogramSize - 1u) / float(sourceArea);
962 unsigned int sum = 0u;
963
964 for (unsigned int i = 0u; i < histogramSize; ++i)
965 {
966 sum += histogram[i];
967
968 ocean_assert((int)(float(sum) * normalizationFactor + 0.5f) >= 0);
969 ocean_assert((int)(float(sum) * normalizationFactor + 0.5f) <= (int)(NumericT<uint8_t>::maxValue()));
970 lookupTable[i] = (uint8_t)(float(sum) * normalizationFactor + 0.5f);
971 }
972}
973
974template <unsigned int tChannels>
976{
977 memset(histogramBins, 0x00, sizeof(unsigned int) * 256u * tChannels);
978}
979
980template <unsigned int tChannels>
981template <unsigned int tChannel>
982inline unsigned int Histogram::HistogramBase8BitPerChannel<tChannels>::bin(const uint8_t index) const
983{
984 static_assert(tChannel < tChannels, "Invalid channel index!");
985
986 return histogramBins[tChannel * 256u + index];
987}
988
989template <unsigned int tChannels>
990inline unsigned int Histogram::HistogramBase8BitPerChannel<tChannels>::bin(const unsigned int channel, const uint8_t index) const
991{
992 ocean_assert(channel < tChannels);
993
994 return histogramBins[channel * 256u + index];
995}
996
997template <unsigned int tChannels>
998inline unsigned int Histogram::HistogramBase8BitPerChannel<tChannels>::sumBin(const uint8_t index) const
999{
1000 unsigned int result = 0u;
1001
1002 for (unsigned int n = 0u; n < tChannels; ++n)
1003 {
1004 result += histogramBins[n * 256u + index];
1005 }
1006
1007 return result;
1008}
1009
1010template <unsigned int tChannels>
1011template <unsigned int tChannel>
1013{
1014 static_assert(tChannel < tChannels, "Invalid channel index!");
1015
1016 return histogramBins + 256u * tChannel;
1017}
1018
1019template <unsigned int tChannels>
1020inline const unsigned int* Histogram::HistogramBase8BitPerChannel<tChannels>::bins(const unsigned int channel) const
1021{
1022 ocean_assert(channel < tChannels);
1023
1024 return histogramBins + 256u * channel;
1025}
1026
1027template <unsigned int tChannels>
1028template <unsigned int tChannel>
1030{
1031 static_assert(tChannel < tChannels, "Invalid channel index!");
1032
1033 unsigned int value = 0u;
1034 const unsigned int* bins = histogramBins + 256u * tChannel;
1035
1036 for (unsigned int n = 0u; n < 256u; ++n)
1037 {
1038 if (bins[n] > value)
1039 {
1040 value = bins[n];
1041 }
1042 }
1043
1044 return value;
1045}
1046
1047template <unsigned int tChannels>
1049{
1050 ocean_assert(channel < tChannels);
1051
1052 unsigned int value = 0u;
1053 const unsigned int* bins = histogramBins + 256u * channel;
1054
1055 for (unsigned int n = 0u; n < 256u; ++n)
1056 {
1057 if (bins[n] > value)
1058 {
1059 value = bins[n];
1060 }
1061 }
1062
1063 return value;
1064}
1065
1066template <unsigned int tChannels>
1068{
1069 unsigned int value = 0u;
1070
1071 for (unsigned int n = 0u; n < 256u * tChannels; ++n)
1072 {
1073 if (histogramBins[n] > value)
1074 {
1075 value = histogramBins[n];
1076 }
1077 }
1078
1079 return value;
1080}
1081
1082template <unsigned int tChannels>
1084{
1085 ocean_assert(channel < tChannels);
1086
1087 const unsigned int* bins = histogramBins + 256u * channel;
1088
1089 for (unsigned int n = 0u; n < 256u; ++n)
1090 {
1091 if (bins[n] != 0u)
1092 {
1093 return n;
1094 }
1095 }
1096
1097 return (unsigned int)(-1);
1098}
1099
1100template <unsigned int tChannels>
1102{
1103 ocean_assert(channel < tChannels);
1104
1105 const unsigned int* bins = histogramBins + 256u * channel;
1106
1107 for (unsigned int n = 255u; n < 256u; --n)
1108 {
1109 if (bins[n] != 0u)
1110 {
1111 return n;
1112 }
1113 }
1114
1115 return (unsigned int)(-1);
1116}
1117
1118template <unsigned int tChannels>
1119inline void Histogram::HistogramBase8BitPerChannel<tChannels>::normalize(const unsigned int newMaximalValue)
1120{
1121 const unsigned int maximalValue = determineHighestValue();
1122
1123 if (maximalValue == 0u)
1124 {
1125 return;
1126 }
1127
1128 const unsigned int maximalValue_2 = maximalValue / 2u;
1129
1130 for (unsigned int n = 0u; n < 256u * tChannels; ++n)
1131 {
1132 histogramBins[n] = (histogramBins[n] * newMaximalValue + maximalValue_2) / maximalValue;
1133 }
1134}
1135
1136template <unsigned int tChannels>
1137inline void Histogram::HistogramBase8BitPerChannel<tChannels>::normalize(const unsigned int channel, const unsigned int newMaximalValue)
1138{
1139 ocean_assert(channel < tChannels);
1140
1141 const unsigned int maximalValue = determineHighestValue(channel);
1142
1143 if (maximalValue == 0u)
1144 {
1145 return;
1146 }
1147
1148 const unsigned int maximalValue_2 = maximalValue / 2u;
1149
1150 unsigned int* bins = histogramBins + 256u * channel;
1151
1152 for (unsigned int n = 0u; n < 256u; ++n)
1153 {
1154 bins[n] = (bins[n] * newMaximalValue + maximalValue_2) / maximalValue;
1155 }
1156}
1157
1158template <unsigned int tChannels>
1160{
1161 memset(histogramBins, 0x00, sizeof(unsigned int) * 256u * tChannels);
1162}
1163
1164template <unsigned int tChannels>
1166{
1167 for (unsigned int n = 0u; n < 256u * tChannels; ++n)
1168 {
1169 if (histogramBins[n] != histogram.histogramBins[n])
1170 {
1171 return false;
1172 }
1173 }
1174
1175 return true;
1176}
1177
1178template <unsigned int tChannels>
1180{
1181 return !(*this == histogram);
1182}
1183
1184template <unsigned int tChannels>
1186{
1187 for (unsigned int n = 0u; n < 256u * tChannels; ++n)
1188 {
1190 }
1191
1192 return *this;
1193}
1194
1195template <unsigned int tChannels>
1197{
1198 return histogramBins;
1199}
1200
1201template <unsigned int tChannels>
1202void Histogram::HistogramBase8BitPerChannel<tChannels>::setBin(const unsigned int channel, const uint8_t index, const unsigned int value)
1203{
1204 ocean_assert(channel < tChannels);
1205
1206 histogramBins[channel * 256u + index] = value;
1207}
1208
1209template <unsigned int tChannels>
1211{
1212 for (unsigned int n = 0u; n < 256u * tChannels; ++n)
1213 {
1214 if (histogramBins[n] != 0u)
1215 {
1216 return false;
1217 }
1218 }
1219
1220 return true;
1221}
1222
1223template <unsigned int tChannels>
1225 HistogramBase8BitPerChannel<tChannels>()
1226{
1227 // nothing to do here
1228}
1229
1230template <unsigned int tChannels>
1231template <unsigned int tChannel>
1233{
1234 static_assert(tChannel < tChannels, "Invalid channel index!");
1235
1237}
1238
1239template <unsigned int tChannels>
1240inline void Histogram::Histogram8BitPerChannel<tChannels>::incrementBin(const unsigned int channel, const uint8_t index)
1241{
1242 ocean_assert(channel < tChannels);
1243
1245}
1246
1247template <unsigned int tChannels>
1249{
1250 ocean_assert(pixel != nullptr);
1251
1252 for (unsigned int n = 0u; n < tChannels; ++n)
1253 {
1255 }
1256}
1257
1258template <unsigned int tChannels>
1260{
1262
1263 for (unsigned int n = 0u; n < 256u * tChannels; ++n)
1264 {
1266 }
1267
1268 return result;
1269}
1270
1271template <unsigned int tChannels>
1277
1278template <unsigned int tChannels>
1280 HistogramBase8BitPerChannel<tChannels>()
1281{
1282 for (unsigned int c = 0u; c < tChannels; ++c)
1283 {
1284 const unsigned int* const bins = histogram.bins(c);
1285 unsigned int* const thisBins = HistogramBase8BitPerChannel<tChannels>::histogramBins + 256u * c;
1286
1287 // copy the first bin
1288 thisBins[0] = bins[0];
1289
1290 // copy and increment the remaining bins
1291 for (unsigned int b = 1u; b < 256u; ++b)
1292 {
1293 thisBins[b] = thisBins[b - 1u] + bins[b];
1294 }
1295 }
1296
1297#ifdef OCEAN_DEBUG
1298
1299 // check whether the increment values are identical
1300 for (unsigned int c = 1u; c < tChannels; ++c)
1301 {
1303 }
1304
1305#endif // OCEAN_DEBUG
1306}
1307
1308template <unsigned int tChannels>
1310{
1312
1314
1315 for (unsigned int c = 0u; c < tChannels; ++c)
1316 {
1317 for (unsigned int n = 0u; n < 256u; ++n)
1318 {
1319 const unsigned int value = HistogramBase8BitPerChannel<tChannels>::bin(c, (uint8_t)(n));
1320
1321 for (int r = int(value); r >= 0; --r)
1322 {
1323 if (result.bin(c, (uint8_t)(r)) == 0)
1324 {
1325 result.setBin(c, (uint8_t)(r), n);
1326 }
1327 else
1328 {
1329 break;
1330 }
1331 }
1332 }
1333 }
1334
1335 return result;
1336}
1337
1338template <unsigned int tChannels>
1340{
1341 for (unsigned int c = 0u; c < tChannels; ++c)
1342 {
1343 for (unsigned int n = 0u; n < 256u; ++n)
1344 {
1345 lookupData[c * 256u + n] = n;
1346 }
1347 }
1348}
1349
1350template <unsigned int tChannels>
1352{
1353 ocean_assert(normalizedHistogram.determineHighestValue() <= 255u);
1354 ocean_assert(invertedNormalizedHistogram.determineHighestValue() <= 255u);
1355
1356 for (unsigned int c = 0u; c < tChannels; ++c)
1357 {
1358 for (unsigned int n = 0u; n < 256u; ++n)
1359 {
1360 lookupData[c * 256u + n] = (uint8_t)(invertedNormalizedHistogram.bin(c, (uint8_t)(normalizedHistogram.bin(c, (uint8_t)(n)))));
1361 }
1362 }
1363}
1364
1365template <unsigned int tChannels>
1366template <unsigned int tChannel>
1368{
1369 static_assert(tChannel < tChannels, "Invalid channel!");
1370
1371 return lookupData[tChannel * 256u + index];
1372}
1373
1374template <unsigned int tChannels>
1375uint8_t Histogram::LookupTable8BitPerChannel<tChannels>::lookup(const unsigned int channel, const uint8_t index) const
1376{
1377 ocean_assert(channel < tChannels);
1378
1379 return lookupData[channel * 256u + index];
1380}
1381
1382template <unsigned int tChannels>
1383Histogram::Histogram8BitPerChannel<tChannels> Histogram::determineHistogram8BitPerChannel(const uint8_t* frame, const unsigned int width, const unsigned int height, const unsigned int framePaddingElements, Worker* worker)
1384{
1385 ocean_assert(frame && width >= 1u && height >= 1u);
1386
1388
1389 if (worker)
1390 {
1391 Lock lock;
1392 worker->executeFunction(Worker::Function::createStatic(determineHistogram8BitPerChannelSubset<tChannels>, frame, width, height, &result, &lock, 0u, width, framePaddingElements, 0u, 0u), 0u, height, 8u, 9u, 20u);
1393 }
1394 else
1395 {
1396 if (framePaddingElements == 0u)
1397 {
1398 const uint8_t* const frameEnd = frame + height * width * tChannels;
1399
1400 while (frame != frameEnd)
1401 {
1402 result.increment(frame);
1403 frame += tChannels;
1404 }
1405 }
1406 else
1407 {
1408 for (unsigned int y = 0u; y < height; ++y)
1409 {
1410 for (unsigned int x = 0u; x < width; ++x)
1411 {
1412 result.increment(frame);
1413 frame += tChannels;
1414 }
1415
1416 frame += framePaddingElements;
1417 }
1418 }
1419 }
1420
1421 return result;
1422}
1423
1424template <unsigned int tChannels>
1425Histogram::Histogram8BitPerChannel<tChannels> Histogram::determineHistogram8BitPerChannel(const uint8_t* frame, const unsigned int width, const unsigned int height, const unsigned int subframeLeft, const unsigned int subframeTop, const unsigned int subframeWidth, const unsigned int subframeHeight, const unsigned int framePaddingElements, Worker* worker)
1426{
1427 ocean_assert(frame && width >= 1u && height >= 1u);
1428
1429 ocean_assert(subframeLeft + subframeWidth <= width);
1430 ocean_assert(subframeTop + subframeHeight <= height);
1431
1433
1434 if (worker)
1435 {
1436 Lock lock;
1437 worker->executeFunction(Worker::Function::createStatic(determineHistogram8BitPerChannelSubset<tChannels>, frame, width, height, &result, &lock, subframeLeft, subframeWidth, framePaddingElements, 0u, 0u), subframeTop, subframeHeight, 8u, 9u, 20u);
1438 }
1439 else
1440 {
1441 determineHistogram8BitPerChannelSubset<tChannels>(frame, width, height, &result, nullptr, subframeLeft, subframeWidth, framePaddingElements, subframeTop, subframeHeight);
1442 }
1443
1444 return result;
1445}
1446
1447template <unsigned int tChannels>
1448bool Histogram::adjustColorToReference(uint8_t* frame, const unsigned int frameWidth, const unsigned int frameHeight, const uint8_t* reference, const unsigned int referenceWidth, const unsigned int referenceHeight, const unsigned int horizontalBins, const unsigned int verticalBins, const unsigned int framePaddingElements, const unsigned int referencePaddingElements, Worker* worker)
1449{
1450 ocean_assert(frame != nullptr && reference != nullptr);
1451
1452 ocean_assert(horizontalBins > 0u && verticalBins > 0u);
1453 ocean_assert(horizontalBins <= min(frameWidth, referenceWidth));
1454 ocean_assert(verticalBins <= min(frameHeight, referenceHeight));
1455
1456 if (frame == nullptr || reference == nullptr || verticalBins == 0u || horizontalBins == 0u || horizontalBins > frameWidth || horizontalBins > referenceWidth || verticalBins > frameHeight || verticalBins > referenceHeight)
1457 {
1458 return false;
1459 }
1460
1461 std::vector<LookupTable8BitPerChannel<tChannels>> lookups;
1462 lookups.reserve(horizontalBins * verticalBins);
1463
1464 // create reference histograms
1465 for (unsigned int y = 0; y < verticalBins; ++y)
1466 {
1467 for (unsigned int x = 0; x < horizontalBins; ++x)
1468 {
1469 const unsigned int referenceBinLeft = x * referenceWidth / horizontalBins;
1470 const unsigned int referenceBinTop = y * referenceHeight / verticalBins;
1471
1472 const unsigned int referenceBinRight = min((x + 1) * referenceWidth / horizontalBins, referenceWidth);
1473 const unsigned int referenceBinBottom = min((y + 1) * referenceHeight / verticalBins, referenceHeight);
1474
1475 const unsigned int referenceBinWidth = referenceBinRight - referenceBinLeft;
1476 const unsigned int referenceBinHeight = referenceBinBottom - referenceBinTop;
1477
1478 IntegralHistogram8BitPerChannel<tChannels> integralReferenceHistogram(determineHistogram8BitPerChannel<tChannels>(reference, referenceWidth, referenceHeight, referenceBinLeft, referenceBinTop, referenceBinWidth, referenceBinHeight, referencePaddingElements, worker));
1479 integralReferenceHistogram.normalize(0xFF);
1480
1481 const unsigned int frameBinLeft = x * frameWidth / horizontalBins;
1482 const unsigned int frameBinTop = y * frameHeight / verticalBins;
1483
1484 const unsigned int frameBinRight = min((x + 1) * frameWidth / horizontalBins, frameWidth);
1485 const unsigned int frameBinBottom = min((y + 1) * frameHeight / verticalBins, frameHeight);
1486
1487 const unsigned int frameBinWidth = frameBinRight - frameBinLeft;
1488 const unsigned int frameBinHeight = frameBinBottom - frameBinTop;
1489
1490 IntegralHistogram8BitPerChannel<tChannels> frameHistogram(determineHistogram8BitPerChannel<tChannels>(frame, frameWidth, frameHeight, frameBinLeft, frameBinTop, frameBinWidth, frameBinHeight, framePaddingElements, worker));
1491 frameHistogram.normalize(0xFF);
1492
1493 lookups.push_back(LookupTable8BitPerChannel<tChannels>(frameHistogram, integralReferenceHistogram.invert()));
1494 }
1495 }
1496
1497 const unsigned int frameStrideElements = frameWidth * tChannels + framePaddingElements;
1498
1499 for (unsigned int y = 0u; y < frameHeight; ++y)
1500 {
1501 for (unsigned int x = 0u; x < frameWidth; ++x)
1502 {
1503 const unsigned int xBin = (x * horizontalBins) / frameWidth;
1504 const unsigned int yBin = (y * verticalBins) / frameHeight;
1505
1506 const unsigned int xBinCenter = (xBin * frameWidth / horizontalBins + min((xBin + 1u) * frameWidth / horizontalBins, frameWidth)) / 2u;
1507 const unsigned int yBinCenter = (yBin * frameHeight / verticalBins + min((yBin + 1u) * frameHeight / verticalBins, frameHeight)) / 2u;
1508
1509 ocean_assert(xBinCenter < frameWidth);
1510 ocean_assert(yBinCenter < frameHeight);
1511
1512 const unsigned int xLowBin = (x >= xBinCenter) ? xBin : max(0, int(xBin) - 1);
1513 const unsigned int xHighBin = (x < xBinCenter) ? xBin : min(xLowBin + 1u, horizontalBins - 1u);
1514
1515 const unsigned int yLowBin = (y >= yBinCenter) ? yBin : max(0, int(yBin) - 1);
1516 const unsigned int yHighBin = (y < yBinCenter) ? yBin : min(yLowBin + 1u, verticalBins - 1u);
1517
1518 ocean_assert(((xLowBin == 0u || xLowBin == horizontalBins - 1u) && xHighBin == xLowBin) || xLowBin + 1u == xHighBin);
1519 ocean_assert(((yLowBin == 0u || yLowBin == verticalBins - 1u) && yHighBin == yLowBin) || yLowBin + 1u == yHighBin);
1520
1521 const unsigned int leftCenter = (xLowBin * frameWidth / horizontalBins + min((xLowBin + 1u) * frameWidth / horizontalBins, frameWidth)) / 2u;
1522 const unsigned int rightCenter = (xHighBin * frameWidth / horizontalBins + min((xHighBin + 1u) * frameWidth / horizontalBins, frameWidth)) / 2u;
1523
1524 const unsigned int topCenter = (yLowBin * frameHeight / verticalBins + min((yLowBin + 1u) * frameHeight / verticalBins, frameHeight)) / 2u;
1525 const unsigned int bottomCenter = (yHighBin * frameHeight / verticalBins + min((yHighBin + 1u) * frameHeight / verticalBins, frameHeight)) / 2u;
1526
1527
1528 ocean_assert(leftCenter <= rightCenter);
1529 ocean_assert(topCenter <= bottomCenter);
1530
1531 const unsigned int centerWidth = rightCenter - leftCenter;
1532 const unsigned int centerHeight = bottomCenter - topCenter;
1533
1534 const unsigned int xFactor = centerWidth != 0u ? (abs(int(x) - int(leftCenter)) * 256u + centerWidth / 2u) / centerWidth : 256u;
1535 const unsigned int yFactor = centerHeight != 0u ? (abs(int(y) - int(topCenter)) * 256u + centerHeight / 2u) / centerHeight : 256u;
1536
1537 ocean_assert(xFactor <= 256u);
1538 ocean_assert(yFactor <= 256u);
1539
1540 uint8_t* const framePixel = frame + y * frameStrideElements + x * tChannels;
1541
1542 const LookupTable8BitPerChannel<tChannels>& topLeft = lookups[yLowBin * horizontalBins + xLowBin];
1543 const LookupTable8BitPerChannel<tChannels>& topRight = lookups[yLowBin * horizontalBins + xHighBin];
1544 const LookupTable8BitPerChannel<tChannels>& bottomLeft = lookups[yHighBin * horizontalBins + xLowBin];
1545 const LookupTable8BitPerChannel<tChannels>& bottomRight = lookups[yHighBin * horizontalBins + xHighBin];
1546
1547 const unsigned int factorTopLeft = (256u - xFactor) * (256u - yFactor);
1548 const unsigned int factorTopRight = xFactor * (256u - yFactor);
1549 const unsigned int factorBottomLeft = (256u - xFactor) * yFactor;
1550 const unsigned int factorBottomRight = xFactor * yFactor;
1551
1552 for (unsigned int n = 0u; n < tChannels; ++n)
1553 {
1554 const uint8_t value = framePixel[n];
1555
1556 framePixel[n] = (uint8_t)((topLeft.lookup(n, value) * factorTopLeft + topRight.lookup(n, value) * factorTopRight
1557 + bottomLeft.lookup(n, value) * factorBottomLeft + bottomRight.lookup(n, value) * factorBottomRight + 32768u) >> 16u); // / 65536;
1558 }
1559 }
1560 }
1561
1562 return true;
1563}
1564
1565template <unsigned int tChannels>
1566inline bool Histogram::equalization(uint8_t* frame, const unsigned int width, const unsigned int height, const Scalar factor, const unsigned int framePaddingElements, Worker* worker)
1567{
1568 ocean_assert(frame && width > 0u && height > 0u);
1569 ocean_assert(factor >= 0 && factor <= 1);
1570
1571 if (factor < 0 || factor > 1)
1572 {
1573 return false;
1574 }
1575
1576 IntegralHistogram8BitPerChannel<tChannels> integralHistogram(determineHistogram8BitPerChannel<tChannels>(frame, width, height, framePaddingElements, worker));
1577 integralHistogram.normalize(0xFF);
1578
1579 return equalization<tChannels>(frame, width, height, integralHistogram, factor, framePaddingElements, worker);
1580}
1581
1582template <unsigned int tChannels>
1583inline bool Histogram::equalization(const uint8_t* source, uint8_t* target, const unsigned int width, const unsigned int height, const Scalar factor, const unsigned int sourcePaddingElements, const unsigned int targetPaddingElements, Worker* worker)
1584{
1585 ocean_assert(source && target && width > 0u && height > 0u);
1586 ocean_assert(factor >= 0 && factor <= 1);
1587
1588 if (factor < 0 || factor > 1)
1589 {
1590 return false;
1591 }
1592
1593 IntegralHistogram8BitPerChannel<tChannels> integralHistogram(determineHistogram8BitPerChannel<tChannels>(source, width, height, sourcePaddingElements, worker));
1594 integralHistogram.normalize(0xFF);
1595
1596 return equalization<tChannels>(source, target, width, height, integralHistogram, factor, sourcePaddingElements, targetPaddingElements, worker);
1597}
1598
1599template <unsigned int tChannels>
1600inline bool Histogram::equalization(uint8_t* frame, const unsigned int width, const unsigned int height, const IntegralHistogram8BitPerChannel<tChannels>& normalizedIntegral, const Scalar factor, const unsigned int framePaddingElements, Worker* worker)
1601{
1602 return equalization<tChannels>(frame, width, height, 0u, 0u, width, height, normalizedIntegral, factor, framePaddingElements, worker);
1603}
1604
1605template <unsigned int tChannels>
1606bool Histogram::equalization(uint8_t* frame, const unsigned int width, const unsigned int height, const unsigned int subframeLeft, const unsigned int subframeTop, const unsigned int subframeWidth, const unsigned int subframeHeight, const IntegralHistogram8BitPerChannel<tChannels>& normalizedIntegral, const Scalar factor, const unsigned int framePaddingElements, Worker* worker)
1607{
1608 ocean_assert(frame && width > 0u && height > 0u);
1609 ocean_assert(factor >= 0 && factor <= 1);
1610
1611 ocean_assert(subframeLeft + subframeWidth <= width);
1612 ocean_assert(subframeTop + subframeHeight <= height);
1613
1614 if (factor < 0 || factor > 1 || subframeLeft + subframeWidth > width || subframeTop + subframeHeight > height)
1615 {
1616 return false;
1617 }
1618
1619 const unsigned int iFactor = (unsigned int)(factor * Scalar(256));
1620
1621 if (worker)
1622 {
1623 worker->executeFunction(Worker::Function::createStatic(equalizationSubset<tChannels>, frame, width, height, (const IntegralHistogram8BitPerChannel<tChannels>*)&normalizedIntegral, iFactor, subframeLeft, subframeWidth, framePaddingElements, 0u, 0u), 0u, height, 8u, 9u, 20u);
1624 }
1625 else
1626 {
1627 equalizationSubset<tChannels>(frame, width, height, &normalizedIntegral, iFactor, subframeLeft, subframeWidth, framePaddingElements, subframeTop, subframeHeight);
1628 }
1629
1630 return true;
1631}
1632
1633template <unsigned int tChannels>
1634inline bool Histogram::equalization(const uint8_t* source, uint8_t* target, const unsigned int width, const unsigned int height, const IntegralHistogram8BitPerChannel<tChannels>& normalizedIntegral, const Scalar factor, const unsigned int sourcePaddingElements, const unsigned int targetPaddingElements, Worker* worker)
1635{
1636 return equalization<tChannels>(source, target, width, height, 0u, 0u, width, height, normalizedIntegral, factor, sourcePaddingElements, targetPaddingElements, worker);
1637}
1638
1639template <unsigned int tChannels>
1640bool Histogram::equalization(const uint8_t* source, uint8_t* target, const unsigned int width, const unsigned int height, const unsigned int subframeLeft, const unsigned int subframeTop, const unsigned int subframeWidth, const unsigned int subframeHeight, const IntegralHistogram8BitPerChannel<tChannels>& normalizedIntegral, const Scalar factor, const unsigned int sourcePaddingElements, const unsigned int targetPaddingElements, Worker* worker)
1641{
1642 ocean_assert(source && target && width > 0u && height > 0u);
1643 ocean_assert(factor >= 0 && factor <= 1);
1644
1645 ocean_assert(subframeLeft + subframeWidth <= width);
1646 ocean_assert(subframeTop + subframeHeight <= height);
1647
1648 if (factor < 0 || factor > 1 || subframeLeft + subframeWidth > width || subframeTop + subframeHeight > height)
1649 {
1650 return false;
1651 }
1652
1653 const unsigned int iFactor = (unsigned int)(factor * Scalar(256));
1654
1655 if (worker)
1656 {
1657 worker->executeFunction(Worker::Function::createStatic(equalizationOfTargetSubset<tChannels>, source, target, width, height, &normalizedIntegral, iFactor, subframeLeft, subframeWidth, sourcePaddingElements, targetPaddingElements, 0u, 0u), subframeTop, subframeHeight, 10u, 11u, 20u);
1658 }
1659 else
1660 {
1661 equalizationOfTargetSubset<tChannels>(source, target, width, height, &normalizedIntegral, iFactor, subframeLeft, subframeWidth, sourcePaddingElements, targetPaddingElements, subframeTop, subframeHeight);
1662 }
1663
1664 return true;
1665}
1666
1667template <unsigned int tChannels>
1668bool Histogram::adjustColorToReference(uint8_t* frame, const unsigned int frameWidth, const unsigned int frameHeight, const uint8_t* reference, const unsigned int referenceWidth, const unsigned int referenceHeight, const unsigned int framePaddingElements, const unsigned int referencePaddingElements, Worker* worker)
1669{
1670 ocean_assert(frame && reference);
1671
1672 IntegralHistogram8BitPerChannel<tChannels> integralReferenceHistogram(determineHistogram8BitPerChannel<tChannels>(reference, referenceWidth, referenceHeight, referencePaddingElements, worker));
1673 integralReferenceHistogram.normalize(0xFF);
1674 const IntegralHistogram8BitPerChannel<tChannels> invertedReferenceHistogram(integralReferenceHistogram.invert());
1675
1676 return adjustColorToReference<tChannels>(frame, frameWidth, frameHeight, invertedReferenceHistogram, framePaddingElements, worker);
1677}
1678
1679template <unsigned int tChannels>
1680bool Histogram::adjustColorToReference(const uint8_t* source, uint8_t* target, const unsigned int sourceWidth, const unsigned int sourceHeight, const uint8_t* reference, const unsigned int referenceWidth, const unsigned int referenceHeight, const unsigned int sourcePaddingElements, const unsigned int targetPaddingElements, const unsigned int referencePaddingElements, Worker* worker)
1681{
1682 ocean_assert(source && target && reference);
1683
1684 IntegralHistogram8BitPerChannel<tChannels> integralReferenceHistogram(determineHistogram8BitPerChannel<tChannels>(reference, referenceWidth, referenceHeight, referencePaddingElements, worker));
1685 integralReferenceHistogram.normalize(0xFF);
1686 const IntegralHistogram8BitPerChannel<tChannels> invertedReferenceHistogram(integralReferenceHistogram.invert());
1687
1688 return adjustColorToReference<tChannels>(source, target, sourceWidth, sourceHeight, invertedReferenceHistogram, sourcePaddingElements, targetPaddingElements, worker);
1689}
1690
1691template <unsigned int tChannels>
1692inline bool Histogram::adjustColorToReference(uint8_t* frame, const unsigned int width, const unsigned int height, const IntegralHistogram8BitPerChannel<tChannels>& invertedNormalizedReferenceIntegral, const unsigned int framePaddingElements, Worker* worker)
1693{
1694 return adjustColorToReference<tChannels>(frame, width, height, 0u, 0u, width, height, invertedNormalizedReferenceIntegral, framePaddingElements, worker);
1695}
1696
1697template <unsigned int tChannels>
1698bool Histogram::adjustColorToReference(uint8_t* frame, const unsigned int width, const unsigned int height, const unsigned int subframeLeft, const unsigned int subframeTop, const unsigned int subframeWidth, const unsigned int subframeHeight, const IntegralHistogram8BitPerChannel<tChannels>& invertedNormalizedReferenceIntegral, const unsigned int framePaddingElements, Worker* worker)
1699{
1700 ocean_assert(frame);
1701
1702 if (!frame || subframeLeft + subframeWidth > width || subframeTop + subframeHeight > height)
1703 {
1704 return false;
1705 }
1706
1707 IntegralHistogram8BitPerChannel<tChannels> frameHistogram(determineHistogram8BitPerChannel<tChannels>(frame, width, height, framePaddingElements, worker));
1708 frameHistogram.normalize(0xFF);
1709
1710 const LookupTable8BitPerChannel<tChannels> lookupTable(frameHistogram, invertedNormalizedReferenceIntegral);
1711
1712 if (worker)
1713 {
1714 worker->executeFunction(Worker::Function::createStatic(adjustColorToReferenceSubset<tChannels>, frame, width, height, &lookupTable, subframeLeft, subframeWidth, framePaddingElements, 0u, 0u), subframeTop, subframeHeight, 8u, 9u, 20u);
1715 }
1716 else
1717 {
1718 adjustColorToReferenceSubset<tChannels>(frame, width, height, &lookupTable, subframeLeft, subframeWidth, framePaddingElements, subframeTop, subframeHeight);
1719 }
1720
1721 return true;
1722}
1723
1724template <unsigned int tChannels>
1725inline bool Histogram::adjustColorToReference(const uint8_t* source, uint8_t* target, const unsigned int width, const unsigned int height, const IntegralHistogram8BitPerChannel<tChannels>& invertedNormalizedReferenceIntegral, const unsigned int sourcePaddingElements, const unsigned int targetPaddingElements, Worker* worker)
1726{
1727 return adjustColorToReference<tChannels>(source, target, width, height, 0u, 0u, width, height, invertedNormalizedReferenceIntegral, sourcePaddingElements, targetPaddingElements, worker);
1728}
1729
1730template <unsigned int tChannels>
1731bool Histogram::adjustColorToReference(const uint8_t* source, uint8_t* target, const unsigned int width, const unsigned int height, const unsigned int subframeLeft, const unsigned int subframeTop, const unsigned int subframeWidth, const unsigned int subframeHeight, const IntegralHistogram8BitPerChannel<tChannels>& invertedNormalizedReferenceIntegral, const unsigned int sourcePaddingElements, const unsigned int targetPaddingElements, Worker* worker)
1732{
1733 ocean_assert(source && target);
1734
1735 if (!source || !target || subframeLeft + subframeWidth > width || subframeTop + subframeHeight > height)
1736 {
1737 return false;
1738 }
1739
1740 IntegralHistogram8BitPerChannel<tChannels> frameHistogram(determineHistogram8BitPerChannel<tChannels>(source, width, height, sourcePaddingElements, worker));
1741 frameHistogram.normalize(0xFF);
1742
1743 const LookupTable8BitPerChannel<tChannels> lookupTable(frameHistogram, invertedNormalizedReferenceIntegral);
1744
1745 if (worker)
1746 {
1747 worker->executeFunction(Worker::Function::createStatic(adjustColorToReferenceOfTargetSubset<tChannels>, source, target, width, height, &lookupTable, subframeLeft, subframeWidth, sourcePaddingElements, targetPaddingElements, 0u, 0u), subframeTop, subframeHeight, 9u, 10u, 20u);
1748 }
1749 else
1750 {
1751 adjustColorToReferenceOfTargetSubset<tChannels>(source, target, width, height, &lookupTable, subframeLeft, subframeWidth, sourcePaddingElements, targetPaddingElements, subframeTop, subframeHeight);
1752 }
1753
1754 return true;
1755}
1756
1757template <unsigned int tChannels>
1758void Histogram::determineHistogram8BitPerChannelSubset(const uint8_t* frame, const unsigned int width, const unsigned int height, Histogram8BitPerChannel<tChannels>* histogram, Lock* lock, const unsigned int firstColumn, const unsigned int numberColumns, const unsigned int framePaddingElements, const unsigned int firstRow, const unsigned int numberRows)
1759{
1760 ocean_assert(frame != nullptr);
1761
1762 ocean_assert(firstColumn + numberColumns <= width);
1763 ocean_assert_and_suppress_unused(firstRow + numberRows <= height, height);
1764
1766
1767 if (numberColumns == width && framePaddingElements == 0u)
1768 {
1769 ocean_assert(firstColumn == 0u);
1770
1771 frame += firstRow * width * tChannels;
1772 const uint8_t* const frameEnd = frame + numberRows * width * tChannels;
1773
1774 while (frame != frameEnd)
1775 {
1776 localHistogram.increment(frame);
1777 frame += tChannels;
1778 }
1779 }
1780 else if (framePaddingElements == 0u)
1781 {
1782#ifdef OCEAN_DEBUG
1783 const uint8_t* const debugFrame = frame;
1784#endif
1785
1786 frame += (firstRow * width + firstColumn) * tChannels;
1787 const uint8_t* const frameEnd = frame + numberRows * width * tChannels;
1788
1789 const unsigned int rowOffset = (width - numberColumns) * tChannels;
1790
1791 while (frame != frameEnd)
1792 {
1793 ocean_assert(frame < frameEnd);
1794 ocean_assert((frame - debugFrame) % (width * tChannels) == firstColumn * tChannels);
1795
1796 const uint8_t* const frameRowEnd = frame + numberColumns * tChannels;
1797
1798 while (frame != frameRowEnd)
1799 {
1800 ocean_assert(frame < frameEnd);
1801 ocean_assert(frame < frameRowEnd);
1802
1803 localHistogram.increment(frame);
1804 frame += tChannels;
1805 }
1806
1807 frame += rowOffset;
1808 }
1809 }
1810 else
1811 {
1812 const unsigned int frameStrideElements = width * tChannels + framePaddingElements;
1813 frame += firstRow * frameStrideElements + firstColumn * tChannels;
1814
1815 const unsigned int rowOffset = (width - numberColumns) * tChannels + framePaddingElements;
1816
1817 for (unsigned int y = firstRow; y < firstRow + numberRows; ++y)
1818 {
1819 for (unsigned int x = firstColumn; x < firstColumn + numberColumns; ++x)
1820 {
1821 localHistogram.increment(frame);
1822 frame += tChannels;
1823 }
1824
1825 frame += rowOffset;
1826 }
1827 }
1828
1829 const OptionalScopedLock scopedLock(lock);
1830 *histogram += localHistogram;
1831}
1832
1833template <unsigned int tChannels>
1834void Histogram::equalizationSubset(uint8_t* frame, const unsigned int width, const unsigned int height, const IntegralHistogram8BitPerChannel<tChannels>* normalizedIntegral, const unsigned int factor, const unsigned int firstColumn, const unsigned int numberColumns, const unsigned int framePaddingElements, const unsigned int firstRow, const unsigned int numberRows)
1835{
1836 ocean_assert(frame != nullptr && normalizedIntegral != nullptr);
1837 ocean_assert(width > 0u && height > 0u);
1838
1839 ocean_assert(firstColumn + numberColumns <= width);
1840 ocean_assert_and_suppress_unused(firstRow + numberRows <= height, height);
1841
1842 ocean_assert(normalizedIntegral->determineHighestValue() <= 0xFFu);
1843
1844 ocean_assert(factor <= 256u);
1845 const unsigned int factor_ = 256u - factor;
1846
1847 const unsigned int frameStrideElements = width * tChannels + framePaddingElements;
1848
1849 for (unsigned int y = firstRow; y < firstRow + numberRows; ++y)
1850 {
1851 uint8_t* frameRow = frame + y * frameStrideElements + firstColumn * tChannels;
1852
1853 for (unsigned int x = 0u; x < numberColumns; ++x)
1854 {
1855 for (unsigned int n = 0u; n < tChannels; ++n)
1856 {
1857 frameRow[n] = (uint8_t)((normalizedIntegral->bin(n, (uint8_t)(frameRow[n])) * factor + frameRow[n] * factor_) >> 8u);
1858 }
1859
1860 frameRow += tChannels;
1861 }
1862 }
1863}
1864
1865template <unsigned int tChannels>
1866void Histogram::equalizationOfTargetSubset(const uint8_t* source, uint8_t* target, const unsigned int width, const unsigned int height, const IntegralHistogram8BitPerChannel<tChannels>* normalizedIntegral, const unsigned int factor, const unsigned int firstColumn, const unsigned int numberColumns, const unsigned int sourcePaddingElements, const unsigned int targetPaddingElements, const unsigned int firstRow, const unsigned int numberRows)
1867{
1868 ocean_assert(source != nullptr && target != nullptr && normalizedIntegral != nullptr);
1869 ocean_assert(width > 0u && height > 0u);
1870
1871 ocean_assert(firstColumn + numberColumns <= width);
1872 ocean_assert_and_suppress_unused(firstRow + numberRows <= height, height);
1873
1874 ocean_assert(normalizedIntegral->determineHighestValue() <= 0xFF);
1875
1876 ocean_assert(factor <= 256u);
1877 const unsigned int factor_ = 256u - factor;
1878
1879 const unsigned int sourceStrideElements = width * tChannels + sourcePaddingElements;
1880 const unsigned int targetStrideElements = width * tChannels + targetPaddingElements;
1881
1882 for (unsigned int y = firstRow; y < firstRow + numberRows; ++y)
1883 {
1884 const uint8_t* sourceRow = source + y * sourceStrideElements + firstColumn * tChannels;
1885 uint8_t* targtRow = target + y * targetStrideElements + firstColumn * tChannels;
1886
1887 for (unsigned int x = 0u; x < numberColumns; ++x)
1888 {
1889 for (unsigned int n = 0u; n < tChannels; ++n)
1890 {
1891 targtRow[n] = (uint8_t)((normalizedIntegral->bin(n, sourceRow[n]) * factor + sourceRow[n] * factor_) >> 8u);
1892 }
1893
1894 sourceRow += tChannels;
1895 targtRow += tChannels;
1896 }
1897 }
1898}
1899
1900template <unsigned int tChannels>
1901void Histogram::adjustColorToReferenceSubset(uint8_t* frame, const unsigned int width, const unsigned int height, const LookupTable8BitPerChannel<tChannels>* lookupTable, const unsigned int firstColumn, const unsigned int numberColumns, const unsigned int framePaddingElements, const unsigned int firstRow, const unsigned int numberRows)
1902{
1903 ocean_assert(frame != nullptr && lookupTable != nullptr);
1904
1905 ocean_assert(firstColumn + numberColumns <= width);
1906 ocean_assert_and_suppress_unused(firstRow + numberRows <= height, height);
1907
1908 const unsigned int frameStrideElements = width * tChannels + framePaddingElements;
1909
1910 for (unsigned int y = firstRow; y < firstRow + numberRows; ++y)
1911 {
1912 uint8_t* frameRow = frame + y * frameStrideElements + firstColumn * tChannels;
1913
1914 for (unsigned int x = 0u; x < numberColumns; ++x)
1915 {
1916 for (unsigned int n = 0u; n < tChannels; ++n)
1917 {
1918 frameRow[n] = lookupTable->lookup(n, frameRow[n]);
1919 }
1920
1921 frameRow += tChannels;
1922 }
1923 }
1924}
1925
1926template <unsigned int tChannels>
1927void Histogram::adjustColorToReferenceOfTargetSubset(const uint8_t* source, uint8_t* target, const unsigned int width, const unsigned int height, const LookupTable8BitPerChannel<tChannels>* lookupTable, const unsigned int firstColumn, const unsigned int numberColumns, const unsigned int sourcePaddingElements, const unsigned int targetPaddingElements, const unsigned int firstRow, const unsigned int numberRows)
1928{
1929 ocean_assert(source && target && lookupTable);
1930
1931 ocean_assert(firstColumn + numberColumns <= width);
1932 ocean_assert_and_suppress_unused(firstRow + numberRows <= height, height);
1933
1934 const unsigned int sourceStrideElements = width * tChannels + sourcePaddingElements;
1935 const unsigned int targetStrideElements = width * tChannels + targetPaddingElements;
1936
1937 for (unsigned int y = firstRow; y < firstRow + numberRows; ++y)
1938 {
1939 const uint8_t* sourceRow = source + y * sourceStrideElements + firstColumn * tChannels;
1940 uint8_t* targetRow = target + y * targetStrideElements + firstColumn * tChannels;
1941
1942 for (unsigned int x = 0u; x < numberColumns; ++x)
1943 {
1944 for (unsigned int n = 0u; n < tChannels; ++n)
1945 {
1946 targetRow[n] = lookupTable->lookup(n, sourceRow[n]);
1947 }
1948
1949 sourceRow += tChannels;
1950 targetRow += tChannels;
1951 }
1952 }
1953}
1954
1955} // namespace CV
1956
1957} // namespace Ocean
1958
1959#endif // META_OCEAN_CV_HISTOGRAM_H
Implementation of Contrast-Limited Adaptive Histogram Equalization (CLAHE).
Definition Histogram.h:755
static void bilinearInterpolationNEON7BitPrecisionSubset(const uint8_t *const source, const TileLookupCenter2 *lookupCenter2, uint8_t *const target, const uint8_t *const tileLookupTables, const Index32 *const leftBins, const uint8_t *const leftFactors_fixed7, const Index32 *const topBins, const uint8_t *const topFactors_fixed7, const unsigned int sourcePaddingElements=0u, const unsigned int targetPaddingElements=0u, const unsigned int tileStart=0u, const unsigned int tileCount=0u)
Helper function for the histogram normalization by bilinearly interpolating pixels using the CLAHE pe...
LookupCenter2< uint8_t > TileLookupCenter2
Image partitioning and tile boundary lookup.
Definition Histogram.h:765
static void computeLookupTable(const uint8_t *source, const unsigned int width, const unsigned int height, uint8_t *const lookupTable, const Scalar clipLimit, const unsigned int sourcePaddingElements=0u)
Computation of a lookup table required to normalize an image histogram (used per tile)
Definition Histogram.h:887
static void bilinearInterpolation7BitPrecisionSubset(const uint8_t *const source, const TileLookupCenter2 *lookupCenter2, uint8_t *const target, const uint8_t *const tileLookupTables, const Index32 *const leftBins, const uint8_t *const leftFactors_fixed7, const unsigned int sourcePaddingElements=0u, const unsigned int targetPaddingElements=0u, const unsigned int rowStart=0u, const unsigned int rowCount=0u)
Integer-based (fixed-point arithmetic) helper function for the histogram normalization by bilinearly ...
static void computeTileLookupTables(const uint8_t *const source, const TileLookupCenter2 &lookupCenter2, std::vector< uint8_t > &tileLookupTables, const Scalar clipLimit, const unsigned int sourcePaddingElements=0u, Worker *worker=nullptr)
Computation of per-tile lookup tables required to normalize an image histogram given a partitioned im...
std::array< unsigned int, histogramSize > TileHistogram
Tile histogram.
Definition Histogram.h:762
static void bilinearInterpolation(const uint8_t *const source, const TileLookupCenter2 &lookupCenter2, uint8_t *const target, const std::vector< uint8_t > &tileLookupTables, const unsigned int sourcePaddingElements=0u, const unsigned int targetPaddingElements=0u, Worker *worker=nullptr)
Histogram normalization by bilinearly interpolating pixels using the CLAHE per-tile lookup tables.
static void computeTileLookupTablesSubset(const uint8_t *const source, const TileLookupCenter2 *lookupCenter2, uint8_t *const tileLookupTables, const Scalar clipLimit, const unsigned int sourcePaddingElements=0u, const unsigned int firstTile=0u, const unsigned int tileCount=0u)
Helper function for the computation of per-tile lookup tables required to normalize an image histogra...
static void computeLowBilinearInterpolationFactors7BitPrecision(const TileLookupCenter2 &lookupCenter2, const bool isHorizontal, Index32 *lowBins, uint8_t *lowFactors_fixed7)
Computation of the bilinear interpolation parameters for the low bins of an image pixel If isHorizont...
static void equalization8BitPerChannel(const uint8_t *const source, const unsigned int width, const unsigned height, uint8_t *const target, const Scalar clipLimit=Scalar(40), const unsigned int horizontalTiles=8u, const unsigned int verticalTiles=8u, const unsigned int sourcePaddingElements=0u, const unsigned int targetPaddingElements=0u, Worker *worker=nullptr)
Histogram equalization a la CLAHE.
static constexpr unsigned int histogramSize
Number of bins in the tile histograms.
Definition Histogram.h:759
This class implements a standard histogram object storing 8 bit per channel.
Definition Histogram.h:208
void incrementBin(const uint8_t index)
Increments a specific bin of this histogram (by one).
Definition Histogram.h:1232
void increment(const uint8_t *pixel)
Increments all channels of a specific histogram bin (by one).
Definition Histogram.h:1248
Histogram8BitPerChannel< tChannels > operator+(const Histogram8BitPerChannel< tChannels > &histogram) const
Adds to histogram objects and returns the new histogram.
Definition Histogram.h:1259
Histogram8BitPerChannel()
Creates a new histogram object and sets all histogram bins to zero.
Definition Histogram.h:1224
This class implements the base class for all histogram objects holding 8 bit per data channel.
Definition Histogram.h:41
unsigned int determineHighestValue() const
Determines the highest value within the entire histogram.
unsigned int determineEndBin(const unsigned int channel) const
Determines the last bin that is not zero for a specific channel.
Definition Histogram.h:1101
void clear()
Clears the entire histogram and sets all bins to zero.
Definition Histogram.h:1159
void normalize(const unsigned int newMaximalValue)
Normalizes the entire histogram by application of the highest histogram value.
Definition Histogram.h:1119
unsigned int determineStartBin(const unsigned int channel) const
Determines the first bin that is not zero for a specific channel.
Definition Histogram.h:1083
void setBin(const unsigned int channel, const uint8_t index, const unsigned int value)
Explicitly sets a value of a specific histogram bin.
Definition Histogram.h:1202
HistogramBase8BitPerChannel< tChannels > & operator+=(const HistogramBase8BitPerChannel< tChannels > &histogram)
Adds the histogram bins of a second histogram to this histogram.
Definition Histogram.h:1185
HistogramBase8BitPerChannel()
Creates an empty histogram object and sets all histogram bins to zero.
Definition Histogram.h:975
const unsigned int * bins() const
Returns the 256 histogram values for a specific channel.
Definition Histogram.h:1012
unsigned int determineHighestValue() const
Determines the highest value within the histogram for a specific channel.
Definition Histogram.h:1029
bool isNull() const
Returns whether all bins inside the histogram are zero.
Definition Histogram.h:1210
const unsigned int * operator()() const
Returns all histogram bins of this histogram.
Definition Histogram.h:1196
bool operator!=(const HistogramBase8BitPerChannel< tChannels > &histogram) const
Returns whether two histogram objects are not identical according to their histogram bins.
Definition Histogram.h:1179
unsigned int histogramBins[256u *tChannels]
The histogram bins.
Definition Histogram.h:199
bool operator==(const HistogramBase8BitPerChannel< tChannels > &histogram) const
Returns whether two histogram objects are identical according to their histogram bins.
Definition Histogram.h:1165
unsigned int bin() const
Returns the bin value of a specific channel and bin.
unsigned int sumBin(const uint8_t index) const
Returns the sum of all channels stored for a specific bin.
Definition Histogram.h:998
This class implements an integral histogram object.
Definition Histogram.h:253
IntegralHistogram8BitPerChannel()
Creates a new integral histogram object and sets all histogram bins to zero.
Definition Histogram.h:1272
IntegralHistogram8BitPerChannel invert() const
Inverts this (normalized) integral histogram so that the inverted histogram can be used as lookup obj...
Definition Histogram.h:1309
This class implements a simple lookup table.
Definition Histogram.h:285
LookupTable8BitPerChannel()
Creates a default lookup table providing the identity lookup result.
Definition Histogram.h:1339
uint8_t lookup(const uint8_t index) const
Lookup function providing the lookup value for a specific channel and bin.
Definition Histogram.h:1367
This class implements an image histogram.
Definition Histogram.h:32
static void adjustColorToReferenceSubset(uint8_t *frame, const unsigned int width, const unsigned int height, const LookupTable8BitPerChannel< tChannels > *lookupTable, const unsigned int firstColumn, const unsigned int numberColumns, const unsigned int framePaddingElements, const unsigned int firstRow, const unsigned int numberRows)
Adjusts the color in a subset of a frame according to a given reference frame.
Definition Histogram.h:1901
static void equalizationOfTargetSubset(const uint8_t *source, uint8_t *target, const unsigned int width, const unsigned int height, const IntegralHistogram8BitPerChannel< tChannels > *normalizedIntegral, const unsigned int factor, const unsigned int firstColumn, const unsigned int numberColumns, const unsigned int sourcePaddingElements, const unsigned int targetPaddingElements, const unsigned int firstRow, const unsigned int numberRows)
Applies a histogram equalization in a subset of a given frame.
Definition Histogram.h:1866
static bool equalization(const Frame &source, Frame &target, const Scalar factor=1, Worker *worker=nullptr)
Applies a histogram equalization for a given frame.
static bool adjustColorToReference(const Frame &source, Frame &target, const Frame &reference, Worker *worker=nullptr)
Adjusts the color of a frame according to a given reference frame.
static bool adjustColorToReference(Frame &frame, const Frame &reference, const unsigned int horizontalBins, const unsigned int verticalBins, Worker *worker=nullptr)
Adjusts the color of a frame according to a given reference frame while using corresponding bins for ...
static Histogram8BitPerChannel< tChannels > determineHistogram8BitPerChannel(const uint8_t *frame, const unsigned int width, const unsigned int height, const unsigned int framePaddingElements, Worker *worker=nullptr)
Determines the standard histogram for a given frame.
Definition Histogram.h:1383
static bool adjustColorToReference(Frame &frame, const Frame &reference, Worker *worker=nullptr)
Adjusts the color of a frame according to a given reference frame.
static void adjustColorToReferenceOfTargetSubset(const uint8_t *source, uint8_t *target, const unsigned int width, const unsigned int height, const LookupTable8BitPerChannel< tChannels > *lookupTable, const unsigned int firstColumn, const unsigned int numberColumns, const unsigned int sourcePaddingElements, const unsigned int targetPaddingElements, const unsigned int firstRow, const unsigned int numberRows)
Adjusts the color of a frame according to a given reference frame.
Definition Histogram.h:1927
static bool equalization(Frame &frame, const Scalar factor=1, Worker *worker=nullptr)
Applies a histogram equalization for a given frame.
static void determineHistogram8BitPerChannelSubset(const uint8_t *frame, const unsigned int width, const unsigned int height, Histogram8BitPerChannel< tChannels > *histogram, Lock *lock, const unsigned int firstColumn, const unsigned int numberColumns, const unsigned int framePaddingElements, const unsigned int firstRow, const unsigned int numberRows)
Determines the standard histogram in a subset of a given frame.
Definition Histogram.h:1758
static void equalizationSubset(uint8_t *frame, const unsigned int width, const unsigned int height, const IntegralHistogram8BitPerChannel< tChannels > *normalizedIntegral, const unsigned int factor, const unsigned int firstColumn, const unsigned int numberColumns, const unsigned int framePaddingElements, const unsigned int firstRow, const unsigned int numberRows)
Applies a histogram equalization in a subset of a given frame.
Definition Histogram.h:1834
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:1808
This class implements a recursive lock object.
Definition Lock.h:31
This class implements a 2D lookup object with values at the bins' center positions defining the indiv...
Definition Lookup2.h:198
This class provides basic numeric functionalities.
Definition Numeric.h:57
This class implements an optional recursive scoped lock object locking the lock object only if it's d...
Definition Lock.h:325
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.
uint32_t Index32
Definition of a 32 bit index value.
Definition Base.h:84
float Scalar
Definition of a scalar type.
Definition Math.h:129
The namespace covering the entire Ocean framework.
Definition Accessor.h:15
AutomaticDifferentiationT< T1, TNumeric1 > operator+(const T2 &left, const AutomaticDifferentiationT< T1, TNumeric1 > &right)
Definition AutomaticDifferentiation.h:418