193 ocean_assert(frame !=
nullptr);
194 ocean_assert(width != 0u && height != 0u);
196 ocean_assert_accuracy(extremumValue !=
nullptr || extremumLocation !=
nullptr);
198 const unsigned int frameStrideElements = width + framePaddingElements;
200 unsigned char internalExtremumValue = frame[0];
203 if (width >= 16u && width < 65535u && height < 65535u)
222 const uint16x8_t constant_8_u_16x8 = vdupq_n_u16(8u);
224 const uint16x8_t constant_16_u_16x8 = vdupq_n_u16(16u);
227 uint16x8_t extremumLocationX_01234567_u_16x8 = constant_01234567_u_16x8;
228 uint16x8_t extremumLocationX_89ABCDEF_u_16x8 = vaddq_u16(constant_01234567_u_16x8, constant_8_u_16x8);
230 uint16x8_t extremumLocationY_01234567_u_16x8 = vdupq_n_u16(0u);
231 uint16x8_t extremumLocationY_89ABCDEF_u_16x8 = vdupq_n_u16(0u);
233 uint8x16_t extremumValue_u_8x16 = vld1q_u8(frame + 0);
235 for (
unsigned int y = 0u; y < height; ++y)
238 const uint16x8_t candidateLocation_y_u_16x8 = vdupq_n_u16(uint16_t(y));
241 uint16x8_t candidateLocation_01234567_x_u_16x8 = constant_01234567_u_16x8;
242 uint16x8_t candidateLocation_89ABCDEF_x_u_16x8 = vaddq_u16(constant_01234567_u_16x8, constant_8_u_16x8);
244 for (
unsigned int x = 0u; x < width; x += 16u)
251 ocean_assert(x >= 16u && width > 16u);
252 const unsigned int newX = width - 16u;
254 ocean_assert(x > newX);
255 const unsigned int offset = x - newX;
256 ocean_assert(offset < 16u);
260 candidateLocation_01234567_x_u_16x8 = vsubq_u16(candidateLocation_01234567_x_u_16x8, vdupq_n_u16(uint16_t(offset)));
261 candidateLocation_89ABCDEF_x_u_16x8 = vsubq_u16(candidateLocation_89ABCDEF_x_u_16x8, vdupq_n_u16(uint16_t(offset)));
264 ocean_assert(!(x + 16u < width));
267 const uint8x16_t candidates_u_8x16 = vld1q_u8(frame + x);
274 const uint8x16_t mask_u_8x16 = tDetermineMinimum ? vcltq_u8(candidates_u_8x16, extremumValue_u_8x16) : vcgtq_u8(candidates_u_8x16, extremumValue_u_8x16);
277 extremumValue_u_8x16 = vbslq_u8(mask_u_8x16, candidates_u_8x16, extremumValue_u_8x16);
280 uint16x8_t mask_01234567_u_16x8 = vmovl_u8(vget_low_u8(mask_u_8x16));
281 uint16x8_t mask_89ABCDEF_u_16x8 = vmovl_u8(vget_high_u8(mask_u_8x16));
282 mask_01234567_u_16x8 = vorrq_u16(mask_01234567_u_16x8, vshlq_n_u16(mask_01234567_u_16x8, 8));
283 mask_89ABCDEF_u_16x8 = vorrq_u16(mask_89ABCDEF_u_16x8, vshlq_n_u16(mask_89ABCDEF_u_16x8, 8));
286 extremumLocationX_01234567_u_16x8 = vbslq_u16(mask_01234567_u_16x8, candidateLocation_01234567_x_u_16x8, extremumLocationX_01234567_u_16x8);
287 extremumLocationX_89ABCDEF_u_16x8 = vbslq_u16(mask_89ABCDEF_u_16x8, candidateLocation_89ABCDEF_x_u_16x8, extremumLocationX_89ABCDEF_u_16x8);
290 extremumLocationY_01234567_u_16x8 = vbslq_u16(mask_01234567_u_16x8, candidateLocation_y_u_16x8, extremumLocationY_01234567_u_16x8);
291 extremumLocationY_89ABCDEF_u_16x8 = vbslq_u16(mask_89ABCDEF_u_16x8, candidateLocation_y_u_16x8, extremumLocationY_89ABCDEF_u_16x8);
294 candidateLocation_01234567_x_u_16x8 = vaddq_u16(candidateLocation_01234567_x_u_16x8, constant_16_u_16x8);
295 candidateLocation_89ABCDEF_x_u_16x8 = vaddq_u16(candidateLocation_89ABCDEF_x_u_16x8, constant_16_u_16x8);
298 frame += frameStrideElements;
303 const uint8x8_t extremumValue_01234567_u_8x8 = vget_low_u8(extremumValue_u_8x16);
304 const uint8x8_t extremumValue_89ABCDEF_u_8x8 = vget_high_u8(extremumValue_u_8x16);
306 const uint8x8_t mask_u_8x8 = tDetermineMinimum ? vclt_u8(extremumValue_01234567_u_8x8, extremumValue_89ABCDEF_u_8x8) : vcgt_u8(extremumValue_01234567_u_8x8, extremumValue_89ABCDEF_u_8x8);
307 const uint8x8_t extremumValue_u_8x8 = vbsl_u8(mask_u_8x8, extremumValue_01234567_u_8x8, extremumValue_89ABCDEF_u_8x8);
309 uint16x8_t mask_u_16x8 = vmovl_u8(mask_u_8x8);
310 mask_u_16x8 = vorrq_u16(mask_u_16x8, vshlq_n_u16(mask_u_16x8, 8));
312 const uint16x8_t extremumLocationX_u_16x8 = vbslq_u16(mask_u_16x8, extremumLocationX_01234567_u_16x8, extremumLocationX_89ABCDEF_u_16x8);
313 const uint16x8_t extremumLocationY_u_16x8 = vbslq_u16(mask_u_16x8, extremumLocationY_01234567_u_16x8, extremumLocationY_89ABCDEF_u_16x8);
317 uint16_t extremumLocationsX[8];
318 vst1q_u16(extremumLocationsX, extremumLocationX_u_16x8);
320 uint16_t extremumLocationsY[8];
321 vst1q_u16(extremumLocationsY, extremumLocationY_u_16x8);
323 unsigned char extremumValues[8];
324 vst1_u8(extremumValues, extremumValue_u_8x8);
326 internalExtremumValue = extremumValues[0];
327 internalExtremumLocation =
CV::PixelPosition((
unsigned int)(extremumLocationsX[0]), (
unsigned int)(extremumLocationsY[0]));
329 for (
unsigned int n = 1u; n < 8u; ++n)
331 if (tDetermineMinimum ? (extremumValues[n] < internalExtremumValue) : (extremumValues[n] > internalExtremumValue))
333 internalExtremumValue = extremumValues[n];
334 internalExtremumLocation =
CV::PixelPosition((
unsigned int)(extremumLocationsX[n]), (
unsigned int)(extremumLocationsY[n]));
340 for (
unsigned int y = 0u; y < height; ++y)
342 for (
unsigned int x = 0u; x < width; ++x)
344 if (tDetermineMinimum ? (frame[x] < internalExtremumValue) : (frame[x] > internalExtremumValue))
346 internalExtremumValue = frame[x];
351 frame += frameStrideElements;
357 *extremumValue = internalExtremumValue;
360 if (extremumLocation)
362 *extremumLocation = internalExtremumLocation;
370 ocean_assert(frame !=
nullptr);
371 ocean_assert(width != 0u && height != 0u);
373 ocean_assert_accuracy(extremumValue !=
nullptr || extremumLocation !=
nullptr);
375 const unsigned int frameStrideElements = width + framePaddingElements;
377 float internalExtremumValue = frame[0];
399 const uint32x4_t constant_4_u_32x4 = vdupq_n_u32(4u);
401 const uint32x4_t constant_8_u_32x4 = vdupq_n_u32(8u);
404 uint32x4_t extremumLocationX_0123_u_32x4 = constant_0123_u_32x4;
405 uint32x4_t extremumLocationX_4567_u_32x4 = vaddq_u32(constant_0123_u_32x4, constant_4_u_32x4);
407 uint32x4_t extremumLocationY_0123_u_32x4 = vdupq_n_u32(0u);
408 uint32x4_t extremumLocationY_4567_u_32x4 = vdupq_n_u32(0u);
410 float32x4_t extremumValue_0123_f_32x4 = vld1q_f32(frame + 0);
411 float32x4_t extremumValue_4567_f_32x4 = vld1q_f32(frame + 4);
413 for (
unsigned int y = 0u; y < height; ++y)
416 const uint32x4_t candidateLocation_y_u_32x4 = vdupq_n_u32(y);
419 uint32x4_t candidateLocation_0123_x_u_32x4 = constant_0123_u_32x4;
420 uint32x4_t candidateLocation_4567_x_u_32x4 = vaddq_u32(constant_0123_u_32x4, constant_4_u_32x4);
422 for (
unsigned int x = 0u; x < width; x += 8u)
429 ocean_assert(x >= 8u && width > 8u);
430 const unsigned int newX = width - 8u;
432 ocean_assert(x > newX);
433 const unsigned int offset = x - newX;
434 ocean_assert(offset < 8u);
438 candidateLocation_0123_x_u_32x4 = vsubq_u32(candidateLocation_0123_x_u_32x4, vdupq_n_u32(offset));
439 candidateLocation_4567_x_u_32x4 = vsubq_u32(candidateLocation_4567_x_u_32x4, vdupq_n_u32(offset));
442 ocean_assert(!(x + 8u < width));
445 const float32x4_t candidates_0123_f_32x4 = vld1q_f32(frame + x + 0u);
446 const float32x4_t candidates_4567_f_32x4 = vld1q_f32(frame + x + 4u);
453 const uint32x4_t mask_0123_u_32x4 = tDetermineMinimum ? vcltq_f32(candidates_0123_f_32x4, extremumValue_0123_f_32x4) : vcgtq_f32(candidates_0123_f_32x4, extremumValue_0123_f_32x4);
454 const uint32x4_t mask_4567_u_32x4 = tDetermineMinimum ? vcltq_f32(candidates_4567_f_32x4, extremumValue_4567_f_32x4) : vcgtq_f32(candidates_4567_f_32x4, extremumValue_4567_f_32x4);
457 extremumValue_0123_f_32x4 = vbslq_f32(mask_0123_u_32x4, candidates_0123_f_32x4, extremumValue_0123_f_32x4);
458 extremumValue_4567_f_32x4 = vbslq_f32(mask_4567_u_32x4, candidates_4567_f_32x4, extremumValue_4567_f_32x4);
460 extremumLocationX_0123_u_32x4 = vbslq_u32(mask_0123_u_32x4, candidateLocation_0123_x_u_32x4, extremumLocationX_0123_u_32x4);
461 extremumLocationX_4567_u_32x4 = vbslq_u32(mask_4567_u_32x4, candidateLocation_4567_x_u_32x4, extremumLocationX_4567_u_32x4);
463 extremumLocationY_0123_u_32x4 = vbslq_u32(mask_0123_u_32x4, candidateLocation_y_u_32x4, extremumLocationY_0123_u_32x4);
464 extremumLocationY_4567_u_32x4 = vbslq_u32(mask_4567_u_32x4, candidateLocation_y_u_32x4, extremumLocationY_4567_u_32x4);
467 candidateLocation_0123_x_u_32x4 = vaddq_u32(candidateLocation_0123_x_u_32x4, constant_8_u_32x4);
468 candidateLocation_4567_x_u_32x4 = vaddq_u32(candidateLocation_4567_x_u_32x4, constant_8_u_32x4);
471 frame += frameStrideElements;
474 const uint32x4_t mask_u_32x4 = tDetermineMinimum ? vcltq_f32(extremumValue_0123_f_32x4, extremumValue_4567_f_32x4) : vcgtq_f32(extremumValue_0123_f_32x4, extremumValue_4567_f_32x4);
475 extremumValue_0123_f_32x4 = vbslq_f32(mask_u_32x4, extremumValue_0123_f_32x4, extremumValue_4567_f_32x4);
476 extremumLocationX_0123_u_32x4 = vbslq_u32(mask_u_32x4, extremumLocationX_0123_u_32x4, extremumLocationX_4567_u_32x4);
477 extremumLocationY_0123_u_32x4 = vbslq_u32(mask_u_32x4, extremumLocationY_0123_u_32x4, extremumLocationY_4567_u_32x4);
481 unsigned int extremumLocationsX[4];
482 vst1q_u32(extremumLocationsX, extremumLocationX_0123_u_32x4);
484 unsigned int extremumLocationsY[4];
485 vst1q_u32(extremumLocationsY, extremumLocationY_0123_u_32x4);
487 float extremumValues[4];
488 vst1q_f32(extremumValues, extremumValue_0123_f_32x4);
490 internalExtremumValue = extremumValues[0];
491 internalExtremumLocation =
CV::PixelPosition(extremumLocationsX[0], extremumLocationsY[0]);
493 for (
unsigned int n = 1u; n < 4u; ++n)
495 if (tDetermineMinimum ? (extremumValues[n] < internalExtremumValue) : (extremumValues[n] > internalExtremumValue))
497 internalExtremumValue = extremumValues[n];
498 internalExtremumLocation =
CV::PixelPosition(extremumLocationsX[n], extremumLocationsY[n]);
504 for (
unsigned int y = 0u; y < height; ++y)
506 for (
unsigned int x = 0u; x < width; ++x)
508 if (tDetermineMinimum ? (frame[x] < internalExtremumValue) : (frame[x] > internalExtremumValue))
510 internalExtremumValue = frame[x];
515 frame += frameStrideElements;
521 *extremumValue = internalExtremumValue;
524 if (extremumLocation)
526 *extremumLocation = internalExtremumLocation;
547 static_assert(tChannels >= 1u,
"Invalid channel number!");
549 ocean_assert(frame !=
nullptr && minimalValues !=
nullptr && maximalValues !=
nullptr);
550 ocean_assert(width >= 1u && height >= 1u);
552 for (
unsigned int n = 0u; n < tChannels; ++n)
557 for (
unsigned int n = 0u; n < tChannels; ++n)
565 worker->
executeFunction(
Worker::Function::createStatic(determineMinMaxValuesSubset<T, tChannels, tIgnoreInfinity>, frame, width, height, minimalValues, maximalValues, &lock, framePaddingElements, 0u, 0u), 0u, height, 7u, 8u, 20u);
569 determineMinMaxValuesSubset<T, tChannels, tIgnoreInfinity>(frame, width, height, minimalValues, maximalValues,
nullptr, framePaddingElements, 0u, height);
582bool FrameMinMax::countElementsOutsideRange(
const T* frame,
const uint32_t width,
const uint32_t height,
const uint32_t framePaddingElements,
const T rangeStart,
const T rangeEnd, uint32_t* elementsBelowRange, uint32_t* elementsAboveRange)
584 if (frame ==
nullptr || width == 0u || height == 0u || rangeStart > rangeEnd || (elementsBelowRange ==
nullptr && elementsAboveRange ==
nullptr))
586 ocean_assert(
false &&
"Invalid input");
590 const uint32_t frameStrideElements = width + framePaddingElements;
591 const T*
const frameEnd = frame + height * frameStrideElements - framePaddingElements;
593 uint32_t elementsBelowRangeLocal = 0u;
594 uint32_t elementsAboveRangeLocal = 0u;
596 if (framePaddingElements == 0u)
598 while (frame < frameEnd)
600 if (*frame < rangeStart)
602 ++elementsBelowRangeLocal;
604 else if (*frame >= rangeEnd)
606 ++elementsAboveRangeLocal;
614 for (uint32_t y = 0u; y < height; ++y)
616 const T* frameRowEnd = frame + width;
618 while (frame < frameRowEnd)
620 if (*frame < rangeStart)
622 ++elementsBelowRangeLocal;
624 else if (*frame >= rangeEnd)
626 ++elementsAboveRangeLocal;
632 frame += framePaddingElements;
636 if (elementsBelowRange)
638 *elementsBelowRange = elementsBelowRangeLocal;
641 if (elementsAboveRange)
643 *elementsAboveRange = elementsAboveRangeLocal;
650void FrameMinMax::determineMinMaxValuesSubset(
const T* frame,
const unsigned int width,
const unsigned int height, T* minimalValues, T* maximalValues,
Lock* lock,
const unsigned int framePaddingElements,
const unsigned int firstRow,
const unsigned int numberRows)
652 static_assert(tChannels >= 1u,
"Invalid channel number!");
654 ocean_assert(frame !=
nullptr && minimalValues !=
nullptr && maximalValues !=
nullptr);
655 ocean_assert(width >= 1u && height >= 1u);
656 ocean_assert_and_suppress_unused(firstRow + numberRows <= height, height);
658 T localMinimal[tChannels];
659 for (
unsigned int n = 0u; n < tChannels; ++n)
664 T localMaximal[tChannels];
665 for (
unsigned int n = 0u; n < tChannels; ++n)
670 const unsigned int frameStrideElements = width * tChannels + framePaddingElements;
672 frame += firstRow * frameStrideElements;
674 const T*
const frameEnd = frame + numberRows * frameStrideElements;
675 while (frame != frameEnd)
677 ocean_assert(frame < frameEnd);
679 const T*
const frameRowEnd = frame + width * tChannels;
681 while (frame != frameRowEnd)
683 ocean_assert(frame < frameRowEnd);
684 ocean_assert(frame < frameEnd);
686 for (
unsigned int n = 0u; n < tChannels; ++n)
688 if constexpr (tIgnoreInfinity && std::is_floating_point<T>::value)
692 if (frame[n] < localMinimal[n])
694 localMinimal[n] = frame[n];
697 if (frame[n] > localMaximal[n])
699 localMaximal[n] = frame[n];
705 if (frame[n] < localMinimal[n])
707 localMinimal[n] = frame[n];
710 if (frame[n] > localMaximal[n])
712 localMaximal[n] = frame[n];
720 frame += framePaddingElements;
725 for (
unsigned int n = 0u; n < tChannels; ++n)
727 minimalValues[n] = min(minimalValues[n], localMinimal[n]);
728 maximalValues[n] = max(maximalValues[n], localMaximal[n]);
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:2877