Ocean
Loading...
Searching...
No Matches
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
18namespace Ocean
19{
20
21namespace CV
22{
23
24namespace Advanced
25{
26
27/**
28 * This class implements color adjustment functions between frames.
29 * @ingroup cvadvanced
30 */
31class 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
576template <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
587template <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
600template <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
611template <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
627template <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
640template <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
653template <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
666template <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
682template <unsigned int tChannels>
684{
685 ocean_assert(index < tChannels);
686 return objectValues_[index];
687}
688
689template <unsigned int tChannels>
691{
692 ocean_assert(index < tChannels);
693 return objectValues_[index];
694}
695
696template <unsigned int tChannels>
697inline 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
730template <unsigned int tChannels>
731void 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
746template <unsigned int tChannels, bool tUseReferenceMask, bool tUseFrameMask>
747inline 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
762template <unsigned int tChannels>
763inline 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
780template <unsigned int tChannels>
781inline 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
798template <unsigned int tChannels>
799inline 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
816template <unsigned int tChannels>
817inline 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
835template <unsigned int tChannels, bool tCopyPixelForInvalidLookup>
836inline 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
853template <unsigned int tChannels, bool tCopyPixelForInvalidLookup>
854inline 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
872template <unsigned int tChannels, bool tCopyPixelForInvalidLookup>
873inline 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
891template<unsigned int tChannels>
892inline 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
908template<unsigned int tChannels>
909inline 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
953template <unsigned int tChannels>
954inline 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
972template <unsigned int tChannels>
973void 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
992template <unsigned int tChannels>
993inline 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
1012template <unsigned int tChannels>
1013inline 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
1089template <unsigned int tChannels, bool tUseReferenceMask, bool tUseFrameMask>
1090inline 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
1211template <unsigned int tChannels>
1212void 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
1242template <unsigned int tChannels>
1243void 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
1280template <unsigned int tChannels>
1281void 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
1310template <unsigned int tChannels>
1311void 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
1354template <unsigned int tChannels, bool tCopyPixelForInvalidLookup>
1355void 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
1400template <unsigned int tChannels, bool tCopyPixelForInvalidLookup>
1401void 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
1468template <unsigned int tChannels>
1469inline 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
1520template <unsigned int tChannels>
1521inline 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
1593template <unsigned int tChannels>
1594inline 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
This class implements Ocean's image class.
Definition Frame.h:1808
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:129
std::vector< Scalar > Scalars
Definition of a vector holding Scalar objects.
Definition Math.h:145
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:524
AutomaticDifferentiationT< T1, TNumeric1 > operator+(const T2 &left, const AutomaticDifferentiationT< T1, TNumeric1 > &right)
Definition AutomaticDifferentiation.h:418
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:484
Default definition of a type with tBytes bytes.
Definition DataType.h:32