Ocean
FrameColorAdjustment.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_ADVANCED_FRAME_COLOR_ADJUSTMENT_H
9 #define META_OCEAN_CV_ADVANCED_FRAME_COLOR_ADJUSTMENT_H
10 
12 
13 #include "ocean/base/Frame.h"
14 #include "ocean/base/Worker.h"
15 
16 #include "ocean/math/Lookup2.h"
17 
18 namespace Ocean
19 {
20 
21 namespace CV
22 {
23 
24 namespace Advanced
25 {
26 
27 /**
28  * This class implements color adjustment functions between frames.
29  * @ingroup cvadvanced
30  */
31 class OCEAN_CV_ADVANCED_EXPORT FrameColorAdjustment
32 {
33  public:
34 
35  /**
36  * This class implements an bin adjustment object supporting an arbitrary number of data channels.
37  * @tparam tChannels The number of data channels, with range [1, infinity)
38  */
39  template <unsigned int tChannels>
40  class Object
41  {
42  public:
43 
44  /**
45  * Creates a new object with values set to zero.
46  */
47  inline Object();
48 
49  /**
50  * Creates a new object and copies the given values.
51  * @param values The values to be copied
52  */
53  inline explicit Object(Scalar* values);
54 
55  /**
56  * Creates a new object and sets all elements to the given value.
57  * @param value The value to be copied
58  */
59  inline explicit Object(const Scalar value);
60 
61  /**
62  * Returns whether the absolute value of each element of this object is below or equal to a specified threshold.
63  * @param threshold The threshold to be checked, with range (0, infinity)
64  * @return True, if so
65  */
66  inline bool belowThreshold(const Scalar threshold) const;
67 
68  /**
69  * Add operator adding two objects element by element.
70  * @param object The second object to be added
71  * @return The add result
72  */
73  inline Object operator+(const Object& object) const;
74 
75  /**
76  * Subtract operator subtracting two objects element by element.
77  * @param object The second object to be subtracted
78  * @return The subtraction result
79  */
80  inline Object operator-(const Object& object) const;
81 
82  /**
83  * Multiplication operator multiplying all elements of this object by a scalar.
84  * @param value The scalar value for multiplication
85  * @return The multiplication result
86  */
87  inline Object operator*(const Scalar value) const;
88 
89  /**
90  * Division operator dividing all elements of this object by a scalar.
91  * @param value The scalar value for division, must not be zero
92  * @return The division result
93  */
94  inline Object operator/(const Scalar value) const;
95 
96  /**
97  * Index operator returning one element of this object.
98  * @param index The index of the element to be returned, with range [0, tChannels - 1]
99  * @return The requested element
100  */
101  inline Scalar operator[](const unsigned int index) const;
102 
103  /**
104  * Index operator returning one element of this object.
105  * @param index The index of the element to be returned, with range [0, tChannels - 1]
106  * @return The requested element
107  */
108  inline Scalar& operator[](const unsigned int index);
109 
110  protected:
111 
112  /// The object's elements.
113  Scalar objectValues_[tChannels];
114  };
115 
116  /**
117  * Definition of a center lookup table holding objects.
118  * @tparam tChannels The number of frame channels, with range [1, infinity)
119  */
120  template <unsigned int tChannels>
122 
123  /**
124  * Definition of an advanced center lookup table holding objects.
125  * @tparam tChannels The number of frame channels, with range [1, infinity)
126  */
127  template <unsigned int tChannels>
129 
130  public:
131 
132  /**
133  * Adjusts the color values of one frame with respect to a given reference frame both showing almost the same visual content.
134  * The reference frame and the frame which will be adjusted must have the same frame dimension, pixel origin and pixel format.<br>
135  * Both frames are separated into bins, the pixel values within each bin is averaged and normalized by the number of valid pixels in the individual bins.<br>
136  * The adjustment is applied due to a bilinear interpolation between neighboring bins.
137  * @param reference The reference frame holding the reference color values, must be valid
138  * @param referenceMask Optional mask defining valid pixels in the reference frame, invalid to interpret all pixels as valid
139  * @param frame The target frame which will be adjusted, must be valid
140  * @param frameMask Optional mask defining valid pixels in the target frame, invalid to interpret all pixels as valid
141  * @param horizontalBins The number of horizontal bins, with range [1, frame.height() / 2]
142  * @param verticalBins the number of vertical bins, with range [1, frame.height() / 2]
143  * @param threshold The color threshold value which must not be exceeded by the difference between corresponding bins between reference and target frame (individually for each data channel)
144  * @param maskValue The mask value defining valid pixels
145  * @param worker Optional worker object to distribute the computation
146  * @see adjustFrameBilinear8BitPerChannel().
147  */
148  static bool adjustFrameBilinear(const Frame& reference, const Frame& referenceMask, Frame& frame, const Frame& frameMask, const unsigned int horizontalBins, const unsigned int verticalBins, const Scalar threshold = Scalar(20), const uint8_t maskValue = 0xFF, Worker* worker = nullptr);
149 
150  /**
151  * Adjusts the color values of one frame with respect to a given reference frame both showing almost the same visual content.
152  * The reference frame and the frame which will be adjusted must have the same frame dimension, pixel origin and pixel format.<br>
153  * Both frames are separated into bins, the pixel values within each bin is averaged and normalized by the number of valid pixels in the individual bins.<br>
154  * The adjustment is applied due to a bilinear interpolation between neighboring bins.
155  * @param reference The reference frame holding the reference color values, must be valid
156  * @param referenceMask Optional mask defining valid pixels in the reference frame, nullptr to interpret all pixels as valid
157  * @param frame The target frame which will be adjusted, must be valid
158  * @param frameMask Optional mask defining valid pixels in the target frame, nullptr to interpret all pixels as valid
159  * @param width The width of reference and target frame (and optional both masks) in pixel, with range [1, infinity)
160  * @param height The height of reference and target frame (and optional both masks) in pixel, with range [1, infinity)
161  * @param referencePaddingElements The number of padding elements at the end of each reference row, in elements, with range [0, infinity)
162  * @param referenceMaskPaddingElements The number of padding elements at the end of each reference mask row, in elements, with range [0, infinity), ignored if referenceMask == nullptr
163  * @param framePaddingElements The number of padding elements at the end of each frame row, in elements, with range [0, infinity)
164  * @param frameMaskPaddingElements The number of padding elements at the end of each frame mask row, in elements, with range [0, infinity), ignored if frameMask == nullptr
165  * @param horizontalBins The number of horizontal bins, with range [1, height / 2]
166  * @param verticalBins the number of vertical bins, with range [1, height / 2]
167  * @param threshold The color threshold value which must not be exceeded by the difference between corresponding bins between reference and target frame (individually for each data channel)
168  * @param maskValue The mask value defining valid pixels
169  * @param worker Optional worker object to distribute the computation
170  * @tparam tChannels The number of data channels of the given frames, with range [1, infinity)
171  * @see adjustFrameBilinear().
172  */
173  template <unsigned int tChannels>
174  static inline void adjustFrameBilinear8BitPerChannel(const uint8_t* reference, const uint8_t* referenceMask, uint8_t* frame, const uint8_t* frameMask, const unsigned int width, const unsigned int height, const unsigned int referencePaddingElements, const unsigned int referenceMaskPaddingElements, const unsigned int framePaddingElements, const unsigned int frameMaskPaddingElements, const unsigned int horizontalBins, const unsigned int verticalBins, const Scalar threshold = Scalar(20), const uint8_t maskValue = 0xFF, Worker* worker = nullptr);
175 
176  /**
177  * Determines the adjustment lookup table between two frames.
178  * @param reference The reference frame holding the reference color values, must be valid
179  * @param frame The target frame which is expected to be adjusted, must be valid
180  * @param referencePaddingElements The number of padding elements at the end of each reference row, in elements, with range [0, infinity)
181  * @param framePaddingElements The number of padding elements at the end of each frame row, in elements, with range [0, infinity)
182  * @param threshold The maximal threshold which will not be exceeded by an adjustment bin, an adjustment bin with (at least) one channel exceeding this threshold will be set as invalid bin
183  * @param lookupTable The resulting lookup table, with valid and invalid bins (depending on the specified threshold and the visual differences between both frames)
184  * @param worker Optional worker object to distribute the computation
185  * @tparam tChannels The number of data channels of the given frames, with range [1, infinity)
186  */
187  template <unsigned int tChannels>
188  static inline void determineAdjustmentLookupTable8BitPerChannel(const uint8_t* reference, const uint8_t* frame, const unsigned int referencePaddingElements, const unsigned int framePaddingElements, const Scalar threshold, LookupTable<tChannels>& lookupTable, Worker* worker = nullptr);
189 
190  /**
191  * Determines the adjustment lookup table between two frames while for each frame an optional mask frame can specify valid and invalid pixels.
192  * @param reference The reference frame holding the reference color values
193  * @param referenceMask An optional 8 bit mask specifying valid and invalid pixels in the reference frame, if valid 'tUseReferenceMask' must be True
194  * @param frame The target frame which is expected to be adjusted
195  * @param frameMask An optional 8 bit mask specifying valid and invalid pixels in the target frame, if valid 'tUseFrameMask' must be True
196  * @param referencePaddingElements The number of padding elements at the end of each reference row, in elements, with range [0, infinity)
197  * @param referenceMaskPaddingElements The number of padding elements at the end of each reference mask row, in elements, with range [0, infinity), ignored if tUseReferenceMask == false
198  * @param framePaddingElements The number of padding elements at the end of each frame row, in elements, with range [0, infinity)
199  * @param frameMaskPaddingElements The number of padding elements at the end of each frame mask row, in elements, with range [0, infinity), ignored if tUseFrameMask == false
200  * @param threshold The maximal threshold which will not be exceeded by an adjustment bin, an adjustment bin with (at least) one channel exceeding this threshold will be set as invalid bin
201  * @param lookupTable The resulting lookup table, with valid and invalid bins (depending on the specified threshold and the visual differences between both frames)
202  * @param maskValue The 8 bit mask value specifying valid pixels in the mask frames
203  * @param worker Optional worker object to distribute the computation
204  * @tparam tChannels The number of data channels of the given frames, with range [1, infinity)
205  * @tparam tUseReferenceMask True, if a mask for the reference frame is specified
206  * @tparam tUseFrameMask True, if a mask for the target frame is given
207  */
208  template <unsigned int tChannels, bool tUseReferenceMask, bool tUseFrameMask>
209  static inline void determineAdjustmentLookupTable8BitPerChannel(const uint8_t* reference, const uint8_t* referenceMask, const uint8_t* frame, const uint8_t* frameMask, const unsigned int referencePaddingElements, const unsigned int referenceMaskPaddingElements, const unsigned int framePaddingElements, const unsigned int frameMaskPaddingElements, const Scalar threshold, LookupTable<tChannels>& lookupTable, const uint8_t maskValue, Worker* worker = nullptr);
210 
211  /**
212  * Adjusts a frame by a given color adjustment lookup table.
213  * @param frame The frame which will be adjusted, must be valid
214  * @param framePaddingElements The number of padding elements at the end of each frame row, in elements, with range [0, infinity)
215  * @param lookupTable The lookup table (providing offset values) which is applied to adjust the given frame, the size of the table must be identical to the dimension of the given frame
216  * @param worker Optional worker object to distribute the computation
217  * @tparam tChannels The number of data channels of the given frames, with range [1, infinity)
218  */
219  template <unsigned int tChannels>
220  static inline void adjustFrameBilinear8BitPerChannel(uint8_t* frame, const unsigned int framePaddingElements, const LookupTable<tChannels>& lookupTable, Worker* worker = nullptr);
221 
222  /**
223  * Adjusts a frame by a given color adjustment lookup table while a mask specifies valid and invalid pixels of the frame.
224  * @param frame The frame which will be adjusted, must be valid
225  * @param mask The 8 bit mask specifying valid and invalid frame pixels, must be valid
226  * @param framePaddingElements The number of padding elements at the end of each frame row, in elements, with range [0, infinity)
227  * @param maskPaddingElements The number of padding elements at the end of each mask row, in elements, with range [0, infinity), ignored if tUseFrameMask == false
228  * @param lookupTable The lookup table (providing offset values) which is applied to adjust the given frame, the size of the table must be identical to the dimension of the given frame
229  * @param maskValue The mask value defining a valid pixel, with range [0, 255]
230  * @param worker Optional worker object to distribute the computation
231  * @tparam tChannels The number of data channels of the given frames, with range [1, infinity)
232  */
233  template <unsigned int tChannels>
234  static inline void adjustFrameMaskBilinear8BitPerChannel(uint8_t* frame, const uint8_t* mask, const unsigned int framePaddingElements, const unsigned int maskPaddingElements, const LookupTable<tChannels>& lookupTable, const uint8_t maskValue, Worker* worker = nullptr);
235 
236  /**
237  * Adjusts a frame by a given color adjustment lookup table holding valid and invalid lookup bins while further a mask specifies valid and invalid pixels of the frame.
238  * @param frame The frame which will be adjusted, must be valid
239  * @param mask The 8 bit mask specifying valid and invalid frame pixels, must be valid
240  * @param framePaddingElements The number of padding elements at the end of each frame row, in elements, with range [0, infinity)
241  * @param maskPaddingElements The number of padding elements at the end of each mask row, in elements, with range [0, infinity), ignored if tUseFrameMask == false
242  * @param lookupTable The lookup table (providing offset values) which is applied to adjust the given frame, the size of the table must be identical to the dimension of the given frame
243  * @param maskValue The mask value defining a valid pixel, with range [0, 255]
244  * @param worker Optional worker object to distribute the computation
245  * @tparam tChannels The number of data channels of the given frames, with range [1, infinity)
246  */
247  template <unsigned int tChannels>
248  static inline void adjustFrameMaskBilinearAdvanced8BitPerChannel(uint8_t* frame, const uint8_t* mask, const unsigned int framePaddingElements, const unsigned int maskPaddingElements, const AdvancedLookupTable<tChannels>& lookupTable, const uint8_t maskValue, Worker* worker = nullptr);
249 
250  /**
251  * Adjusts a frame by two given color adjustment lookup table each holding valid and invalid lookup bins while a mask separates the frame into two parts and thus allows to use one of both lookup tables for each individual pixel of the frame.
252  * @param frame The frame which will be adjusted, must be valid
253  * @param mask The 8 bit mask specifying valid and invalid frame pixels, must be valid
254  * @param framePaddingElements The number of padding elements at the end of each frame row, in elements, with range [0, infinity)
255  * @param maskPaddingElements The number of padding elements at the end of each mask row, in elements, with range [0, infinity), ignored if tUseFrameMask == false
256  * @param lookupTableA The first lookup table (providing offset values) which is applied to adjust the given frame for 'A' mask pixels, the size of the table must be identical to the dimension of the given frame
257  * @param lookupTableB The second lookup table (providing offset values) which is applied to adjust the given frame for 'B' mask pixels, with identical size as lookupTableA
258  * @param maskValue The mask value defining 'A' pixel, all other mask values define 'B' pixels, with range [0, 255]
259  * @param worker Optional worker object to distribute the computation
260  * @tparam tChannels The number of data channels of the given frames, with range [1, infinity)
261  */
262  template <unsigned int tChannels>
263  static inline void adjustFrameMaskBilinearAdvanced8BitPerChannel(uint8_t* frame, const uint8_t* mask, const unsigned int framePaddingElements, const unsigned int maskPaddingElements, const AdvancedLookupTable<tChannels>& lookupTableA, const AdvancedLookupTable<tChannels>& lookupTableB, const uint8_t maskValue, Worker* worker = nullptr);
264 
265  /**
266  * Adjusts a frame by a given color adjustment lookup table holding valid and invalid lookup bins while further a mask specifies valid and invalid pixels of the frame.
267  * @param frame The frame which will be adjusted
268  * @param mask The 8 bit mask specifying valid and invalid frame pixels
269  * @param adjustedFrame The resulting adjusted frame
270  * @param lookupTable The lookup table (providing offset values) which is applied to adjust the given frame, the size of the table must be identical to the dimension of the given frame
271  * @param maskValue The mask value defining a valid pixel, with range [0, 255]
272  * @param worker Optional worker object to distribute the computation
273  * @tparam tChannels The number of data channels of the given frames, with range [1, infinity)
274  * @tparam tCopyPixelForInvalidLookup True, to copy image pixels if no valid corresponding lookup value can be determined; False, to do nothing in this case
275  */
276  template <unsigned int tChannels, bool tCopyPixelForInvalidLookup>
277  static inline void adjustFrameMaskBilinearAdvanced8BitPerChannel(const uint8_t* frame, const uint8_t* mask, uint8_t* adjustedFrame, const AdvancedLookupTable<tChannels>& lookupTable, const uint8_t maskValue, Worker* worker = nullptr);
278 
279  /**
280  * Adjusts a frame by two given color adjustment lookup table each holding valid and invalid lookup bins while a mask separates the frame into two parts and thus allows to use one of both lookup tables for each individual pixel of the frame.
281  * @param frame The frame which will be adjusted
282  * @param mask The 8 bit mask specifying valid and invalid frame pixels
283  * @param adjustedFrame The resulting adjusted frame
284  * @param lookupTableA The first lookup table (providing offset values) which is applied to adjust the given frame for 'A' mask pixels, the size of the table must be identical to the dimension of the given frame
285  * @param lookupTableB The second lookup table (providing offset values) which is applied to adjust the given frame for 'B' mask pixels, with identical size as lookupTableA
286  * @param maskValue The mask value defining 'A' pixel, all other mask values define 'B' pixels
287  * @param worker Optional worker object to distribute the computation
288  * @tparam tChannels The number of data channels of the given frames, with range [1, infinity)
289  * @tparam tCopyPixelForInvalidLookup True, to copy image pixels if no valid corresponding lookup value can be determined; False, to do nothing in this case
290  */
291  template <unsigned int tChannels, bool tCopyPixelForInvalidLookup>
292  static inline void adjustFrameMaskBilinearAdvanced8BitPerChannel(const uint8_t* frame, const uint8_t* mask, uint8_t* adjustedFrame, const AdvancedLookupTable<tChannels>& lookupTableA, const AdvancedLookupTable<tChannels>& lookupTableB, const uint8_t maskValue, Worker* worker = nullptr);
293 
294  /**
295  * Adjusts a frame by two given color adjustment lookup table each holding valid and invalid lookup bins while a mask separates the frame into two parts and thus allows to use one of both lookup tables for each individual pixel of the frame.
296  * @param frame The frame which will be adjusted
297  * @param filterFrame The filter frame to adjust the frame
298  * @param mask The 8 bit mask of the frame specifying valid and invalid pixels
299  * @param filterMask The 8 bit mask specifying valid and invalid filter pixels
300  * @param adjustedFrame The resulting adjusted frame
301  * @param lookupTableA The first lookup table (providing offset values) which is applied to adjust the given frame for 'A' mask pixels, the size of the table must be identical to the dimension of the given frame
302  * @param lookupTableB The second lookup table (providing offset values) which is applied to adjust the given frame for 'B' mask pixels, with identical size as lookupTableA
303  * @param maskValue The mask value defining 'A' pixel, all other mask values define 'B' pixels
304  * @param worker Optional worker object to distribute the computation
305  * @tparam tChannels The number of data channels of the given frames, with range [1, infinity)
306  * @tparam tCopyPixelForInvalidLookup True, to copy pixel data for invalid lookup bins
307  */
308  template <unsigned int tChannels, bool tCopyPixelForInvalidLookup>
309  static inline void adjustFrameMaskBilinearFilterAdvanced8BitPerChannel(const uint8_t* frame, const uint8_t* filterFrame, const uint8_t* mask, const uint8_t* filterMask, uint8_t* adjustedFrame, const AdvancedLookupTable<tChannels>& lookupTableA, const AdvancedLookupTable<tChannels>& lookupTableB, const uint8_t maskValue, Worker* worker = nullptr);
310 
311  /**
312  * Adjust a color transfer algorithm that uses the mean and standard deviation of the image channels.
313  * @param frame The frame which will be adjusted
314  * @param mask The 8 bit mask specifying valid and invalid frame pixels
315  * @param target The target frame which will be adjusted
316  * @param width The width of reference and target frame (and optional both masks) in pixel, with range [1, infinity)
317  * @param height The height of reference and target frame (and optional both masks) in pixel, with range [1, infinity)
318  * @param frameMean Mean values (each channel) of the current frame
319  * @param frameStd Standard deviations (each channel) of the current frame
320  * @param refMean Mean values (each channel) of the reference frame
321  * @param refStd Standard deviations (each channel) of the reference frame
322  * @param maskValue The mask value defining 'A' pixel, all other mask values define 'B' pixels
323  * @param worker Optional worker object to distribute the computation
324  * @tparam tChannels The number of data channels of the given frames, with range [1, infinity)
325  */
326  template <unsigned int tChannels>
327  static inline void colorMatchingTransfer(const uint8_t* frame, const uint8_t* mask, uint8_t* target, const unsigned int width, const unsigned int height, const std::vector<Scalar>& frameMean, const std::vector<Scalar>& frameStd, const std::vector<Scalar>& refMean, const std::vector<Scalar>& refStd, const uint8_t maskValue, Worker* worker = nullptr);
328 
329  /**
330  * Compute color statistics for the source and target images
331  * @param frame The frame which will be adjusted
332  * @param mask The 8 bit mask specifying valid and invalid frame pixels
333  * @param target The target frame which will be adjusted
334  * @param width The width of reference and target frame (and optional both masks) in pixel, with range [1, infinity)
335  * @param height The height of reference and target frame (and optional both masks) in pixel, with range [1, infinity)
336  * @param frameMean Mean values (each channel) of the current frame
337  * @param frameStd Standard deviations (each channel) of the current frame
338  * @param refMean Mean values (each channel) of the reference frame
339  * @param refStd Standard deviations (each channel) of the reference frame
340  * @param firstRow The first row to be handled
341  * @param numberRows The number of rows to be handled
342  * @param maskValue The mask value defining 'A' pixel, all other mask values define 'B' pixels
343  * @tparam tChannels The number of data channels of the given frames, with range [1, infinity)
344  */
345  template<unsigned int tChannels>
346  static inline void colorMatchingTransfer8BitPerChannelSubset(const uint8_t* frame, const uint8_t* mask, uint8_t* target, const unsigned int width, const unsigned int height, const Scalar* frameMean, const Scalar* frameStd, const Scalar* refMean, const Scalar* refStd, const unsigned int firstRow, const unsigned int numberRows, const uint8_t maskValue);
347 
348  /**
349  * Determines the mean color values of a given frame which may have valid and invalid pixels (specified by a given mask).
350  * The mean values are determined for small equally distributed bins and stored in a lookup table.
351  * The resulting lookup table defines the size of the provided frame (and mask).
352  * @param frame The frame for which the mean color values will be determined, with zipped pixel format and 8 bit per channel and pixel, with frame size lookupTable.sizeX() x lookupTable.sizeY()
353  * @param mask The mask frame with 8 bit per pixel, each mask pixel has a corresponding frame pixel
354  * @param lookupTable The resulting lookup table which will received the mean color intensities of the provided frame
355  * @param maskValue The mask value defining a valid pixel, large frame areas with invalid pixels may result in lookup bins set to be invalid, with range [0, 255]
356  * @param minimalSamples The minimal number of samples so that a bin counts as valid and that the mean value will be set, with range [1, infinity)
357  * @param worker Optional worker object to distribute the computation
358  * @tparam tChannels The number of data channels of the given frames, with range [1, infinity)
359  */
360  template <unsigned int tChannels>
361  static inline void determineMeanFrameMaskAdvanced8BitPerChannel(const uint8_t* frame, const uint8_t* mask, AdvancedLookupTable<tChannels>& lookupTable, const uint8_t maskValue, const unsigned int minimalSamples, Worker* worker = nullptr);
362 
363  /**
364  * Determines the mean color values of a given frame separated into two parts with own lookup table for the mean values.
365  * The mean values are determined for small equally distributed bins and stored in lookup tables.<br>
366  * The resulting lookup tables must have the same size and define the size of the provided frame (and mask).
367  * @param frame The frame for which the mean color values will be determined, with zipped pixel format and 8 bit per channel and pixel, with frame size lookupTable.sizeX() x lookupTable.sizeY()
368  * @param separationMask The mask frame with 8 bit per pixel separating the frame into 'A' and 'B' pixels, each mask pixel has a corresponding frame pixel
369  * @param lookupTableA The resulting lookup table which will receive the mean color intensities of all frame pixels with 'A' mask pixels
370  * @param lookupTableB The resulting lookup table which will receive the mean color intensities of all frame pixels with 'B' mask pixels, with identical size as lookupTableA
371  * @param separationMaskValue The separation mask value defining 'A' pixel, all other mask values define 'B' pixels, with range [0, 255]
372  * @param minimalSamples The minimal number of samples so that a bin counts as valid and that the mean value will be set, with range [1, infinity)
373  * @param worker Optional worker object to distribute the computation
374  * @tparam tChannels The number of data channels of the given frames, with range [1, infinity)
375  */
376  template <unsigned int tChannels>
377  static inline void determineMeanFrameMaskAdvanced8BitPerChannel(const uint8_t* frame, const uint8_t* separationMask, AdvancedLookupTable<tChannels>& lookupTableA, AdvancedLookupTable<tChannels>& lookupTableB, const uint8_t separationMaskValue, const unsigned int minimalSamples, Worker* worker = nullptr);
378 
379  /**
380  * Determines the mean color values of a given frame separated into two parts with own lookup table for the mean values.
381  * Further, a mask is used defining valid and invalid pixels.<br>
382  * The mean values are determined for small equally distributed bins and stored in lookup tables.<br>
383  * The resulting lookup tables must have the same size and define the size of the provided frame (and mask).
384  * @param frame The frame for which the mean color values will be determined, with zipped pixel format and 8 bit per channel and pixel, with frame size lookupTable.sizeX() x lookupTable.sizeY()
385  * @param mask The mask frame with 8 bit per pixel defining valid and invalid pixels in general, each mask pixel has a corresponding frame pixel
386  * @param separationMask The separation mask frame with 8 bit per pixel separating the frame into 'A' and 'B' pixels, each mask pixel has a corresponding frame pixel
387  * @param lookupTableA The resulting lookup table which will receive the mean color intensities of all frame pixels with 'A' mask pixels
388  * @param lookupTableB The resulting lookup table which will receive the mean color intensities of all frame pixels with 'B' mask pixels, with identical size as lookupTableA
389  * @param maskValue The mask value defining valid pixels, mask pixels with different value count as invalid and will not be investigated for mean calculation, with range [0, 255]
390  * @param separationMaskValue The separation mask value defining 'A' pixel, all other mask values define 'B' pixels, with range [0, 255]
391  * @param minimalSamples The minimal number of samples so that a bin counts as valid and that the mean value will be set, with range [1, infinity)
392  * @param worker Optional worker object to distribute the computation
393  * @tparam tChannels The number of data channels of the given frames, with range [1, infinity)
394  */
395  template <unsigned int tChannels>
396  static inline void determineMeanFrameMaskAdvanced8BitPerChannel(const uint8_t* frame, const uint8_t* mask, const uint8_t* separationMask, AdvancedLookupTable<tChannels>& lookupTableA, AdvancedLookupTable<tChannels>& lookupTableB, const uint8_t maskValue, const uint8_t separationMaskValue, const unsigned int minimalSamples, Worker* worker = nullptr);
397 
398  protected:
399 
400  /**
401  * Determines a subset of an adjustment lookup table between two frames.
402  * @param reference The reference frame holding the reference color values, must be valid
403  * @param frame The target frame which is expected to be adjusted, must be valid
404  * @param referencePaddingElements The number of padding elements at the end of each reference row, in elements, with range [0, infinity)
405  * @param framePaddingElements The number of padding elements at the end of each frame row, in elements, with range [0, infinity)
406  * @param threshold The maximal threshold which will not be exceeded by an adjustment bin, an adjustment bin with (at least) one channel exceeding this threshold will be set as invalid bin
407  * @param lookupTable The resulting lookup table, with valid and invalid bins (depending on the specified threshold and the visual differences between both frames)
408  * @param firstBin The first bin to be handled
409  * @param numberBins The number of bins to be handled
410  * @tparam tChannels The number of data channels of the given frames, with range [1, infinity)
411  */
412  template <unsigned int tChannels>
413  static void determineAdjustmentLookupTable8BitPerChannelSubset(const uint8_t* reference, const uint8_t* frame, const unsigned int referencePaddingElements, const unsigned int framePaddingElements, const Scalar threshold, LookupTable<tChannels>* lookupTable, unsigned int firstBin, const unsigned int numberBins);
414 
415  /**
416  * Determines a subset of an adjustment lookup table between two frames while for each frame an optional mask frame can specify valid and invalid pixels.
417  * @param reference The reference frame holding the reference color values, must be valid
418  * @param referenceMask An optional 8 bit mask specifying valid and invalid pixels in the reference frame, if valid 'tUseReferenceMask' must be True
419  * @param frame The target frame which is expected to be adjusted, must be valid
420  * @param frameMask An optional 8 bit mask specifying valid and invalid pixels in the target frame, if valid 'tUseFrameMask' must be True
421  * @param referencePaddingElements The number of padding elements at the end of each reference row, in elements, with range [0, infinity)
422  * @param referenceMaskPaddingElements The number of padding elements at the end of each reference mask row, in elements, with range [0, infinity), ignored if tUseReferenceMask == false
423  * @param framePaddingElements The number of padding elements at the end of each frame row, in elements, with range [0, infinity)
424  * @param frameMaskPaddingElements The number of padding elements at the end of each frame mask row, in elements, with range [0, infinity), ignored if tUseFrameMask == false
425  * @param threshold The maximal threshold which will not be exceeded by an adjustment bin, an adjustment bin with (at least) one channel exceeding this threshold will be set as invalid bin
426  * @param lookupTable The resulting lookup table, with valid and invalid bins (depending on the specified threshold and the visual differences between both frames)
427  * @param maskValue The 8 bit mask value specifying valid pixels in the mask frames
428  * @param firstBin The first bin to be handled
429  * @param numberBins The number of bins to be handled
430  * @tparam tChannels The number of data channels of the given frames, with range [1, infinity)
431  * @tparam tUseReferenceMask True, if a mask for the reference frame is specified
432  * @tparam tUseFrameMask True, if a mask for the target frame is given
433  */
434  template <unsigned int tChannels, bool tUseReferenceMask, bool tUseFrameMask>
435  static void determineAdjustmentLookupTable8BitPerChannelSubset(const uint8_t* reference, const uint8_t* referenceMask, const uint8_t* frame, const uint8_t* frameMask, const unsigned int referencePaddingElements, const unsigned int referenceMaskPaddingElements, const unsigned int framePaddingElements, const unsigned int frameMaskPaddingElements, const Scalar threshold, LookupTable<tChannels>* lookupTable, const uint8_t maskValue, unsigned int firstBin, const unsigned int numberBins);
436 
437  /**
438  * Adjusts a subset of a frame by a given color adjustment lookup table.
439  * @param frame The frame which will be adjusted, must be valid
440  * @param framePaddingElements The number of padding elements at the end of each frame row, in elements, with range [0, infinity)
441  * @param lookupTable The lookup table which is applied to adjust the given frame, the size of the table must be identical to the dimension of the given frame
442  * @param firstRow The first row to be handled
443  * @param numberRows The number of rows to be handled
444  * @tparam tChannels The number of data channels of the given frames, with range [1, infinity)
445  */
446  template <unsigned int tChannels>
447  static void adjustFrameBilinear8BitPerChannelSubset(uint8_t* frame, const unsigned int framePaddingElements, const LookupTable<tChannels>* lookupTable, const unsigned int firstRow, const unsigned int numberRows);
448 
449  /**
450  * Adjusts a subset of a frame by a given color adjustment lookup table while a mask specifies valid and invalid pixels of the frame.
451  * @param frame The frame which will be adjusted, must be valid
452  * @param mask The 8 bit mask specifying valid and invalid frame pixels, must be valid
453  * @param framePaddingElements The number of padding elements at the end of each frame row, in elements, with range [0, infinity)
454  * @param maskPaddingElements The number of padding elements at the end of each mask row, in elements, with range [0, infinity)
455  * @param lookupTable The lookup table which is applied to adjust the given frame, the size of the table must be identical to the dimension of the given frame
456  * @param maskValue The mask value defining a valid pixel
457  * @param firstRow The first row to be handled
458  * @param numberRows The number of rows to be handled
459  * @tparam tChannels The number of data channels of the given frames, with range [1, infinity)
460  */
461  template <unsigned int tChannels>
462  static void adjustFrameMaskBilinear8BitPerChannelSubset(uint8_t* frame, const uint8_t* mask, const unsigned int framePaddingElements, const unsigned int maskPaddingElements, const LookupTable<tChannels>* lookupTable, const uint8_t maskValue, const unsigned int firstRow, const unsigned int numberRows);
463 
464  /**
465  * Adjusts a subset of a frame by a given color adjustment lookup table while a mask specifies valid and invalid pixels of the frame.
466  * @param frame The frame which will be adjusted
467  * @param mask The 8 bit mask specifying valid and invalid frame pixels
468  * @param lookupTable The lookup table which is applied to adjust the given frame, the size of the table must be identical to the dimension of the given frame
469  * @param maskValue The mask value defining a valid pixel
470  * @param firstRow The first row to be handled
471  * @param numberRows The number of rows to be handled
472  * @tparam tChannels The number of data channels of the given frames, with range [1, infinity)
473  */
474  template <unsigned int tChannels>
475  static void adjustFrameMaskBilinearAdvanced8BitPerChannelSubset(uint8_t* frame, const uint8_t* mask, const AdvancedLookupTable<tChannels>* lookupTable, const uint8_t maskValue, const unsigned int firstRow, const unsigned int numberRows);
476 
477  /**
478  * Adjusts a subset of a frame by two given color adjustment lookup table each holding valid and invalid lookup bins while a mask separates the frame into two parts and thus allows to use one of both lookup tables for each individual pixel of the frame.
479  * @param frame The frame which will be adjusted
480  * @param mask The 8 bit mask specifying valid and invalid frame pixels
481  * @param lookupTableA The first lookup table (providing offset values) which is applied to adjust the given frame for 'A' mask pixels, the size of the table must be identical to the dimension of the given frame
482  * @param lookupTableB The second lookup table (providing offset values) which is applied to adjust the given frame for 'B' mask pixels, with identical size as lookupTableA
483  * @param maskValue The mask value defining 'A' pixel, all other mask values define 'B' pixels
484  * @param firstRow The first row to be handled
485  * @param numberRows The number of rows to be handled
486  * @tparam tChannels The number of data channels of the given frames, with range [1, infinity)
487  */
488  template <unsigned int tChannels>
489  static void adjustFrameMaskBilinearAdvanced8BitPerChannelSubset(uint8_t* frame, const uint8_t* mask, const AdvancedLookupTable<tChannels>* lookupTableA, const AdvancedLookupTable<tChannels>* lookupTableB, const uint8_t maskValue, const unsigned int firstRow, const unsigned int numberRows);
490 
491  /**
492  * Adjusts a subset of a frame by a given color adjustment lookup table while a mask specifies valid and invalid pixels of the frame.
493  * @param frame The frame which will be adjusted
494  * @param mask The 8 bit mask specifying valid and invalid frame pixels
495  * @param adjustedFrame The resulting adjusted frame
496  * @param lookupTable The lookup table which is applied to adjust the given frame, the size of the table must be identical to the dimension of the given frame
497  * @param maskValue The mask value defining a valid pixel
498  * @param firstRow The first row to be handled
499  * @param numberRows The number of rows to be handled
500  * @tparam tChannels The number of data channels of the given frames, with range [1, infinity)
501  * @tparam tCopyPixelForInvalidLookup True, to copy image pixels if no valid corresponding lookup value can be determined; False, to do nothing in this case
502  */
503  template <unsigned int tChannels, bool tCopyPixelForInvalidLookup>
504  static void adjustFrameMaskBilinearAdvanced8BitPerChannelSubset(const uint8_t* frame, const uint8_t* mask, uint8_t* adjustedFrame, const AdvancedLookupTable<tChannels>* lookupTable, const uint8_t maskValue, const unsigned int firstRow, const unsigned int numberRows);
505 
506  /**
507  * Adjusts a subset of a frame by two given color adjustment lookup table each holding valid and invalid lookup bins while a mask separates the frame into two parts and thus allows to use one of both lookup tables for each individual pixel of the frame.
508  * @param frame The frame which will be adjusted
509  * @param mask The 8 bit mask specifying valid and invalid frame pixels
510  * @param adjustedFrame The resulting adjusted frame
511  * @param lookupTableA The first lookup table (providing offset values) which is applied to adjust the given frame for 'A' mask pixels, the size of the table must be identical to the dimension of the given frame
512  * @param lookupTableB The second lookup table (providing offset values) which is applied to adjust the given frame for 'B' mask pixels, with identical size as lookupTableA
513  * @param maskValue The mask value defining 'A' pixel, all other mask values define 'B' pixels
514  * @param firstRow The first row to be handled
515  * @param numberRows The number of rows to be handled
516  * @tparam tChannels The number of data channels of the given frames, with range [1, infinity)
517  * @tparam tCopyPixelForInvalidLookup True, to copy image pixels if no valid corresponding lookup value can be determined; False, to do nothing in this case
518  */
519  template <unsigned int tChannels, bool tCopyPixelForInvalidLookup>
520  static void adjustFrameMaskBilinearAdvanced8BitPerChannelSubset(const uint8_t* frame, const uint8_t* mask, uint8_t* adjustedFrame, const AdvancedLookupTable<tChannels>* lookupTableA, const AdvancedLookupTable<tChannels>* lookupTableB, const uint8_t maskValue, const unsigned int firstRow, const unsigned int numberRows);
521 
522  /**
523  * Determines the mean color values for a subset of a given frame which may have valid and invalid pixels (specified by a given mask).
524  * The mean values are determined for small equally distributed bins and stored in a lookup table.<br>
525  * The resulting lookup table defines the size of the provided frame (and mask).
526  * @param frame The frame for which the mean color values will be determined, with zipped pixel format and 8 bit per channel and pixel, with frame size lookupTable.sizeX() x lookupTable.sizeY()
527  * @param mask The mask frame with 8 bit per pixel, each mask pixel has a corresponding frame pixel
528  * @param lookupTable The resulting lookup table which will received the mean color intensities of the provided frame
529  * @param maskValue The mask value defining a valid pixel, large frame areas with invalid pixels may result in lookup bins set to be invalid
530  * @param minimalSamples The minimal number of samples so that a bin counts as valid and that the mean value will be set, with range [1, infinity)
531  * @param firstBin The first bin to be handled, with range [0, lookupTable->binsY())
532  * @param numberBins The number of bins to be handled, with range [1, lookupTable->binsY() - firstBin]
533  * @tparam tChannels The number of data channels of the given frames, with range [1, infinity)
534  */
535  template <unsigned int tChannels>
536  static inline void determineMeanFrameMaskAdvanced8BitPerChannelSubset(const uint8_t* frame, const uint8_t* mask, AdvancedLookupTable<tChannels>* lookupTable, const uint8_t maskValue, const unsigned int minimalSamples, const unsigned int firstBin, const unsigned int numberBins);
537 
538  /**
539  * Determines the mean color values for a subset of a given frame separated into two parts with own lookup table for the mean values.
540  * The mean values are determined for small equally distributed bins and stored in lookup tables.<br>
541  * The resulting lookup tables must have the same size and define the size of the provided frame (and mask).
542  * @param frame The frame for which the mean color values will be determined, with zipped pixel format and 8 bit per channel and pixel, with frame size lookupTable.sizeX() x lookupTable.sizeY()
543  * @param mask The mask frame with 8 bit per pixel, each mask pixel has a corresponding frame pixel
544  * @param lookupTableA The resulting lookup table which will receive the mean color intensities of all frame pixels with 'A' mask pixels
545  * @param lookupTableB The resulting lookup table which will receive the mean color intensities of all frame pixels with 'B' mask pixels, with identical size as lookupTableA
546  * @param maskValue The mask value defining 'A' pixel, all other mask values define 'B' pixels
547  * @param minimalSamples The minimal number of samples so that a bin counts as valid and that the mean value will be set, with range [1, infinity)
548  * @param firstBin The first bin to be handled, with range [0, lookupTable->binsY())
549  * @param numberBins The number of bins to be handled, with range [1, lookupTable->binsY() - firstBin]
550  * @tparam tChannels The number of data channels of the given frames, with range [1, infinity)
551  */
552  template <unsigned int tChannels>
553  static inline void determineMeanFrameMaskAdvanced8BitPerChannelSubset(const uint8_t* frame, const uint8_t* mask, AdvancedLookupTable<tChannels>* lookupTableA, AdvancedLookupTable<tChannels>* lookupTableB, const uint8_t maskValue, const unsigned int minimalSamples, const unsigned int firstBin, const unsigned int numberBins);
554 
555  /**
556  * Determines the mean color values for a subset of a given frame separated into two parts with own lookup table for the mean values.
557  * Further, a mask is used defining valid and invalid pixels.<br>
558  * The mean values are determined for small equally distributed bins and stored in lookup tables.<br>
559  * The resulting lookup tables must have the same size and define the size of the provided frame (and mask).
560  * @param frame The frame for which the mean color values will be determined, with zipped pixel format and 8 bit per channel and pixel, with frame size lookupTable.sizeX() x lookupTable.sizeY()
561  * @param mask The mask frame with 8 bit per pixel defining valid and invalid pixels in general, each mask pixel has a corresponding frame pixel
562  * @param separationMask The separation mask frame with 8 bit per pixel separating the frame into 'A' and 'B' pixels, each mask pixel has a corresponding frame pixel
563  * @param lookupTableA The resulting lookup table which will receive the mean color intensities of all frame pixels with 'A' mask pixels
564  * @param lookupTableB The resulting lookup table which will receive the mean color intensities of all frame pixels with 'B' mask pixels, with identical size as lookupTableA
565  * @param maskValue The mask value defining valid pixels, mask pixels with different value count as invalid and will not be investigated for mean calculation, with range [0, 255]
566  * @param separationMaskValue The separation mask value defining 'A' pixel, all other mask values define 'B' pixels, with range [0, 255]
567  * @param minimalSamples The minimal number of samples so that a bin counts as valid and that the mean value will be set, with range [1, infinity)
568  * @param firstBin The first bin to be handled, with range [0, lookupTable->binsY())
569  * @param numberBins The number of bins to be handled, with range [1, lookupTable->binsY() - firstBin]
570  * @tparam tChannels The number of data channels of the given frames, with range [1, infinity)
571  */
572  template <unsigned int tChannels>
573  static inline void determineMeanFrameMaskAdvanced8BitPerChannelSubset(const uint8_t* frame, const uint8_t* mask, const uint8_t* separationMask, AdvancedLookupTable<tChannels>* lookupTableA, AdvancedLookupTable<tChannels>* lookupTableB, const uint8_t maskValue, const uint8_t separationMaskValue, const unsigned int minimalSamples, const unsigned int firstBin, const unsigned int numberBins);
574 };
575 
576 template <unsigned int tChannels>
578 {
579  static_assert(tChannels != 0u, "Invalid channel number!");
580 
581  for (unsigned int n = 0u; n < tChannels; ++n)
582  {
583  objectValues_[n] = Scalar(0);
584  }
585 }
586 
587 template <unsigned int tChannels>
589 {
590  static_assert(tChannels != 0u, "Invalid channel number!");
591 
592  ocean_assert(values != nullptr);
593 
594  for (unsigned int n = 0u; n < tChannels; ++n)
595  {
596  objectValues_[n] = values[n];
597  }
598 }
599 
600 template <unsigned int tChannels>
602 {
603  static_assert(tChannels != 0u, "Invalid channel number!");
604 
605  for (unsigned int n = 0u; n < tChannels; ++n)
606  {
607  objectValues_[n] = value;
608  }
609 }
610 
611 template <unsigned int tChannels>
613 {
614  ocean_assert(threshold >= 0);
615 
616  for (unsigned int n = 0u; n < tChannels; ++n)
617  {
618  if (Numeric::abs(objectValues_[n]) > threshold)
619  {
620  return false;
621  }
622  }
623 
624  return true;
625 }
626 
627 template <unsigned int tChannels>
629 {
630  Object<tChannels> copy(*this);
631 
632  for (unsigned int n = 0u; n < tChannels; ++n)
633  {
634  copy.objectValues_[n] += object.objectValues_[n];
635  }
636 
637  return copy;
638 }
639 
640 template <unsigned int tChannels>
642 {
643  Object<tChannels> copy(*this);
644 
645  for (unsigned int n = 0u; n < tChannels; ++n)
646  {
647  copy.objectValues_[n] -= object.objectValues_[n];
648  }
649 
650  return copy;
651 }
652 
653 template <unsigned int tChannels>
655 {
656  Object<tChannels> copy(*this);
657 
658  for (unsigned int n = 0u; n < tChannels; ++n)
659  {
660  copy.objectValues_[n] *= value;
661  }
662 
663  return copy;
664 }
665 
666 template <unsigned int tChannels>
668 {
669  Object<tChannels> copy(*this);
670 
671  ocean_assert(Numeric::isNotEqualEps(value));
672  const Scalar invValue = Scalar(1) / value;
673 
674  for (unsigned int n = 0u; n < tChannels; ++n)
675  {
676  copy.objectValues_[n] *= invValue;
677  }
678 
679  return copy;
680 }
681 
682 template <unsigned int tChannels>
683 inline Scalar FrameColorAdjustment::Object<tChannels>::operator[](const unsigned int index) const
684 {
685  ocean_assert(index < tChannels);
686  return objectValues_[index];
687 }
688 
689 template <unsigned int tChannels>
691 {
692  ocean_assert(index < tChannels);
693  return objectValues_[index];
694 }
695 
696 template <unsigned int tChannels>
697 inline void FrameColorAdjustment::adjustFrameBilinear8BitPerChannel(const uint8_t* reference, const uint8_t* referenceMask, uint8_t* frame, const uint8_t* frameMask, const unsigned int width, const unsigned int height, const unsigned int referencePaddingElements, const unsigned int referenceMaskPaddingElements, const unsigned int framePaddingElements, const unsigned int frameMaskPaddingElements, const unsigned int horizontalBins, const unsigned int verticalBins, const Scalar threshold, const uint8_t maskValue, Worker* worker)
698 {
699  ocean_assert(reference != nullptr && frame != nullptr);
700 
701  LookupTable<tChannels> lookupTable(width, height, horizontalBins, verticalBins);
702 
703  if (referenceMask != nullptr && frameMask != nullptr)
704  {
705  determineAdjustmentLookupTable8BitPerChannel<tChannels, true, true>(reference, referenceMask, frame, frameMask, referencePaddingElements, referenceMaskPaddingElements, framePaddingElements, frameMaskPaddingElements, threshold, lookupTable, maskValue, worker);
706  }
707  else if (referenceMask != nullptr)
708  {
709  determineAdjustmentLookupTable8BitPerChannel<tChannels, true, false>(reference, referenceMask, frame, nullptr, referencePaddingElements, referenceMaskPaddingElements, framePaddingElements, 0u /*frameMaskPaddingElements*/, threshold, lookupTable, maskValue, worker);
710  }
711  else if (frameMask)
712  {
713  determineAdjustmentLookupTable8BitPerChannel<tChannels, false, true>(reference, nullptr, frame, frameMask, referencePaddingElements, 0u /*referenceMaskPaddingElements*/, framePaddingElements, frameMaskPaddingElements, threshold, lookupTable, maskValue, worker);
714  }
715  else
716  {
717  determineAdjustmentLookupTable8BitPerChannel<tChannels>(reference, frame, referencePaddingElements, framePaddingElements, threshold, lookupTable, worker);
718  }
719 
720  if (frameMask)
721  {
722  adjustFrameMaskBilinear8BitPerChannel<tChannels>(frame, frameMask, framePaddingElements, frameMaskPaddingElements, lookupTable, maskValue, worker);
723  }
724  else
725  {
726  adjustFrameBilinear8BitPerChannel<tChannels>(frame, framePaddingElements, lookupTable, worker);
727  }
728 }
729 
730 template <unsigned int tChannels>
731 void FrameColorAdjustment::determineAdjustmentLookupTable8BitPerChannel(const uint8_t* reference, const uint8_t* frame, const unsigned int referencePaddingElements, const unsigned int framePaddingElements, const Scalar threshold, LookupTable<tChannels>& lookupTable, Worker* worker)
732 {
733  ocean_assert(reference != nullptr && frame != nullptr);
734  ocean_assert(!lookupTable.isEmpty());
735 
736  if (worker)
737  {
738  worker->executeFunction(Worker::Function::createStatic(&FrameColorAdjustment::determineAdjustmentLookupTable8BitPerChannelSubset<tChannels>, reference, frame, referencePaddingElements, framePaddingElements, threshold, &lookupTable, 0u, 0u), 0u, (unsigned int)(lookupTable.binsX() * lookupTable.binsY()));
739  }
740  else
741  {
742  determineAdjustmentLookupTable8BitPerChannelSubset<tChannels>(reference, frame, referencePaddingElements, framePaddingElements, threshold, &lookupTable, 0u, (unsigned int)(lookupTable.binsX() * lookupTable.binsY()));
743  }
744 }
745 
746 template <unsigned int tChannels, bool tUseReferenceMask, bool tUseFrameMask>
747 inline void FrameColorAdjustment::determineAdjustmentLookupTable8BitPerChannel(const uint8_t* reference, const uint8_t* referenceMask, const uint8_t* frame, const uint8_t* frameMask, const unsigned int referencePaddingElements, const unsigned int referenceMaskPaddingElements, const unsigned int framePaddingElements, const unsigned int frameMaskPaddingElements, const Scalar threshold, LookupTable<tChannels>& lookupTable, const uint8_t maskValue, Worker* worker)
748 {
749  ocean_assert(reference != nullptr && frame != nullptr);
750  ocean_assert(!lookupTable.isEmpty());
751 
752  if (worker)
753  {
754  worker->executeFunction(Worker::Function::createStatic(&FrameColorAdjustment::determineAdjustmentLookupTable8BitPerChannelSubset<tChannels, tUseReferenceMask, tUseFrameMask>, reference, referenceMask, frame, frameMask, referencePaddingElements, referenceMaskPaddingElements, framePaddingElements, frameMaskPaddingElements, threshold, &lookupTable, maskValue, 0u, 0u), 0u, (unsigned int)(lookupTable.binsX() * lookupTable.binsY()));
755  }
756  else
757  {
758  determineAdjustmentLookupTable8BitPerChannelSubset<tChannels, tUseReferenceMask, tUseFrameMask>(reference, referenceMask, frame, frameMask, referencePaddingElements, referenceMaskPaddingElements, framePaddingElements, frameMaskPaddingElements, threshold, &lookupTable, maskValue, 0u, (unsigned int)(lookupTable.binsX() * lookupTable.binsY()));
759  }
760 }
761 
762 template <unsigned int tChannels>
763 inline void FrameColorAdjustment::adjustFrameBilinear8BitPerChannel(uint8_t* frame, const unsigned int framePaddingElements, const LookupTable<tChannels>& lookupTable, Worker* worker)
764 {
765  static_assert(tChannels != 0u, "Invalid channel number!");
766 
767  ocean_assert(frame != nullptr);
768  ocean_assert(!lookupTable.isEmpty());
769 
770  if (worker)
771  {
772  worker->executeFunction(Worker::Function::createStatic(&FrameColorAdjustment::adjustFrameBilinear8BitPerChannelSubset<tChannels>, frame, framePaddingElements, &lookupTable, 0u, 0u), 0u, (unsigned int)(lookupTable.sizeY()));
773  }
774  else
775  {
776  adjustFrameBilinear8BitPerChannelSubset<tChannels>(frame, framePaddingElements, &lookupTable, 0u, (unsigned int)(lookupTable.sizeY()));
777  }
778 }
779 
780 template <unsigned int tChannels>
781 inline void FrameColorAdjustment::adjustFrameMaskBilinear8BitPerChannel(uint8_t* frame, const uint8_t* mask, const unsigned int framePaddingElements, const unsigned int maskPaddingElements, const LookupTable<tChannels>& lookupTable, const uint8_t maskValue, Worker* worker)
782 {
783  static_assert(tChannels != 0u, "Invalid channel number!");
784 
785  ocean_assert(frame != nullptr && mask != nullptr);
786  ocean_assert(!lookupTable.isEmpty());
787 
788  if (worker)
789  {
790  worker->executeFunction(Worker::Function::createStatic(&FrameColorAdjustment::adjustFrameMaskBilinear8BitPerChannelSubset<tChannels>, frame, mask, framePaddingElements, maskPaddingElements, &lookupTable, maskValue, 0u, 0u), 0u, (unsigned int)(lookupTable.sizeY()));
791  }
792  else
793  {
794  adjustFrameMaskBilinear8BitPerChannelSubset<tChannels>(frame, mask, framePaddingElements, maskPaddingElements, &lookupTable, maskValue, 0u, (unsigned int)(lookupTable.sizeY()));
795  }
796 }
797 
798 template <unsigned int tChannels>
799 inline void FrameColorAdjustment::adjustFrameMaskBilinearAdvanced8BitPerChannel(uint8_t* frame, const uint8_t* mask, const unsigned int framePaddingElements, const unsigned int maskPaddingElements, const AdvancedLookupTable<tChannels>& lookupTable, const uint8_t maskValue, Worker* worker)
800 {
801  static_assert(tChannels != 0u, "Invalid channel number!");
802 
803  ocean_assert(frame != nullptr && mask != nullptr);
804  ocean_assert(!lookupTable.isEmpty());
805 
806  if (worker)
807  {
808  worker->executeFunction(Worker::Function::createStatic(&FrameColorAdjustment::adjustFrameMaskBilinear8BitPerChannelSubset<tChannels>, frame, mask, framePaddingElements, maskPaddingElements, &lookupTable, maskValue, 0u, 0u), 0u, (unsigned int)(lookupTable.sizeY()));
809  }
810  else
811  {
812  adjustFrameMaskBilinear8BitPerChannelSubset<tChannels>(frame, mask, framePaddingElements, maskPaddingElements, &lookupTable, maskValue, 0u, (unsigned int)(lookupTable.sizeY()));
813  }
814 }
815 
816 template <unsigned int tChannels>
817 inline void FrameColorAdjustment::adjustFrameMaskBilinearAdvanced8BitPerChannel(uint8_t* frame, const uint8_t* mask, const unsigned int framePaddingElements, const unsigned int maskPaddingElements, const AdvancedLookupTable<tChannels>& lookupTableA, const AdvancedLookupTable<tChannels>& lookupTableB, const uint8_t maskValue, Worker* worker)
818 {
819  static_assert(tChannels != 0u, "Invalid channel number!");
820 
821  ocean_assert(frame != nullptr && mask != nullptr);
822  ocean_assert(!lookupTableA.isEmpty());
823  ocean_assert(lookupTableA.sizeX() == lookupTableB.sizeX() && lookupTableA.sizeY() == lookupTableB.sizeY());
824 
825  if (worker)
826  {
827  worker->executeFunction(Worker::Function::createStatic(&FrameColorAdjustment::adjustFrameMaskBilinear8BitPerChannelSubset<tChannels>, frame, mask, framePaddingElements, maskPaddingElements, &lookupTableA, &lookupTableB, maskValue, 0u, 0u), 0u, (unsigned int)(lookupTableA.sizeY()));
828  }
829  else
830  {
831  adjustFrameMaskBilinear8BitPerChannelSubset<tChannels>(frame, mask, framePaddingElements, maskPaddingElements, &lookupTableA, &lookupTableB, maskValue, 0u, (unsigned int)(lookupTableA.sizeY()));
832  }
833 }
834 
835 template <unsigned int tChannels, bool tCopyPixelForInvalidLookup>
836 inline void FrameColorAdjustment::adjustFrameMaskBilinearAdvanced8BitPerChannel(const uint8_t* frame, const uint8_t* mask, uint8_t* adjustedFrame, const AdvancedLookupTable<tChannels>& lookupTable, const uint8_t maskValue, Worker* worker)
837 {
838  static_assert(tChannels != 0u, "Invalid channel number!");
839 
840  ocean_assert(frame != nullptr && mask != nullptr && adjustedFrame != nullptr);
841  ocean_assert(!lookupTable.isEmpty());
842 
843  if (worker)
844  {
845  worker->executeFunction(Worker::Function::createStatic(&FrameColorAdjustment::adjustFrameMaskBilinearAdvanced8BitPerChannelSubset<tChannels, tCopyPixelForInvalidLookup>, frame, mask, adjustedFrame, &lookupTable, maskValue, 0u, 0u), 0u, (unsigned int)(lookupTable.sizeY()));
846  }
847  else
848  {
849  adjustFrameMaskBilinearAdvanced8BitPerChannelSubset<tChannels, tCopyPixelForInvalidLookup>(frame, mask, adjustedFrame, &lookupTable, maskValue, 0u, (unsigned int)(lookupTable.sizeY()));
850  }
851 }
852 
853 template <unsigned int tChannels, bool tCopyPixelForInvalidLookup>
854 inline void FrameColorAdjustment::adjustFrameMaskBilinearAdvanced8BitPerChannel(const uint8_t* frame, const uint8_t* mask, uint8_t* adjustedFrame, const AdvancedLookupTable<tChannels>& lookupTableA, const AdvancedLookupTable<tChannels>& lookupTableB, const uint8_t maskValue, Worker* worker)
855 {
856  static_assert(tChannels != 0u, "Invalid channel number!");
857 
858  ocean_assert(frame != nullptr && mask != nullptr && adjustedFrame != nullptr);
859  ocean_assert(!lookupTableA.isEmpty());
860  ocean_assert(lookupTableA.sizeX() == lookupTableB.sizeX() && lookupTableA.sizeY() == lookupTableB.sizeY());
861 
862  if (worker)
863  {
864  worker->executeFunction(Worker::Function::createStatic(&FrameColorAdjustment::adjustFrameMaskBilinearAdvanced8BitPerChannelSubset<tChannels, tCopyPixelForInvalidLookup>, frame, mask, adjustedFrame, &lookupTableA, &lookupTableB, maskValue, 0u, 0u), 0u, (unsigned int)(lookupTableA.sizeY()));
865  }
866  else
867  {
868  adjustFrameMaskBilinearAdvanced8BitPerChannelSubset<tChannels, tCopyPixelForInvalidLookup>(frame, mask, adjustedFrame, &lookupTableA, &lookupTableB, maskValue, 0u, (unsigned int)(lookupTableA.sizeY()));
869  }
870 }
871 
872 template <unsigned int tChannels, bool tCopyPixelForInvalidLookup>
873 inline void FrameColorAdjustment::adjustFrameMaskBilinearFilterAdvanced8BitPerChannel(const uint8_t* frame, const uint8_t* filterFrame, const uint8_t* mask, const uint8_t* filterMask, uint8_t* adjustedFrame, const AdvancedLookupTable<tChannels>& lookupTableA, const AdvancedLookupTable<tChannels>& lookupTableB, const uint8_t maskValue, Worker* worker)
874 {
875  static_assert(tChannels != 0u, "Invalid channel number!");
876 
877  ocean_assert(frame != nullptr && mask != nullptr && adjustedFrame != nullptr);
878  ocean_assert(!lookupTableA.isEmpty());
879  ocean_assert(lookupTableA.sizeX() == lookupTableB.sizeX() && lookupTableA.sizeY() == lookupTableB.sizeY());
880 
881  if (worker)
882  {
883  worker->executeFunction(Worker::Function::createStatic(&FrameColorAdjustment::adjustFrameMaskBilinearAdvanced8BitPerChannelSubset<tChannels, tCopyPixelForInvalidLookup>, frame, filterFrame, mask, filterMask, adjustedFrame, &lookupTableA, &lookupTableB, maskValue, 0u, 0u), 0u, (unsigned int)(lookupTableA.sizeY()));
884  }
885  else
886  {
887  adjustFrameMaskBilinearAdvanced8BitPerChannelSubset<tChannels, tCopyPixelForInvalidLookup>(frame, filterFrame, mask, filterMask, adjustedFrame, &lookupTableA, &lookupTableB, maskValue, 0u, (unsigned int)(lookupTableA.sizeY()));
888  }
889 }
890 
891 template<unsigned int tChannels>
892 inline void FrameColorAdjustment::colorMatchingTransfer(const uint8_t* frame, const uint8_t* mask, uint8_t* target, const unsigned int width, const unsigned int height, const Scalars& frameMean, const Scalars& frameStd, const Scalars& refMean, const Scalars& refStd, const uint8_t maskValue, Worker* worker)
893 {
894  static_assert(tChannels != 0u, "Invalid channel number!");
895  ocean_assert(frame != nullptr && mask != nullptr && target != nullptr);
896  ocean_assert(width != 0u && height != 0u);
897 
898  if (worker)
899  {
900  worker->executeFunction(Worker::Function::createStatic(&FrameColorAdjustment::colorMatchingTransfer8BitPerChannelSubset<tChannels>, frame, mask, target, width, height, frameMean.data(), frameStd.data(), refMean.data(), refStd.data(), 0u, 0u, maskValue), 0u, height, 9u, 10u, 20u);
901  }
902  else
903  {
904  colorMatchingTransfer8BitPerChannelSubset<tChannels>(frame, mask, target, width, height, frameMean.data(), frameStd.data(), refMean.data(), refStd.data(), 0u, height, maskValue);
905  }
906 }
907 
908 template<unsigned int tChannels>
909 inline void FrameColorAdjustment::colorMatchingTransfer8BitPerChannelSubset(const uint8_t* frame, const uint8_t* mask, uint8_t* target, const unsigned int width, const unsigned int height, const Scalar* frameMean, const Scalar* frameStd, const Scalar* refMean, const Scalar* refStd, const unsigned int firstRow, const unsigned int numberRows, const uint8_t maskValue)
910 {
911  ocean_assert(frame != nullptr && mask != nullptr && target != nullptr);
912  ocean_assert(width != 0u && height != 0u);
913 
914  ocean_assert_and_suppress_unused(firstRow + numberRows <= height, height);
915 
916  const uint8_t* pixFrame = frame;
917  const uint8_t* pixMask = mask;
918 
919  pixFrame += firstRow * width * tChannels;
920  pixMask += firstRow * width;
921  target += firstRow * width * tChannels;
922 
923  const uint8_t* const fEnd = pixFrame + (width * numberRows * tChannels);
924 
925  while (pixFrame != fEnd)
926  {
927  ocean_assert(pixFrame < fEnd);
928  if(*pixMask == maskValue)
929  {
930  for (unsigned int n = 0u; n < tChannels; ++n)
931  {
932  Scalar colorTransValue = pixFrame[n];
933  colorTransValue -= refMean[n];
934  colorTransValue *= (refStd[n] / frameStd[n]);
935  colorTransValue += frameMean[n];
936  target[n] = (uint8_t)(minmax<int>(0, Numeric::round32(colorTransValue), 255));
937  }
938  }
939  else
940  {
941  for (unsigned int n = 0u; n < tChannels; ++n)
942  {
943  target[n] = pixFrame[n];
944  }
945  }
946 
947  pixMask++;
948  pixFrame += tChannels;
949  target += tChannels;
950  }
951 }
952 
953 template <unsigned int tChannels>
954 inline void FrameColorAdjustment::determineMeanFrameMaskAdvanced8BitPerChannel(const uint8_t* frame, const uint8_t* mask, AdvancedLookupTable<tChannels>& lookupTable, const uint8_t maskValue, const unsigned int minimalSamples, Worker* worker)
955 {
956  static_assert(tChannels != 0u, "Invalid channel number!");
957 
958  ocean_assert(frame != nullptr && mask != nullptr);
959  ocean_assert(!lookupTable.isEmpty());
960  ocean_assert(minimalSamples >= 1u);
961 
962  if (worker)
963  {
964  worker->executeFunction(Worker::Function::createStatic(&FrameColorAdjustment::determineMeanFrameMaskAdvanced8BitPerChannelSubset<tChannels>, frame, mask, &lookupTable, maskValue, minimalSamples, 0u, 0u), 0u, (unsigned int)(lookupTable.binsY()));
965  }
966  else
967  {
968  determineMeanFrameMaskAdvanced8BitPerChannelSubset<tChannels>(frame, mask, &lookupTable, maskValue, minimalSamples, 0u, (unsigned int)(lookupTable.binsY()));
969  }
970 }
971 
972 template <unsigned int tChannels>
973 void FrameColorAdjustment::determineMeanFrameMaskAdvanced8BitPerChannel(const uint8_t* frame, const uint8_t* separationMask, AdvancedLookupTable<tChannels>& lookupTableA, AdvancedLookupTable<tChannels>& lookupTableB, const uint8_t separationMaskValue, const unsigned int minimalSamples, Worker* worker)
974 {
975  static_assert(tChannels != 0u, "Invalid channel number!");
976 
977  ocean_assert(frame != nullptr && separationMask != nullptr);
978  ocean_assert(!lookupTableA.isEmpty());
979  ocean_assert(lookupTableA.sizeX() == lookupTableB.sizeX() && lookupTableA.sizeY() == lookupTableB.sizeY());
980  ocean_assert(minimalSamples >= 1u);
981 
982  if (worker)
983  {
984  worker->executeFunction(Worker::Function::createStatic(&FrameColorAdjustment::determineMeanFrameMaskAdvanced8BitPerChannelSubset<tChannels>, frame, separationMask, &lookupTableA, &lookupTableB, separationMaskValue, minimalSamples, 0u, 0u), 0u, (unsigned int)(lookupTableA.binsY()));
985  }
986  else
987  {
988  determineMeanFrameMaskAdvanced8BitPerChannelSubset<tChannels>(frame, separationMask, &lookupTableA, &lookupTableB, separationMaskValue, minimalSamples, 0u, (unsigned int)(lookupTableA.binsY()));
989  }
990 }
991 
992 template <unsigned int tChannels>
993 inline void FrameColorAdjustment::determineMeanFrameMaskAdvanced8BitPerChannel(const uint8_t* frame, const uint8_t* mask, const uint8_t* separationMask, AdvancedLookupTable<tChannels>& lookupTableA, AdvancedLookupTable<tChannels>& lookupTableB, const uint8_t maskValue, const uint8_t separationMaskValue, const unsigned int minimalSamples, Worker* worker)
994 {
995  static_assert(tChannels != 0u, "Invalid channel number!");
996 
997  ocean_assert(frame != nullptr && mask != nullptr && separationMask != nullptr);
998  ocean_assert(!lookupTableA.isEmpty());
999  ocean_assert(lookupTableA.sizeX() == lookupTableB.sizeX() && lookupTableA.sizeY() == lookupTableB.sizeY());
1000  ocean_assert(minimalSamples >= 1u);
1001 
1002  if (worker)
1003  {
1004  worker->executeFunction(Worker::Function::createStatic(&FrameColorAdjustment::determineMeanFrameMaskAdvanced8BitPerChannelSubset<tChannels>, frame, mask, separationMask, &lookupTableA, &lookupTableB, maskValue, separationMaskValue, minimalSamples, 0u, 0u), 0u, (unsigned int)(lookupTableA.binsY()));
1005  }
1006  else
1007  {
1008  determineMeanFrameMaskAdvanced8BitPerChannelSubset<tChannels>(frame, mask, separationMask, &lookupTableA, &lookupTableB, maskValue, separationMaskValue, minimalSamples, 0u, (unsigned int)(lookupTableA.binsY()));
1009  }
1010 }
1011 
1012 template <unsigned int tChannels>
1013 inline void FrameColorAdjustment::determineAdjustmentLookupTable8BitPerChannelSubset(const uint8_t* reference, const uint8_t* frame, const unsigned int referencePaddingElements, const unsigned int framePaddingElements, const Scalar threshold, LookupTable<tChannels>* lookupTable, unsigned int firstBin, const unsigned int numberBins)
1014 {
1015  ocean_assert(reference != nullptr && frame != nullptr);
1016  ocean_assert(lookupTable != nullptr && !lookupTable->isEmpty());
1017 
1018  const unsigned int widthElements = (unsigned int)(lookupTable->sizeX()) * tChannels;
1019 
1020  const unsigned int referenceStrideElements = widthElements + referencePaddingElements;
1021  const unsigned int frameStrideElements = widthElements + framePaddingElements;
1022 
1023  for (unsigned int n = firstBin; n < firstBin + numberBins; ++n)
1024  {
1025  const unsigned int binY = n / (unsigned int)(lookupTable->binsX());
1026  const unsigned int binX = n - binY * (unsigned int)(lookupTable->binsX());
1027  ocean_assert(binX == n % lookupTable->binsX());
1028 
1029  const unsigned int left = (unsigned int)(lookupTable->binTopLeftX(binX));
1030  const unsigned int top = (unsigned int)(lookupTable->binTopLeftY(binY));
1031 
1032  const unsigned int right = (unsigned int)(lookupTable->binBottomRightX(binX));
1033  const unsigned int bottom = (unsigned int)(lookupTable->binBottomRightY(binY));
1034 
1035  Object<tChannels> referenceObject, frameObject;
1036 
1037  const uint8_t* framePixel = frame + top * frameStrideElements + left * tChannels;
1038  const uint8_t* referencePixel = reference + top * referenceStrideElements + left * tChannels;
1039 
1040  const unsigned int binWidthElements = (right - left + 1u) * tChannels;
1041  ocean_assert(binWidthElements <= frameStrideElements && binWidthElements <= referenceStrideElements);
1042 
1043  const unsigned int frameRowOffset = frameStrideElements - binWidthElements;
1044  const unsigned int referenceRowOffset = referenceStrideElements - binWidthElements;
1045 
1046  for (unsigned int y = top; y <= bottom; ++y)
1047  {
1048  for (unsigned int x = left; x <= right; ++x)
1049  {
1050  for (unsigned int i = 0u; i < tChannels; ++i)
1051  {
1052  frameObject[i] += framePixel[i];
1053  }
1054 
1055  for (unsigned int i = 0u; i < tChannels; ++i)
1056  {
1057  referenceObject[i] += referencePixel[i];
1058  }
1059 
1060  framePixel += tChannels;
1061  referencePixel += tChannels;
1062  }
1063 
1064  framePixel += frameRowOffset;
1065  referencePixel += referenceRowOffset;
1066  }
1067 
1068  ocean_assert((right - left + 1u) * (bottom - top + 1u) != 0u);
1069  const Scalar normalization = Scalar(1) / Scalar((right - left + 1u) * (bottom - top + 1u));
1070 
1071  Object<tChannels> object;
1072 
1073  for (unsigned int i = 0u; i < tChannels; ++i)
1074  {
1075  object[i] = (referenceObject[i] - frameObject[i]) * normalization;
1076  }
1077 
1078  if (object.belowThreshold(threshold))
1079  {
1080  lookupTable->setBinCenterValue(binX, binY, object);
1081  }
1082  else
1083  {
1084  lookupTable->setBinCenterValue(binX, binY, Object<tChannels>());
1085  }
1086  }
1087 }
1088 
1089 template <unsigned int tChannels, bool tUseReferenceMask, bool tUseFrameMask>
1090 inline void FrameColorAdjustment::determineAdjustmentLookupTable8BitPerChannelSubset(const uint8_t* reference, const uint8_t* referenceMask, const uint8_t* frame, const uint8_t* frameMask, const unsigned int referencePaddingElements, const unsigned int referenceMaskPaddingElements, const unsigned int framePaddingElements, const unsigned int frameMaskPaddingElements, const Scalar threshold, LookupTable<tChannels>* lookupTable, const uint8_t maskValue, unsigned int firstBin, const unsigned int numberBins)
1091 {
1092  ocean_assert(reference != nullptr && frame != nullptr);
1093  ocean_assert(lookupTable != nullptr && !lookupTable->isEmpty());
1094 
1095  const unsigned int widthElements = (unsigned int)(lookupTable->sizeX()) * tChannels;
1096 
1097  const unsigned int referenceStrideElements = widthElements + referencePaddingElements;
1098  const unsigned int referenceMaskStrideElements = (unsigned int)(lookupTable->sizeX()) + referenceMaskPaddingElements;
1099 
1100  const unsigned int frameStrideElements = widthElements + framePaddingElements;
1101  const unsigned int frameMaskStrideElements = (unsigned int)(lookupTable->sizeX()) + frameMaskPaddingElements;
1102 
1103  for (unsigned int n = firstBin; n < firstBin + numberBins; ++n)
1104  {
1105  const unsigned int binY = n / (unsigned int)lookupTable->binsX();
1106  const unsigned int binX = n - binY * (unsigned int)lookupTable->binsX();
1107  ocean_assert(binX == n % lookupTable->binsX());
1108 
1109  const unsigned int left = (unsigned int)lookupTable->binTopLeftX(binX);
1110  const unsigned int top = (unsigned int)lookupTable->binTopLeftY(binY);
1111 
1112  const unsigned int right = (unsigned int)lookupTable->binBottomRightX(binX);
1113  const unsigned int bottom = (unsigned int)lookupTable->binBottomRightY(binY);
1114 
1115  Object<tChannels> referenceObject, frameObject;
1116 
1117  unsigned int referenceCounter = 0u;
1118  unsigned int frameCounter = 0u;
1119 
1120  const uint8_t* framePixel = frame + top * frameStrideElements + left * tChannels;
1121  const uint8_t* frameMaskPixel = tUseFrameMask ? frameMask + top * frameMaskStrideElements + left : nullptr;
1122 
1123  const uint8_t* referencePixel = reference + top * referenceStrideElements + left * tChannels;
1124  const uint8_t* referenceMaskPixel = tUseReferenceMask ? referenceMask + top * referenceMaskStrideElements + left : nullptr;
1125 
1126  const unsigned int binWidthElements = (right - left + 1u) * tChannels;
1127  ocean_assert(binWidthElements <= frameStrideElements && binWidthElements <= referenceStrideElements);
1128 
1129  const unsigned int frameRowOffset = frameStrideElements - binWidthElements;
1130  const unsigned int frameMaskRowOffset = tUseFrameMask ? frameMaskStrideElements - (right - left + 1u) : 0u;
1131 
1132  const unsigned int referenceRowOffset = referenceStrideElements - binWidthElements;
1133  const unsigned int referenceMaskRowOffset = tUseReferenceMask ? referenceMaskStrideElements - (right - left + 1u) : 0u;
1134 
1135  for (unsigned int y = top; y <= bottom; ++y)
1136  {
1137  for (unsigned int x = left; x <= right; ++x)
1138  {
1139  if (!tUseFrameMask || *frameMaskPixel == maskValue)
1140  {
1141  for (unsigned int i = 0u; i < tChannels; ++i)
1142  {
1143  frameObject[i] += framePixel[i];
1144  }
1145 
1146  ++frameCounter;
1147  }
1148 
1149  if (!tUseReferenceMask || *referenceMaskPixel == maskValue)
1150  {
1151  for (unsigned int i = 0u; i < tChannels; ++i)
1152  {
1153  referenceObject[i] += referencePixel[i];
1154  }
1155 
1156  ++referenceCounter;
1157  }
1158 
1159  framePixel += tChannels;
1160  referencePixel += tChannels;
1161 
1162  if constexpr (tUseFrameMask)
1163  {
1164  ++frameMaskPixel;
1165  }
1166 
1167  if constexpr (tUseReferenceMask)
1168  {
1169  ++referenceMaskPixel;
1170  }
1171  }
1172 
1173  framePixel += frameRowOffset;
1174  referencePixel += referenceRowOffset;
1175 
1176  if constexpr (tUseFrameMask)
1177  {
1178  frameMaskPixel += frameMaskRowOffset;
1179  }
1180 
1181  if constexpr (tUseReferenceMask)
1182  {
1183  referenceMaskPixel += referenceMaskRowOffset;
1184  }
1185  }
1186 
1187  if (frameCounter != 0u && referenceCounter != 0u)
1188  {
1189  const Scalar frameNormalization = Scalar(1) / Scalar(frameCounter);
1190  const Scalar referenceNormalization = Scalar(1) / Scalar(referenceCounter);
1191 
1192  Object<tChannels> object;
1193 
1194  for (unsigned int i = 0u; i < tChannels; ++i)
1195  {
1196  object[i] = referenceObject[i] * referenceNormalization - frameObject[i] * frameNormalization;
1197  }
1198 
1199  if (object.belowThreshold(threshold))
1200  {
1201  lookupTable->setBinCenterValue(binX, binY, object);
1202  }
1203  else
1204  {
1205  lookupTable->setBinCenterValue(binX, binY, Object<tChannels>());
1206  }
1207  }
1208  }
1209 }
1210 
1211 template <unsigned int tChannels>
1212 void FrameColorAdjustment::adjustFrameBilinear8BitPerChannelSubset(uint8_t* frame, const unsigned int framePaddingElements, const LookupTable<tChannels>* lookupTable, const unsigned int firstRow, const unsigned int numberRows)
1213 {
1214  static_assert(tChannels != 0u, "Invalid channel number!");
1215 
1216  ocean_assert(frame != nullptr);
1217  ocean_assert(lookupTable != nullptr && !lookupTable->isEmpty());
1218  ocean_assert(firstRow + numberRows <= lookupTable->sizeY());
1219 
1220  const unsigned int frameStrideElements = (unsigned int)(lookupTable->sizeX()) * tChannels + framePaddingElements;
1221 
1222  frame += firstRow * frameStrideElements;
1223 
1224  for (unsigned int y = firstRow; y < firstRow + numberRows; ++y)
1225  {
1226  for (unsigned int x = 0u; x < (unsigned int)(lookupTable->sizeX()); ++x)
1227  {
1228  const Object<tChannels> object(lookupTable->bilinearValue(Scalar(x), Scalar(y)));
1229 
1230  for (unsigned int n = 0u; n < tChannels; ++n)
1231  {
1232  frame[n] = (uint8_t)(minmax<int>(0, Numeric::round32(Scalar(frame[n]) + object[n]), 255));
1233  }
1234 
1235  frame += tChannels;
1236  }
1237 
1238  frame += framePaddingElements;
1239  }
1240 }
1241 
1242 template <unsigned int tChannels>
1243 void FrameColorAdjustment::adjustFrameMaskBilinear8BitPerChannelSubset(uint8_t* frame, const uint8_t* mask, const unsigned int framePaddingElements, const unsigned int maskPaddingElements, const LookupTable<tChannels>* lookupTable, const uint8_t maskValue, const unsigned int firstRow, const unsigned int numberRows)
1244 {
1245  static_assert(tChannels != 0u, "Invalid channel number!");
1246 
1247  ocean_assert(frame != nullptr && mask != nullptr);
1248  ocean_assert(lookupTable != nullptr && !lookupTable->isEmpty());
1249  ocean_assert(firstRow + numberRows <= lookupTable->sizeY());
1250 
1251  const unsigned int frameStrideElements = (unsigned int)(lookupTable->sizeX()) * tChannels + framePaddingElements;
1252  const unsigned int maskStrideElements = (unsigned int)(lookupTable->sizeX()) + maskPaddingElements;
1253 
1254  frame += firstRow * frameStrideElements;
1255  mask += firstRow * maskStrideElements;
1256 
1257  for (unsigned int y = firstRow; y < firstRow + numberRows; ++y)
1258  {
1259  for (unsigned int x = 0u; x < (unsigned int)lookupTable->sizeX(); ++x)
1260  {
1261  if (*mask == maskValue)
1262  {
1263  const Object<tChannels> object(lookupTable->bilinearValue(Scalar(x), Scalar(y)));
1264 
1265  for (unsigned int n = 0u; n < tChannels; ++n)
1266  {
1267  frame[n] = (uint8_t)(minmax<int>(0, Numeric::round32(Scalar(frame[n]) + object[n]), 255));
1268  }
1269  }
1270 
1271  frame += tChannels;
1272  ++mask;
1273  }
1274 
1275  frame += framePaddingElements;
1276  mask += maskPaddingElements;
1277  }
1278 }
1279 
1280 template <unsigned int tChannels>
1281 void FrameColorAdjustment::adjustFrameMaskBilinearAdvanced8BitPerChannelSubset(uint8_t* frame, const uint8_t* mask, const AdvancedLookupTable<tChannels>* lookupTable, const uint8_t maskValue, const unsigned int firstRow, const unsigned int numberRows)
1282 {
1283  static_assert(tChannels != 0u, "Invalid channel number!");
1284 
1285  ocean_assert(frame != nullptr && mask != nullptr);
1286  ocean_assert(lookupTable != nullptr && !lookupTable->isEmpty());
1287  ocean_assert(firstRow + numberRows <= lookupTable->sizeY());
1288 
1289  frame += firstRow * lookupTable->sizeX() * tChannels;
1290  mask += firstRow * lookupTable->sizeX();
1291 
1292  Object<tChannels> object;
1293 
1294  for (unsigned int y = firstRow; y < firstRow + numberRows; ++y)
1295  {
1296  for (unsigned int x = 0u; x < (unsigned int)lookupTable->sizeX(); ++x)
1297  {
1298  if (*mask == maskValue && lookupTable->bilinearValue(Scalar(x), Scalar(y), object))
1299  {
1300  for (unsigned int n = 0u; n < tChannels; ++n)
1301  frame[n] = minmax<int>(0, Numeric::round32(Scalar(frame[n]) + object[n]), 255);
1302  }
1303 
1304  frame += tChannels;
1305  mask++;
1306  }
1307  }
1308 }
1309 
1310 template <unsigned int tChannels>
1311 void FrameColorAdjustment::adjustFrameMaskBilinearAdvanced8BitPerChannelSubset(uint8_t* frame, const uint8_t* mask, const AdvancedLookupTable<tChannels>* lookupTableA, const AdvancedLookupTable<tChannels>* lookupTableB, const uint8_t maskValue, const unsigned int firstRow, const unsigned int numberRows)
1312 {
1313  static_assert(tChannels != 0u, "Invalid channel number!");
1314 
1315  ocean_assert(frame != nullptr && mask != nullptr);
1316  ocean_assert(lookupTableA != nullptr && lookupTableB != nullptr && !lookupTableA->isEmpty());
1317  ocean_assert(lookupTableA->sizeX() == lookupTableB->sizeX() && lookupTableA->sizeY() == lookupTableB->sizeY());
1318  ocean_assert(firstRow + numberRows <= lookupTableA->sizeY());
1319 
1320  frame += firstRow * lookupTableA->sizeX() * tChannels;
1321  mask += firstRow * lookupTableA->sizeX();
1322 
1323  Object<tChannels> object;
1324 
1325  for (unsigned int y = firstRow; y < firstRow + numberRows; ++y)
1326  {
1327  for (unsigned int x = 0u; x < (unsigned int)lookupTableA->sizeX(); ++x)
1328  {
1329  if (*mask == maskValue)
1330  {
1331  if (lookupTableA->bilinearValue(Scalar(x), Scalar(y), object))
1332  {
1333  for (unsigned int n = 0u; n < tChannels; ++n)
1334  frame[n] = minmax<int>(0, Numeric::round32(Scalar(frame[n]) + object[n]), 255);
1335  }
1336  }
1337  else
1338  {
1339  ocean_assert(*mask != maskValue);
1340 
1341  if (lookupTableB->bilinearValue(Scalar(x), Scalar(y), object))
1342  {
1343  for (unsigned int n = 0u; n < tChannels; ++n)
1344  frame[n] = minmax<int>(0, Numeric::round32(Scalar(frame[n]) + object[n]), 255);
1345  }
1346  }
1347 
1348  frame += tChannels;
1349  mask++;
1350  }
1351  }
1352 }
1353 
1354 template <unsigned int tChannels, bool tCopyPixelForInvalidLookup>
1355 void FrameColorAdjustment::adjustFrameMaskBilinearAdvanced8BitPerChannelSubset(const uint8_t* frame, const uint8_t* mask, uint8_t* adjustedFrame, const AdvancedLookupTable<tChannels>* lookupTable, const uint8_t maskValue, const unsigned int firstRow, const unsigned int numberRows)
1356 {
1357  static_assert(tChannels != 0u, "Invalid channel number!");
1358 
1359  ocean_assert(frame != nullptr && mask != nullptr && adjustedFrame != nullptr);
1360  ocean_assert(lookupTable != nullptr && !lookupTable->isEmpty());
1361  ocean_assert(firstRow + numberRows <= lookupTable->sizeY());
1362 
1363  typedef typename DataType<uint8_t, tChannels>::Type PixelType;
1364 
1365  frame += firstRow * lookupTable->sizeX() * tChannels;
1366  adjustedFrame += firstRow * lookupTable->sizeX() * tChannels;
1367  mask += firstRow * lookupTable->sizeX();
1368 
1369  Object<tChannels> object;
1370 
1371  for (unsigned int y = firstRow; y < firstRow + numberRows; ++y)
1372  {
1373  for (unsigned int x = 0u; x < (unsigned int)lookupTable->sizeX(); ++x)
1374  {
1375  if (*mask == maskValue)
1376  {
1377  if (lookupTable->bilinearValue(Scalar(x), Scalar(y), object))
1378  {
1379  for (unsigned int n = 0u; n < tChannels; ++n)
1380  {
1381  adjustedFrame[n] = minmax<int>(0, Numeric::round32(Scalar(frame[n]) + object[n]), 255);
1382  }
1383  }
1384  else
1385  {
1386  if constexpr (tCopyPixelForInvalidLookup)
1387  {
1388  *((PixelType*)adjustedFrame) = *((PixelType*)frame);
1389  }
1390  }
1391  }
1392 
1393  frame += tChannels;
1394  adjustedFrame += tChannels;
1395  mask++;
1396  }
1397  }
1398 }
1399 
1400 template <unsigned int tChannels, bool tCopyPixelForInvalidLookup>
1401 void FrameColorAdjustment::adjustFrameMaskBilinearAdvanced8BitPerChannelSubset(const uint8_t* frame, const uint8_t* mask, uint8_t* adjustedFrame, const AdvancedLookupTable<tChannels>* lookupTableA, const AdvancedLookupTable<tChannels>* lookupTableB, const uint8_t maskValue, const unsigned int firstRow, const unsigned int numberRows)
1402 {
1403  static_assert(tChannels != 0u, "Invalid channel number!");
1404 
1405  ocean_assert(frame != nullptr && mask != nullptr && adjustedFrame != nullptr);
1406  ocean_assert(lookupTableA != nullptr && lookupTableB != nullptr && !lookupTableA->isEmpty());
1407  ocean_assert(lookupTableA->sizeX() == lookupTableB->sizeX() && lookupTableA->sizeY() == lookupTableB->sizeY());
1408  ocean_assert(firstRow + numberRows <= lookupTableA->sizeY());
1409 
1410  typedef typename DataType<uint8_t, tChannels>::Type PixelType;
1411 
1412  frame += firstRow * lookupTableA->sizeX() * tChannels;
1413  adjustedFrame += firstRow * lookupTableA->sizeX() * tChannels;
1414  mask += firstRow * lookupTableA->sizeX();
1415 
1416  Object<tChannels> object;
1417 
1418  for (unsigned int y = firstRow; y < firstRow + numberRows; ++y)
1419  {
1420  for (unsigned int x = 0u; x < (unsigned int)(lookupTableA->sizeX()); ++x)
1421  {
1422  if (*mask == maskValue)
1423  {
1424  if (lookupTableA->bilinearValue(Scalar(x), Scalar(y), object))
1425  {
1426  //object = lookupTableA->binCenterValue(lookupTableA->binX(x), lookupTableA->binY(y));
1427  for (unsigned int n = 0u; n < tChannels; ++n)
1428  {
1429  adjustedFrame[n] = minmax<int>(0, Numeric::round32(Scalar(frame[n]) + object[n]), 255);
1430  }
1431  }
1432  else
1433  {
1434  if constexpr (tCopyPixelForInvalidLookup)
1435  {
1436  *((PixelType*)adjustedFrame) = *((PixelType*)frame);
1437  }
1438  }
1439  }
1440  else
1441  {
1442  ocean_assert(*mask != maskValue);
1443 
1444  if (lookupTableB->bilinearValue(Scalar(x), Scalar(y), object))
1445  {
1446  //object = lookupTableB->binCenterValue(lookupTableB->binX(x), lookupTableB->binY(y));
1447  for (unsigned int n = 0u; n < tChannels; ++n)
1448  {
1449  adjustedFrame[n] = minmax<int>(0, Numeric::round32(Scalar(frame[n]) + object[n]), 255);
1450  }
1451  }
1452  else
1453  {
1454  if constexpr (tCopyPixelForInvalidLookup)
1455  {
1456  *((PixelType*)adjustedFrame) = *((PixelType*)frame);
1457  }
1458  }
1459  }
1460 
1461  frame += tChannels;
1462  adjustedFrame += tChannels;
1463  mask++;
1464  }
1465  }
1466 }
1467 
1468 template <unsigned int tChannels>
1469 inline void FrameColorAdjustment::determineMeanFrameMaskAdvanced8BitPerChannelSubset(const uint8_t* frame, const uint8_t* mask, AdvancedLookupTable<tChannels>* lookupTable, const uint8_t maskValue, const unsigned int minimalSamples, const unsigned int firstBin, const unsigned int numberBins)
1470 {
1471  ocean_assert(frame != nullptr && mask != nullptr);
1472  ocean_assert(lookupTable != nullptr && !lookupTable->isEmpty());
1473  ocean_assert(minimalSamples >= 1u);
1474 
1475  ocean_assert(firstBin + numberBins <= lookupTable->binsY());
1476 
1477  const unsigned int width = lookupTable->sizeX();
1478 
1479  for (unsigned int yBin = firstBin; yBin < firstBin + numberBins; ++yBin)
1480  {
1481  for (unsigned int xBin = 0u; xBin < lookupTable->binsX(); ++xBin)
1482  {
1483  const unsigned int left = (unsigned int)lookupTable->binTopLeftX(xBin);
1484  const unsigned int top = (unsigned int)lookupTable->binTopLeftY(yBin);
1485 
1486  const unsigned int right = (unsigned int)lookupTable->binBottomRightX(xBin);
1487  const unsigned int bottom = (unsigned int)lookupTable->binBottomRightY(yBin);
1488 
1489  Object<tChannels> value;
1490  unsigned int samples = 0u;
1491 
1492  for (unsigned int y = top; y <= bottom; ++y)
1493  {
1494  for (unsigned int x = left; x <= right; ++x)
1495  {
1496  if (mask[y * width + x] == maskValue)
1497  {
1498  for (unsigned int n = 0u; n < tChannels; ++n)
1499  {
1500  value[n] += Scalar(frame[tChannels * (y * width + x) + n]);
1501  }
1502 
1503  samples++;
1504  }
1505  }
1506  }
1507 
1508  if (samples >= minimalSamples)
1509  {
1510  lookupTable->setBinCenterValue(xBin, yBin, value / Scalar(samples), true);
1511  }
1512  else
1513  {
1514  lookupTable->setBinCenterValue(xBin, yBin, Object<tChannels>(), false);
1515  }
1516  }
1517  }
1518 }
1519 
1520 template <unsigned int tChannels>
1521 inline void FrameColorAdjustment::determineMeanFrameMaskAdvanced8BitPerChannelSubset(const uint8_t* frame, const uint8_t* separationMask, AdvancedLookupTable<tChannels>* lookupTableA, AdvancedLookupTable<tChannels>* lookupTableB, const uint8_t separationMaskValue, const unsigned int minimalSamples, const unsigned int firstBin, const unsigned int numberBins)
1522 {
1523  ocean_assert(frame != nullptr && separationMask != nullptr);
1524  ocean_assert(lookupTableA != nullptr && !lookupTableA->isEmpty());
1525  ocean_assert(lookupTableB != nullptr && lookupTableA->sizeX() == lookupTableB->sizeX() && lookupTableA->sizeY() == lookupTableB->sizeY());
1526  ocean_assert(minimalSamples >= 1u);
1527 
1528  ocean_assert(firstBin + numberBins <= lookupTableA->binsY());
1529 
1530  const unsigned int width = (unsigned int)lookupTableA->sizeX();
1531 
1532  for (unsigned int yBin = firstBin; yBin < firstBin + numberBins; ++yBin)
1533  {
1534  for (unsigned int xBin = 0u; xBin < lookupTableA->binsX(); ++xBin)
1535  {
1536  const unsigned int left = (unsigned int)lookupTableA->binTopLeftX(xBin);
1537  const unsigned int top = (unsigned int)lookupTableA->binTopLeftY(yBin);
1538 
1539  const unsigned int right = (unsigned int)lookupTableA->binBottomRightX(xBin);
1540  const unsigned int bottom = (unsigned int)lookupTableA->binBottomRightY(yBin);
1541 
1542  Object<tChannels> valueA;
1543  Object<tChannels> valueB;
1544  unsigned int samplesA = 0u;
1545  unsigned int samplesB = 0u;
1546 
1547  for (unsigned int y = top; y <= bottom; ++y)
1548  {
1549  for (unsigned int x = left; x <= right; ++x)
1550  {
1551  if (separationMask[y * width + x] == separationMaskValue)
1552  {
1553  for (unsigned int n = 0u; n < tChannels; ++n)
1554  {
1555  valueA[n] += Scalar(frame[tChannels * (y * width + x) + n]);
1556  }
1557 
1558  samplesA++;
1559  }
1560  else
1561  {
1562  for (unsigned int n = 0u; n < tChannels; ++n)
1563  {
1564  valueB[n] += Scalar(frame[tChannels * (y * width + x) + n]);
1565  }
1566 
1567  samplesB++;
1568  }
1569  }
1570  }
1571 
1572  if (samplesA >= minimalSamples)
1573  {
1574  lookupTableA->setBinCenterValue(xBin, yBin, valueA / Scalar(samplesA), true);
1575  }
1576  else
1577  {
1578  lookupTableA->setBinCenterValue(xBin, yBin, Object<tChannels>(), false);
1579  }
1580 
1581  if (samplesB >= minimalSamples)
1582  {
1583  lookupTableB->setBinCenterValue(xBin, yBin, valueB / Scalar(samplesB), true);
1584  }
1585  else
1586  {
1587  lookupTableB->setBinCenterValue(xBin, yBin, Object<tChannels>(), false);
1588  }
1589  }
1590  }
1591 }
1592 
1593 template <unsigned int tChannels>
1594 inline void FrameColorAdjustment::determineMeanFrameMaskAdvanced8BitPerChannelSubset(const uint8_t* frame, const uint8_t* mask, const uint8_t* separationMask, AdvancedLookupTable<tChannels>* lookupTableA, AdvancedLookupTable<tChannels>* lookupTableB, const uint8_t maskValue, const uint8_t separationMaskValue, const unsigned int minimalSamples, const unsigned int firstBin, const unsigned int numberBins)
1595 {
1596  ocean_assert(frame != nullptr && mask != nullptr && separationMask != nullptr);
1597  ocean_assert(lookupTableA != nullptr && !lookupTableA->isEmpty());
1598  ocean_assert(lookupTableB != nullptr && lookupTableA->sizeX() == lookupTableB->sizeX() && lookupTableA->sizeY() == lookupTableB->sizeY());
1599  ocean_assert(minimalSamples >= 1u);
1600 
1601  ocean_assert(firstBin + numberBins <= lookupTableA->binsY());
1602 
1603  const unsigned int width = (unsigned int)lookupTableA->sizeX();
1604 
1605  for (unsigned int yBin = firstBin; yBin < firstBin + numberBins; ++yBin)
1606  {
1607  for (unsigned int xBin = 0u; xBin < lookupTableA->binsX(); ++xBin)
1608  {
1609  const unsigned int left = (unsigned int)lookupTableA->binTopLeftX(xBin);
1610  const unsigned int top = (unsigned int)lookupTableA->binTopLeftY(yBin);
1611 
1612  const unsigned int right = (unsigned int)lookupTableA->binBottomRightX(xBin);
1613  const unsigned int bottom = (unsigned int)lookupTableA->binBottomRightY(yBin);
1614 
1615  Object<tChannels> valueA;
1616  Object<tChannels> valueB;
1617  unsigned int samplesA = 0u;
1618  unsigned int samplesB = 0u;
1619 
1620  for (unsigned int y = top; y <= bottom; ++y)
1621  {
1622  for (unsigned int x = left; x <= right; ++x)
1623  {
1624  if (mask[y * width + x] == maskValue)
1625  {
1626  if (separationMask[y * width + x] == separationMaskValue)
1627  {
1628  for (unsigned int n = 0u; n < tChannels; ++n)
1629  valueA[n] += Scalar(frame[tChannels * (y * width + x) + n]);
1630 
1631  samplesA++;
1632  }
1633  else
1634  {
1635  for (unsigned int n = 0u; n < tChannels; ++n)
1636  valueB[n] += Scalar(frame[tChannels * (y * width + x) + n]);
1637 
1638  samplesB++;
1639  }
1640  }
1641  }
1642  }
1643 
1644  if (samplesA >= minimalSamples)
1645  {
1646  lookupTableA->setBinCenterValue(xBin, yBin, valueA / Scalar(samplesA), true);
1647  }
1648  else
1649  {
1650  lookupTableA->setBinCenterValue(xBin, yBin, Object<tChannels>(), false);
1651  }
1652 
1653  if (samplesB >= minimalSamples)
1654  {
1655  lookupTableB->setBinCenterValue(xBin, yBin, valueB / Scalar(samplesB), true);
1656  }
1657  else
1658  {
1659  lookupTableB->setBinCenterValue(xBin, yBin, Object<tChannels>(), false);
1660  }
1661  }
1662  }
1663 }
1664 
1665 }
1666 
1667 }
1668 
1669 }
1670 
1671 #endif // META_OCEAN_CV_ADVANCED_FRAME_COLOR_ADJUSTMENT_H
This class implements an advanced 2D lookup object with values at the bins' center positions defining...
Definition: Lookup2.h:424
bool bilinearValue(const TScalar x, const TScalar y, T &value) const
Applies a lookup for a specific position in this lookup object.
Definition: Lookup2.h:1468
void setBinCenterValue(const size_t binX, const size_t binY, const T &value, const bool isValid)
Sets the value of one specific lookup bin's center and defines whether this bin is valid.
Definition: Lookup2.h:1600
This class implements an bin adjustment object supporting an arbitrary number of data channels.
Definition: FrameColorAdjustment.h:41
Object operator-(const Object &object) const
Subtract operator subtracting two objects element by element.
Definition: FrameColorAdjustment.h:641
Scalar operator[](const unsigned int index) const
Index operator returning one element of this object.
Definition: FrameColorAdjustment.h:683
Object operator/(const Scalar value) const
Division operator dividing all elements of this object by a scalar.
Definition: FrameColorAdjustment.h:667
Object operator+(const Object &object) const
Add operator adding two objects element by element.
Definition: FrameColorAdjustment.h:628
Scalar objectValues_[tChannels]
The object's elements.
Definition: FrameColorAdjustment.h:113
Object operator*(const Scalar value) const
Multiplication operator multiplying all elements of this object by a scalar.
Definition: FrameColorAdjustment.h:654
Object()
Creates a new object with values set to zero.
Definition: FrameColorAdjustment.h:577
bool belowThreshold(const Scalar threshold) const
Returns whether the absolute value of each element of this object is below or equal to a specified th...
Definition: FrameColorAdjustment.h:612
This class implements color adjustment functions between frames.
Definition: FrameColorAdjustment.h:32
static void adjustFrameMaskBilinear8BitPerChannel(uint8_t *frame, const uint8_t *mask, const unsigned int framePaddingElements, const unsigned int maskPaddingElements, const LookupTable< tChannels > &lookupTable, const uint8_t maskValue, Worker *worker=nullptr)
Adjusts a frame by a given color adjustment lookup table while a mask specifies valid and invalid pix...
Definition: FrameColorAdjustment.h:781
static void determineAdjustmentLookupTable8BitPerChannel(const uint8_t *reference, const uint8_t *frame, const unsigned int referencePaddingElements, const unsigned int framePaddingElements, const Scalar threshold, LookupTable< tChannels > &lookupTable, Worker *worker=nullptr)
Determines the adjustment lookup table between two frames.
Definition: FrameColorAdjustment.h:731
static void adjustFrameMaskBilinearAdvanced8BitPerChannel(uint8_t *frame, const uint8_t *mask, const unsigned int framePaddingElements, const unsigned int maskPaddingElements, const AdvancedLookupTable< tChannels > &lookupTable, const uint8_t maskValue, Worker *worker=nullptr)
Adjusts a frame by a given color adjustment lookup table holding valid and invalid lookup bins while ...
Definition: FrameColorAdjustment.h:799
static bool adjustFrameBilinear(const Frame &reference, const Frame &referenceMask, Frame &frame, const Frame &frameMask, const unsigned int horizontalBins, const unsigned int verticalBins, const Scalar threshold=Scalar(20), const uint8_t maskValue=0xFF, Worker *worker=nullptr)
Adjusts the color values of one frame with respect to a given reference frame both showing almost the...
static void adjustFrameMaskBilinear8BitPerChannelSubset(uint8_t *frame, const uint8_t *mask, const unsigned int framePaddingElements, const unsigned int maskPaddingElements, const LookupTable< tChannels > *lookupTable, const uint8_t maskValue, const unsigned int firstRow, const unsigned int numberRows)
Adjusts a subset of a frame by a given color adjustment lookup table while a mask specifies valid and...
Definition: FrameColorAdjustment.h:1243
static void adjustFrameBilinear8BitPerChannel(const uint8_t *reference, const uint8_t *referenceMask, uint8_t *frame, const uint8_t *frameMask, const unsigned int width, const unsigned int height, const unsigned int referencePaddingElements, const unsigned int referenceMaskPaddingElements, const unsigned int framePaddingElements, const unsigned int frameMaskPaddingElements, const unsigned int horizontalBins, const unsigned int verticalBins, const Scalar threshold=Scalar(20), const uint8_t maskValue=0xFF, Worker *worker=nullptr)
Adjusts the color values of one frame with respect to a given reference frame both showing almost the...
Definition: FrameColorAdjustment.h:697
static void determineAdjustmentLookupTable8BitPerChannelSubset(const uint8_t *reference, const uint8_t *frame, const unsigned int referencePaddingElements, const unsigned int framePaddingElements, const Scalar threshold, LookupTable< tChannels > *lookupTable, unsigned int firstBin, const unsigned int numberBins)
Determines a subset of an adjustment lookup table between two frames.
Definition: FrameColorAdjustment.h:1013
static void determineMeanFrameMaskAdvanced8BitPerChannelSubset(const uint8_t *frame, const uint8_t *mask, AdvancedLookupTable< tChannels > *lookupTable, const uint8_t maskValue, const unsigned int minimalSamples, const unsigned int firstBin, const unsigned int numberBins)
Determines the mean color values for a subset of a given frame which may have valid and invalid pixel...
Definition: FrameColorAdjustment.h:1469
static void colorMatchingTransfer8BitPerChannelSubset(const uint8_t *frame, const uint8_t *mask, uint8_t *target, const unsigned int width, const unsigned int height, const Scalar *frameMean, const Scalar *frameStd, const Scalar *refMean, const Scalar *refStd, const unsigned int firstRow, const unsigned int numberRows, const uint8_t maskValue)
Compute color statistics for the source and target images.
Definition: FrameColorAdjustment.h:909
static void adjustFrameMaskBilinearAdvanced8BitPerChannelSubset(uint8_t *frame, const uint8_t *mask, const AdvancedLookupTable< tChannels > *lookupTable, const uint8_t maskValue, const unsigned int firstRow, const unsigned int numberRows)
Adjusts a subset of a frame by a given color adjustment lookup table while a mask specifies valid and...
Definition: FrameColorAdjustment.h:1281
static void adjustFrameMaskBilinearFilterAdvanced8BitPerChannel(const uint8_t *frame, const uint8_t *filterFrame, const uint8_t *mask, const uint8_t *filterMask, uint8_t *adjustedFrame, const AdvancedLookupTable< tChannels > &lookupTableA, const AdvancedLookupTable< tChannels > &lookupTableB, const uint8_t maskValue, Worker *worker=nullptr)
Adjusts a frame by two given color adjustment lookup table each holding valid and invalid lookup bins...
Definition: FrameColorAdjustment.h:873
static void colorMatchingTransfer(const uint8_t *frame, const uint8_t *mask, uint8_t *target, const unsigned int width, const unsigned int height, const std::vector< Scalar > &frameMean, const std::vector< Scalar > &frameStd, const std::vector< Scalar > &refMean, const std::vector< Scalar > &refStd, const uint8_t maskValue, Worker *worker=nullptr)
Adjust a color transfer algorithm that uses the mean and standard deviation of the image channels.
static void determineMeanFrameMaskAdvanced8BitPerChannel(const uint8_t *frame, const uint8_t *mask, AdvancedLookupTable< tChannels > &lookupTable, const uint8_t maskValue, const unsigned int minimalSamples, Worker *worker=nullptr)
Determines the mean color values of a given frame which may have valid and invalid pixels (specified ...
Definition: FrameColorAdjustment.h:954
static void adjustFrameBilinear8BitPerChannelSubset(uint8_t *frame, const unsigned int framePaddingElements, const LookupTable< tChannels > *lookupTable, const unsigned int firstRow, const unsigned int numberRows)
Adjusts a subset of a frame by a given color adjustment lookup table.
Definition: FrameColorAdjustment.h:1212
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
Template class allowing to define an array of data types.
Definition: DataType.h:27
This class implements Ocean's image class.
Definition: Frame.h:1792
size_t sizeY() const
Returns the vertical dimension of this lookup object.
Definition: Lookup2.h:947
size_t sizeX() const
Returns the horizontal dimension of this lookup object.
Definition: Lookup2.h:941
bool isEmpty() const
Returns whether this lookup object does not hold any lookup bin.
Definition: Lookup2.h:1009
size_t binsY() const
Returns the number of vertical bins of this lookup object.
Definition: Lookup2.h:959
size_t binsX() const
Returns the number of horizontal bins of this lookup object.
Definition: Lookup2.h:953
This class implements a 2D lookup object with values at the bins' center positions defining the indiv...
Definition: Lookup2.h:198
void setBinCenterValue(const size_t binX, const size_t binY, const T &value)
Sets the value of one specific lookup bin's center.
Definition: Lookup2.h:1380
size_t binTopLeftY(const size_t binY) const
Returns the vertical top left position of a specified bin with pixel accuracy.
Definition: Lookup2.h:1168
size_t binBottomRightY(const size_t binY) const
Returns the vertical bottom right position of a specified bin with pixel accuracy.
Definition: Lookup2.h:1192
size_t binBottomRightX(const size_t binX) const
Returns the horizontal bottom right position (including) of a specified bin with pixel accuracy.
Definition: Lookup2.h:1179
size_t binTopLeftX(const size_t binX) const
Returns the horizontal top left position of a specified bin with pixel accuracy.
Definition: Lookup2.h:1157
T bilinearValue(const TScalar x, const TScalar y) const
Applies a lookup for a specific position in this lookup object.
Definition: Lookup2.h:1260
static T abs(const T value)
Returns the absolute value of a given value.
Definition: Numeric.h:1220
static constexpr int32_t round32(const T value)
Returns the rounded 32 bit integer value of a given value.
Definition: Numeric.h:2064
static constexpr bool isNotEqualEps(const T value)
Returns whether a value is not smaller than or equal to a small epsilon.
Definition: Numeric.h:2237
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.
float Scalar
Definition of a scalar type.
Definition: Math.h:128
std::vector< Scalar > Scalars
Definition of a vector holding Scalar objects.
Definition: Math.h:144
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:484
AutomaticDifferentiationT< T1, TNumeric1 > operator/(const T2 &left, const AutomaticDifferentiationT< T1, TNumeric1 > &right)
Definition: AutomaticDifferentiation.h:572
AutomaticDifferentiationT< T1, TNumeric1 > operator*(const T2 &left, const AutomaticDifferentiationT< T1, TNumeric1 > &right)
Definition: AutomaticDifferentiation.h:524
AutomaticDifferentiationT< T1, TNumeric1 > operator+(const T2 &left, const AutomaticDifferentiationT< T1, TNumeric1 > &right)
Definition: AutomaticDifferentiation.h:418