8 #ifndef META_OCEAN_CV_FRAME_FILTER_SOBEL_H
9 #define META_OCEAN_CV_FRAME_FILTER_SOBEL_H
17 #if defined(OCEAN_HARDWARE_SSE_VERSION) && OCEAN_HARDWARE_SSE_VERSION >= 41
98 template <
typename TTarget,
unsigned int tSourceChannels>
99 static inline void filterHorizontalVertical8BitPerChannel(
const uint8_t* source, TTarget* target,
const unsigned int width,
const unsigned int height,
const unsigned int sourcePaddingElements,
const unsigned int targetPaddingElements,
Worker* worker =
nullptr);
116 template <
typename TTarget,
unsigned int tSourceChannels>
117 static inline void filterDiagonal8BitPerChannel(
const uint8_t* source, TTarget* target,
const unsigned int width,
const unsigned int height,
const unsigned int sourcePaddingElements,
const unsigned int targetPaddingElements,
Worker* worker =
nullptr);
134 template <
typename TTarget,
unsigned int tSourceChannels>
135 static inline void filter8BitPerChannel(
const uint8_t* source, TTarget* target,
const unsigned int width,
const unsigned int height,
const unsigned int sourcePaddingElements,
const unsigned int targetPaddingElements,
Worker* worker =
nullptr);
152 template <
typename TTarget,
unsigned int tSourceChannels>
153 static inline void filterHorizontalVerticalMaximumAbsolute8BitPerChannel(
const uint8_t* source, TTarget* target,
const unsigned int width,
const unsigned int height,
const unsigned int sourcePaddingElements,
const unsigned int targetPaddingElements,
Worker* worker =
nullptr);
171 template <
typename TTarget,
unsigned int tChannels,
bool tIsCorePixel = false>
172 static inline void filterPixelHorizontalVerticalMaximum8BitPerChannel(
const uint8_t*
const source,
const unsigned int width,
const unsigned int height,
const unsigned int x,
const unsigned int y, TTarget*
const response,
unsigned int sourcePaddingElements);
189 template <
typename TTarget,
unsigned int tSourceChannels>
190 static inline void filterPixelHorizontalVertical8BitPerChannel(
const uint8_t* source,
const unsigned int width,
const unsigned int height,
const unsigned int x,
const unsigned int y, TTarget* response,
const unsigned int sourcePaddingElements);
203 template <
typename TTarget,
unsigned int tSourceChannels>
204 static inline void filterPixelCoreHorizontalVertical8BitPerChannel(
const uint8_t* source,
const unsigned int width, TTarget* response,
const unsigned int sourcePaddingElements);
217 template <
typename TTarget, TTarget tNormalizationDenominator,
bool tRoundedNormalization = false>
218 static inline void filterPixelCoreHorizontalVertical3Squared1Channel8Bit(
const uint8_t* source,
const unsigned int width, TTarget* responses,
const unsigned int paddingElements);
252 template <
typename TSource,
typename TTarget,
unsigned int tSourceChannels,
unsigned int tTargetChannels>
253 static void filterHorizontalVerticalRow(
const TSource* sourceRow, TTarget* targetRow,
const unsigned int width,
const unsigned int height,
unsigned int rowIndex,
const unsigned int sourceStrideElements,
const unsigned int targetStrideElements);
269 template <
typename TSource,
typename TTarget,
unsigned int tSourceChannels,
unsigned int tTargetChannels>
270 static void filterDiagonalRow(
const TSource* sourceRow, TTarget* targetRow,
const unsigned int width,
const unsigned int height,
unsigned int rowIndex,
const unsigned int sourceStrideElements,
const unsigned int targetStrideElements);
287 template <
typename TSource,
typename TTarget,
unsigned int tSourceChannels,
unsigned int tTargetChannels>
288 static void filterRow(
const TSource* sourceRow, TTarget* targetRow,
const unsigned int width,
const unsigned int height,
unsigned int rowIndex,
const unsigned int sourceStrideElements,
const unsigned int targetStrideElements);
304 template <
typename TSource,
typename TTarget,
unsigned int tSourceChannels,
unsigned int tTargetChannels>
305 static void filterHorizontalVerticalMaximumAbsoluteRow(
const TSource* sourceRow, TTarget* targetRow,
const unsigned int width,
const unsigned int height,
unsigned int rowIndex,
const unsigned int sourceStrideElements,
const unsigned int targetStrideElements);
307 #if defined(OCEAN_HARDWARE_SSE_VERSION) && OCEAN_HARDWARE_SSE_VERSION >= 41
321 static inline void filterHorizontalVertical8BitBlock14SSE(
const uint8_t* source0,
const uint8_t* source1,
const uint8_t* source2, __m128i& response_x_low, __m128i& response_x_high, __m128i& response_y_low, __m128i& response_y_high);
331 static inline void filterHorizontalVertical1Channel8BitBlock14SSE(
const uint8_t* source,
const unsigned int strideElements, int16_t* response);
342 static inline void filterHorizontalVertical1Channel8BitBlock14SSE(
const uint8_t* source,
const unsigned int strideElements, int8_t* response);
347 template <
typename TTarget,
unsigned int tSourceChannels>
350 static_assert(std::is_same<TTarget, int8_t>::value || std::is_same<TTarget, int16_t>::value,
"Invalid target data type!");
351 static_assert(tSourceChannels >= 1u,
"Invalid channel number!");
353 ocean_assert(source !=
nullptr && target !=
nullptr);
354 ocean_assert(width >= 3u && height >= 3u);
357 constexpr
unsigned int tTargetChannels = tSourceChannels * 2u;
359 FrameChannels::applyRowOperator<uint8_t, TTarget, tSourceChannels, tTargetChannels>(source, target, width, height, sourcePaddingElements, targetPaddingElements, &filterHorizontalVerticalRow<uint8_t, TTarget, tSourceChannels, tTargetChannels>, worker);
362 template <
typename TTarget,
unsigned int tSourceChannels>
365 static_assert(std::is_same<TTarget, int8_t>::value || std::is_same<TTarget, int16_t>::value,
"Invalid target data type!");
366 static_assert(tSourceChannels >= 1u,
"Invalid channel number!");
368 ocean_assert(source !=
nullptr && target !=
nullptr);
369 ocean_assert(width >= 3u && height >= 3u);
372 constexpr
unsigned int tTargetChannels = tSourceChannels * 2u;
374 FrameChannels::applyRowOperator<uint8_t, TTarget, tSourceChannels, tTargetChannels>(source, target, width, height, sourcePaddingElements, targetPaddingElements, &filterDiagonalRow<uint8_t, TTarget, tSourceChannels, tTargetChannels>, worker);
377 template <
typename TTarget,
unsigned int tSourceChannels>
378 inline void FrameFilterSobel::filter8BitPerChannel(
const uint8_t* source, TTarget* target,
const unsigned int width,
const unsigned int height,
const unsigned int sourcePaddingElements,
const unsigned int targetPaddingElements,
Worker* worker)
380 static_assert(std::is_same<TTarget, int8_t>::value || std::is_same<TTarget, int16_t>::value,
"Invalid target data type!");
381 static_assert(tSourceChannels >= 1u,
"Invalid channel number!");
383 ocean_assert(source !=
nullptr && target !=
nullptr);
384 ocean_assert(width >= 3u && height >= 3u);
387 constexpr
unsigned int tTargetChannels = tSourceChannels * 4u;
389 FrameChannels::applyRowOperator<uint8_t, TTarget, tSourceChannels, tTargetChannels>(source, target, width, height, sourcePaddingElements, targetPaddingElements, &filterRow<uint8_t, TTarget, tSourceChannels, tTargetChannels>, worker);
392 template <
typename TTarget,
unsigned int tSourceChannels>
395 static_assert(std::is_same<TTarget, uint8_t>::value || std::is_same<TTarget, uint16_t>::value,
"Invalid target data type!");
396 static_assert(tSourceChannels >= 1u,
"Invalid channel number!");
398 ocean_assert(source !=
nullptr && target !=
nullptr);
399 ocean_assert(width >= 3u && height >= 3u);
402 constexpr
unsigned int tTargetChannels = tSourceChannels;
404 FrameChannels::applyRowOperator<uint8_t, TTarget, tSourceChannels, tTargetChannels>(source, target, width, height, sourcePaddingElements, targetPaddingElements, &filterHorizontalVerticalMaximumAbsoluteRow<uint8_t, TTarget, tSourceChannels, tTargetChannels>, worker);
407 template <
typename TSource,
typename TTarget,
unsigned int tSourceChannels,
unsigned int tTargetChannels>
410 static_assert(std::is_same<TSource, uint8_t>::value,
"Invalid source data type!");
411 static_assert(std::is_same<TTarget, int8_t>::value || std::is_same<TTarget, int16_t>::value,
"Invalid target data type!");
413 static_assert(tSourceChannels >= 1u,
"Invalid source channel number!");
414 static_assert(tTargetChannels == tSourceChannels * 2u,
"Invalid target channel number!");
416 ocean_assert(width >= 3u && height >= 3u);
418 if (rowIndex == 0u || rowIndex == height - 1u)
422 memset(targetRow, 0, width * tTargetChannels *
sizeof(TTarget));
428 for (
unsigned int n = 0u; n < tTargetChannels; ++n)
430 targetRow[n] = TTarget(0);
433 targetRow += tTargetChannels;
435 #if defined(OCEAN_HARDWARE_SSE_VERSION) && OCEAN_HARDWARE_SSE_VERSION >= 41
437 if constexpr (tSourceChannels == 1u)
441 const unsigned int blockNumber = (width - 2u) / 14u;
443 for (
unsigned int iBlock = 0u; iBlock < blockNumber; iBlock++)
446 targetRow += 14u * 2u;
452 const unsigned int blockRest = (width - 2u) % 14u;
457 sourceRow -= (14u - blockRest);
458 targetRow -= (14u - blockRest) * 2u;
463 targetRow += 14u * 2u;
467 for (
unsigned int n = 0u; n < tTargetChannels; ++n)
469 targetRow[n] = TTarget(0);
478 const uint8_t* source0 = sourceRow - sourceStrideElements;
479 const uint8_t* source1 = sourceRow;
480 const uint8_t* source2 = sourceRow + sourceStrideElements;
482 for (
unsigned int x = 1u; x < width - 1u; ++x)
484 if constexpr (std::is_same<TTarget, int8_t>::value)
486 for (
unsigned int n = 0u; n < tSourceChannels; ++n)
491 *targetRow++ = TTarget((*(source0 + tSourceChannels * 2u) - *(source0) + (*(source1 + tSourceChannels * 2u) - *(source1)) * 2 + *(source2 + tSourceChannels * 2u) - *(source2)) / 8);
496 *targetRow++ = TTarget((*(source2) + (*(source2 + tSourceChannels) - *(source0 + tSourceChannels)) * 2 + *(source2 + tSourceChannels * 2u) - *(source0) - *(source0 + tSourceChannels * 2u)) / 8);
505 ocean_assert((std::is_same<TTarget, int16_t>::value));
507 for (
unsigned int n = 0u; n < tSourceChannels; ++n)
512 *targetRow++ = TTarget(*(source0 + tSourceChannels * 2u) - *(source0) + (*(source1 + tSourceChannels * 2u) - *(source1)) * 2 + *(source2 + tSourceChannels * 2u) - *(source2));
517 *targetRow++ = TTarget(*(source2) + (*(source2 + tSourceChannels) - *(source0 + tSourceChannels)) * 2 + *(source2 + tSourceChannels * 2u) - *(source0) - *(source0 + tSourceChannels * 2u));
527 for (
unsigned int n = 0u; n < tTargetChannels; ++n)
529 targetRow[n] = TTarget(0);
533 template <
typename TSource,
typename TTarget,
unsigned int tSourceChannels,
unsigned int tTargetChannels>
534 void FrameFilterSobel::filterDiagonalRow(
const TSource* sourceRow, TTarget* targetRow,
const unsigned int width,
const unsigned int height,
unsigned int rowIndex,
const unsigned int sourceStrideElements,
const unsigned int )
536 static_assert(std::is_same<TSource, uint8_t>::value,
"Invalid source data type!");
537 static_assert(std::is_same<TTarget, int8_t>::value || std::is_same<TTarget, int16_t>::value,
"Invalid target data type!");
539 static_assert(tSourceChannels >= 1u,
"Invalid source channel number!");
540 static_assert(tTargetChannels == tSourceChannels * 2u,
"Invalid target channel number!");
542 ocean_assert(width >= 3u && height >= 3u);
544 if (rowIndex == 0u || rowIndex == height - 1u)
548 memset(targetRow, 0, width * tTargetChannels *
sizeof(TTarget));
554 for (
unsigned int n = 0u; n < tTargetChannels; ++n)
556 targetRow[n] = TTarget(0);
559 targetRow += tTargetChannels;
561 const uint8_t* source0 = sourceRow - sourceStrideElements;
562 const uint8_t* source1 = sourceRow;
563 const uint8_t* source2 = sourceRow + sourceStrideElements;
565 for (
unsigned int x = 1u; x < width - 1u; ++x)
567 if constexpr (std::is_same<TTarget, int8_t>::value)
569 for (
unsigned int n = 0u; n < tSourceChannels; ++n)
574 *targetRow++ = TTarget((*(source1 + tSourceChannels * 2u) + *(source2 + tSourceChannels) + (*(source2 + tSourceChannels * 2u) - *(source0)) * 2 - *(source0 + tSourceChannels) - *(source1)) / 8);
579 *targetRow++ = TTarget((*(source1) + *(source2 + tSourceChannels) + (*(source2) - *(source0 + tSourceChannels * 2u)) * 2 - *(source0 + tSourceChannels) - *(source1 + tSourceChannels * 2u)) / 8);
588 ocean_assert((std::is_same<TTarget, int16_t>::value));
590 for (
unsigned int n = 0u; n < tSourceChannels; ++n)
595 *targetRow++ = TTarget(*(source1 + tSourceChannels * 2u) + *(source2 + tSourceChannels) + (*(source2 + tSourceChannels * 2u) - *(source0)) * 2 - *(source0 + tSourceChannels) - *(source1));
600 *targetRow++ = TTarget(*(source1) + *(source2 + tSourceChannels) + (*(source2) - *(source0 + tSourceChannels * 2u)) * 2 - *(source0 + tSourceChannels) - *(source1 + tSourceChannels * 2u));
610 for (
unsigned int n = 0u; n < tTargetChannels; ++n)
612 targetRow[n] = TTarget(0);
616 template <
typename TSource,
typename TTarget,
unsigned int tSourceChannels,
unsigned int tTargetChannels>
617 void FrameFilterSobel::filterRow(
const TSource* sourceRow, TTarget* targetRow,
const unsigned int width,
const unsigned int height,
unsigned int rowIndex,
const unsigned int sourceStrideElements,
const unsigned int )
619 static_assert(std::is_same<TSource, uint8_t>::value,
"Invalid source data type!");
620 static_assert(std::is_same<TTarget, int8_t>::value || std::is_same<TTarget, int16_t>::value,
"Invalid target data type!");
622 static_assert(tSourceChannels >= 1u,
"Invalid source channel number!");
623 static_assert(tTargetChannels == tSourceChannels * 4u,
"Invalid target channel number!");
625 ocean_assert(width >= 3u && height >= 3u);
627 if (rowIndex == 0u || rowIndex == height - 1u)
631 memset(targetRow, 0, width * tTargetChannels *
sizeof(TTarget));
635 const uint8_t* source0 = sourceRow - sourceStrideElements;
636 const uint8_t* source1 = sourceRow;
637 const uint8_t* source2 = sourceRow + sourceStrideElements;
641 for (
unsigned int n = 0u; n < tTargetChannels; ++n)
643 targetRow[n] = TTarget(0);
646 targetRow += tTargetChannels;
648 for (
unsigned int x = 1u; x < width - 1u; ++x)
650 if constexpr (std::is_same<TTarget, int8_t>::value)
652 for (
unsigned int n = 0u; n < tSourceChannels; ++n)
657 *targetRow++ = TTarget((*(source0 + tSourceChannels * 2u) - *(source0) + (*(source1 + tSourceChannels * 2u) - *(source1)) * 2 + *(source2 + tSourceChannels * 2u) - *(source2)) / 8);
662 *targetRow++ = TTarget((*(source2) + (*(source2 + tSourceChannels) - *(source0 + tSourceChannels)) * 2 + *(source2 + tSourceChannels * 2u) - *(source0) - *(source0 + tSourceChannels * 2u)) / 8);
667 *targetRow++ = TTarget((*(source1 + tSourceChannels * 2u) + *(source2 + tSourceChannels) + (*(source2 + tSourceChannels * 2u) - *(source0)) * 2 - *(source0 + tSourceChannels) - *(source1)) / 8);
672 *targetRow++ = TTarget((*(source1) + *(source2 + tSourceChannels) + (*(source2) - *(source0 + tSourceChannels * 2u)) * 2 - *(source0 + tSourceChannels) - *(source1 + tSourceChannels * 2u)) / 8);
681 ocean_assert((std::is_same<TTarget, int16_t>::value));
683 for (
unsigned int n = 0u; n < tSourceChannels; ++n)
688 *targetRow++ = TTarget(*(source0 + tSourceChannels * 2u) - *(source0) + (*(source1 + tSourceChannels * 2u) - *(source1)) * 2 + *(source2 + tSourceChannels * 2u) - *(source2));
693 *targetRow++ = TTarget(*(source2) + (*(source2 + tSourceChannels) - *(source0 + tSourceChannels)) * 2 + *(source2 + tSourceChannels * 2u) - *(source0) - *(source0 + tSourceChannels * 2u));
698 *targetRow++ = TTarget(*(source1 + tSourceChannels * 2u) + *(source2 + tSourceChannels) + (*(source2 + tSourceChannels * 2u) - *(source0)) * 2 - *(source0 + tSourceChannels) - *(source1));
703 *targetRow++ = TTarget(*(source1) + *(source2 + tSourceChannels) + (*(source2) - *(source0 + tSourceChannels * 2u)) * 2 - *(source0 + tSourceChannels) - *(source1 + tSourceChannels * 2u));
713 for (
unsigned int n = 0u; n < tTargetChannels; ++n)
715 targetRow[n] = TTarget(0);
719 template <
typename TSource,
typename TTarget,
unsigned int tSourceChannels,
unsigned int tTargetChannels>
722 static_assert(std::is_same<TSource, uint8_t>::value,
"Invalid source data type!");
723 static_assert(std::is_same<TTarget, uint8_t>::value || std::is_same<TTarget, uint16_t>::value,
"Invalid target data type!");
725 static_assert(tSourceChannels >= 1u,
"Invalid source channel number!");
726 static_assert(tTargetChannels == tSourceChannels,
"Invalid target channel number!");
728 ocean_assert(width >= 3u && height >= 3u);
730 if (rowIndex == 0u || rowIndex == height - 1u)
734 memset(targetRow, 0, width * tTargetChannels *
sizeof(TTarget));
738 const uint8_t* source0 = sourceRow - sourceStrideElements;
739 const uint8_t* source1 = sourceRow;
740 const uint8_t* source2 = sourceRow + sourceStrideElements;
744 for (
unsigned int n = 0u; n < tTargetChannels; ++n)
746 targetRow[n] = TTarget(0);
749 targetRow += tTargetChannels;
751 for (
unsigned int x = 1u; x < width - 1u; ++x)
753 if constexpr (std::is_same<TTarget, uint8_t>::value)
755 for (
unsigned int n = 0u; n < tSourceChannels; ++n)
760 *targetRow++ = TTarget((max(abs(*(source0 + tSourceChannels * 2u) - *(source0) + (*(source1 + tSourceChannels * 2u) - *(source1)) * 2 + *(source2 + tSourceChannels * 2u) - *(source2)),
765 abs(*(source2) + (*(source2 + tSourceChannels) - *(source0 + tSourceChannels)) * 2 + *(source2 + tSourceChannels * 2u) - *(source0) - *(source0 + tSourceChannels * 2u))) + 2u) / 4u);
774 ocean_assert((std::is_same<TTarget, uint16_t>::value));
776 for (
unsigned int n = 0u; n < tSourceChannels; ++n)
781 *targetRow++ = TTarget(max(abs(*(source0 + tSourceChannels * 2u) - *(source0) + (*(source1 + tSourceChannels * 2u) - *(source1)) * 2 + *(source2 + tSourceChannels * 2u) - *(source2)),
786 abs(*(source2) + (*(source2 + tSourceChannels) - *(source0 + tSourceChannels)) * 2 + *(source2 + tSourceChannels * 2u) - *(source0) - *(source0 + tSourceChannels * 2u))));
796 for (
unsigned int n = 0u; n < tTargetChannels; ++n)
798 targetRow[n] = TTarget(0);
802 template <
typename TTarget,
unsigned int tSourceChannels>
805 static_assert(std::is_same<TTarget, int8_t>::value || std::is_same<TTarget, int16_t>::value,
"Invalid target data type!");
806 static_assert(tSourceChannels >= 1u,
"Invalid channel number!");
808 ocean_assert(source !=
nullptr && response !=
nullptr);
809 ocean_assert(x < width && y < height);
810 ocean_assert(width >= 3u && height >= 3u);
812 ocean_assert((x - 1u < width - 2u && y - 1u < height - 2u) == (x >= 1u && y >= 1u && x + 1u < width && y + 1u < height));
814 if (x - 1u < width - 2u && y - 1u < height - 2u)
816 const unsigned int sourceStrideElements = width * tSourceChannels + sourcePaddingElements;
818 filterPixelCoreHorizontalVertical8BitPerChannel<TTarget, tSourceChannels>(source + y * sourceStrideElements + x * tSourceChannels, width, response, sourcePaddingElements);
822 for (
unsigned int n = 0u; n < tSourceChannels * 2u; ++n)
824 response[n] = TTarget(0);
829 template <
typename TTarget,
unsigned int tSourceChannels>
832 static_assert(std::is_same<TTarget, int8_t>::value || std::is_same<TTarget, int16_t>::value,
"Invalid target data type!");
833 static_assert(tSourceChannels >= 1u,
"Invalid channel number!");
835 ocean_assert(source !=
nullptr && response !=
nullptr);
836 ocean_assert(width >= 3u);
838 const unsigned int sourceStrideElements = width * tSourceChannels + sourcePaddingElements;
840 if constexpr (std::is_same<TTarget, int8_t>::value)
842 for (
unsigned int n = 0u; n < tSourceChannels; ++n)
847 *response++ = TTarget((*(source - sourceStrideElements + tSourceChannels) - *(source - sourceStrideElements - tSourceChannels) + (*(source + tSourceChannels) - *(source - tSourceChannels)) * 2 + *(source + sourceStrideElements + tSourceChannels) - *(source + sourceStrideElements - tSourceChannels)) / 8);
852 *response++ = TTarget((*(source + sourceStrideElements - tSourceChannels) + (*(source + sourceStrideElements) - *(source - sourceStrideElements)) * 2 + *(source + sourceStrideElements + tSourceChannels) - *(source - sourceStrideElements - tSourceChannels) - *(source - sourceStrideElements + tSourceChannels)) / 8);
859 ocean_assert((std::is_same<TTarget, int16_t>::value));
861 for (
unsigned int n = 0u; n < tSourceChannels; ++n)
866 *response++ = TTarget(*(source - sourceStrideElements + tSourceChannels) - *(source - sourceStrideElements - tSourceChannels) + (*(source + tSourceChannels) - *(source - tSourceChannels)) * 2 + *(source + sourceStrideElements + tSourceChannels) - *(source + sourceStrideElements - tSourceChannels));
871 *response++ = TTarget(*(source + sourceStrideElements - tSourceChannels) + (*(source + sourceStrideElements) - *(source - sourceStrideElements)) * 2 + *(source + sourceStrideElements + tSourceChannels) - *(source - sourceStrideElements - tSourceChannels) - *(source - sourceStrideElements + tSourceChannels));
878 template <
typename TTarget, TTarget tNormalizationDenominator,
bool tRoundedNormalization>
881 static_assert(tNormalizationDenominator == 1 || tNormalizationDenominator == 4 || tNormalizationDenominator == 8,
"Invalid normalization factor!");
883 ocean_assert(source !=
nullptr && responses !=
nullptr);
884 ocean_assert(width >= 3u);
886 const unsigned int strideElements = width + paddingElements;
891 const TTarget horizontal = TTarget(FrameFilter::normalizeValue<int32_t, tNormalizationDenominator, tRoundedNormalization>(*(source - strideElements + 1u) - *(source - strideElements - 1u) + (*(source + 1u) - *(source - 1u)) * 2 + *(source + strideElements + 1u) - *(source + strideElements - 1u)));
896 const TTarget vertical = TTarget(FrameFilter::normalizeValue<int32_t, tNormalizationDenominator, tRoundedNormalization>(*(source + strideElements - 1u) + (*(source + strideElements) - *(source - strideElements)) * 2 + *(source + strideElements + 1u) - *(source - strideElements - 1u) - *(source - strideElements + 1u)));
898 *responses++ = horizontal * horizontal;
899 *responses++ = vertical * vertical;
900 *responses = horizontal * vertical;
903 template <
typename TTarget,
unsigned int tChannels,
bool tIsCorePixel>
906 static_assert(std::is_same<TTarget, uint8_t>::value || std::is_same<TTarget, uint16_t>::value,
"Invalid target data type!");
907 static_assert(tChannels >= 1u,
"Invalid channel number!");
909 ocean_assert(source !=
nullptr && response !=
nullptr);
911 ocean_assert((x >= 1u && x < width - 1u && y >= 1u && y < height - 1u) == (x - 1u < width - 2u && y - 1u < height - 2u));
913 if (tIsCorePixel || (x - 1u < width - 2u && y - 1u < height - 2u))
915 const unsigned int sourceStrideElements = width * tChannels + sourcePaddingElements;
917 const uint8_t* source0 = source + (y - 1u) * sourceStrideElements + x * tChannels;
918 const uint8_t* source1 = source + (y + 0u) * sourceStrideElements + x * tChannels;
919 const uint8_t* source2 = source + (y + 1u) * sourceStrideElements + x * tChannels;
921 if (std::is_same<TTarget, uint8_t>::value)
923 for (
unsigned int n = 0u; n < tChannels; ++n)
928 response[n] = TTarget((max(abs(*(source0 + tChannels) - *(source0 - tChannels) + (*(source1 + tChannels) - *(source1 - tChannels)) * 2 + *(source2 + tChannels) - *(source2 - tChannels)),
933 abs(*(source2 - tChannels) + (*(source2) - *(source0)) * 2 + *(source2 + tChannels) - *(source0 - tChannels) - *(source0 + tChannels))) + 2u) / 4u);
942 ocean_assert((std::is_same<TTarget, uint16_t>::value));
944 for (
unsigned int n = 0u; n < tChannels; ++n)
949 response[n] = TTarget(max(abs(*(source0 + tChannels) - *(source0 - tChannels) + (*(source1 + tChannels) - *(source1 - tChannels)) * 2 + *(source2 + tChannels) - *(source2 - tChannels)),
954 abs(*(source2 - tChannels) + (*(source2) - *(source0)) * 2 + *(source2 + tChannels) - *(source0 - tChannels) - *(source0 + tChannels))));
964 for (
unsigned int n = 0u; n < tChannels; ++n)
966 response[n] = TTarget(0);
971 #if defined(OCEAN_HARDWARE_SSE_VERSION) && OCEAN_HARDWARE_SSE_VERSION >= 41
975 ocean_assert(source0 && source1 && source2);
978 const __m128i row0 = _mm_lddqu_si128((__m128i*)source0);
979 const __m128i row1 = _mm_lddqu_si128((__m128i*)source1);
980 const __m128i row2 = _mm_lddqu_si128((__m128i*)source2);
986 const __m128i row0_low = _mm_unpacklo_epi8(row0, _mm_set1_epi8(0u));
987 const __m128i row0_high = _mm_unpackhi_epi8(row0, _mm_set1_epi8(0u));
988 const __m128i row1_low = _mm_unpacklo_epi8(row1, _mm_set1_epi8(0u));
989 const __m128i row1_high = _mm_unpackhi_epi8(row1, _mm_set1_epi8(0u));
990 const __m128i row2_low = _mm_unpacklo_epi8(row2, _mm_set1_epi8(0u));
991 const __m128i row2_high = _mm_unpackhi_epi8(row2, _mm_set1_epi8(0u));
994 const __m128i row0_x2_high = _mm_slli_epi16(row0_high, 1);
995 const __m128i row1_x2_high = _mm_slli_epi16(row1_high, 1);
996 const __m128i row2_x2_high = _mm_slli_epi16(row2_high, 1);
997 const __m128i row0_x2_low = _mm_slli_epi16(row0_low, 1);
998 const __m128i row1_x2_low = _mm_slli_epi16(row1_low, 1);
999 const __m128i row2_x2_low = _mm_slli_epi16(row2_low, 1);
1007 const __m128i diff_row02_high = _mm_sub_epi16(row2_high, row0_high);
1008 const __m128i diff_row02_low = _mm_sub_epi16(row2_low, row0_low);
1010 const __m128i diff_row02_x2_high = _mm_sub_epi16(row2_x2_high, row0_x2_high);
1011 const __m128i diff_row02_x2_low = _mm_sub_epi16(row2_x2_low, row0_x2_low);
1016 const __m128i row02_sum_1 = _mm_add_epi16(diff_row02_low, _mm_or_si128(_mm_srli_si128(diff_row02_low, 4u), _mm_slli_si128(diff_row02_high, 12u)));
1019 const __m128i row02_sum_2 = _mm_add_epi16(diff_row02_high, _mm_srli_si128(diff_row02_high, 4u));
1022 response_y_low = _mm_adds_epi16(row02_sum_1, _mm_or_si128(_mm_srli_si128(diff_row02_x2_low, 2u), _mm_slli_si128(diff_row02_x2_high, 14u)));
1024 response_y_high = _mm_adds_epi16(row02_sum_2, _mm_srli_si128(diff_row02_x2_high, 2u));
1036 const __m128i row0_low_shifted = _mm_or_si128(_mm_srli_si128(row0_low, 4u), _mm_slli_si128(row0_high, 12u));
1039 const __m128i row1_x2_low_shifted = _mm_or_si128(_mm_srli_si128(row1_x2_low, 4u), _mm_slli_si128(row1_x2_high, 12u));
1042 const __m128i row2_low_shifted = _mm_or_si128(_mm_srli_si128(row2_low, 4u), _mm_slli_si128(row2_high, 12u));
1047 const __m128i diff_cols_r0_low = _mm_sub_epi16(row0_low_shifted, row0_low);
1048 const __m128i diff_cols_r0_high = _mm_sub_epi16(_mm_srli_si128(row0_high, 4u), row0_high);
1049 const __m128i diff_cols_r2_low = _mm_sub_epi16(row2_low_shifted, row2_low);
1050 const __m128i diff_cols_r2_high = _mm_sub_epi16(_mm_srli_si128(row2_high, 4u), row2_high);
1051 const __m128i diff_cols_r1_x2_low = _mm_sub_epi16(row1_x2_low_shifted, row1_x2_low);
1052 const __m128i diff_cols_r1_x2_high = _mm_sub_epi16(_mm_srli_si128(row1_x2_high, 4u), row1_x2_high);
1055 response_x_low = _mm_adds_epi16(_mm_adds_epi16(diff_cols_r0_low, diff_cols_r2_low), diff_cols_r1_x2_low);
1056 response_x_high = _mm_adds_epi16(_mm_adds_epi16(diff_cols_r0_high, diff_cols_r2_high), diff_cols_r1_x2_high);
1065 ocean_assert(source !=
nullptr && response !=
nullptr);
1066 ocean_assert(strideElements >= 16u);
1068 __m128i response_y_low;
1069 __m128i response_y_high;
1070 __m128i response_x_low;
1071 __m128i response_x_high;
1082 const __m128i response_x_norm = _mm_packs_epi16(response_x_low_norm, response_x_high_norm);
1083 const __m128i response_y_norm = _mm_packs_epi16(response_y_low_norm, response_y_high_norm);
1086 const __m128i response_zipped_lo = _mm_unpacklo_epi8(response_x_norm, response_y_norm);
1087 const __m128i response_zipped_hi = _mm_unpackhi_epi8(response_x_norm, response_y_norm);
1089 _mm_storeu_si128((__m128i*)response, response_zipped_lo);
1090 memcpy(response + 16, &response_zipped_hi, 12);
1095 ocean_assert(source !=
nullptr && response !=
nullptr);
1096 ocean_assert(strideElements >= 16u);
1098 __m128i response_y_low;
1099 __m128i response_y_high;
1100 __m128i response_x_low;
1101 __m128i response_x_high;
1106 const __m128i response_zipped_lo = _mm_unpacklo_epi16(response_x_low, response_y_low);
1107 const __m128i response_zipped_hi = _mm_unpackhi_epi16(response_x_low, response_y_low);
1108 const __m128i response_zipped_lo_2 = _mm_unpacklo_epi16(response_x_high, response_y_high);
1109 const __m128i response_zipped_hi_2 = _mm_unpackhi_epi16(response_x_high, response_y_high);
1112 memcpy(response, &response_zipped_lo, 16);
1113 memcpy(response + 8, &response_zipped_hi, 16);
1114 memcpy(response + 16, &response_zipped_lo_2, 16);
1115 memcpy(response + 24, &response_zipped_hi_2, 8);
This class implements the base class for all filter.
Definition: FrameFilter.h:29
The following comfort class provides comfortable functions simplifying prototyping applications but a...
Definition: FrameFilterSobel.h:57
static Frame filterHorizontalVertical(const Frame &frame, const FrameType::DataType responseDataType=FrameType::DT_SIGNED_INTEGER_8, Worker *worker=nullptr)
Horizontal and vertical Sobel filter for images.
static Frame filter(const Frame &frame, const FrameType::DataType responseDataType=FrameType::DT_SIGNED_INTEGER_8, Worker *worker=nullptr)
Horizontal, vertical, and diagonal Sobel filter for images.
This class implements a Sobel filter.
Definition: FrameFilterSobel.h:48
static void filterHorizontalVertical8BitPerChannel(const uint8_t *source, TTarget *target, const unsigned int width, const unsigned int height, const unsigned int sourcePaddingElements, const unsigned int targetPaddingElements, Worker *worker=nullptr)
Horizontal and vertical Sobel filter for images.
Definition: FrameFilterSobel.h:348
static void filterHorizontalVerticalMaximumAbsoluteRow(const TSource *sourceRow, TTarget *targetRow, const unsigned int width, const unsigned int height, unsigned int rowIndex, const unsigned int sourceStrideElements, const unsigned int targetStrideElements)
Applies the maximum of the absolute horizontal and vertical Sobel filter to one row of a source frame...
Definition: FrameFilterSobel.h:720
static void filterPixelCoreHorizontalVertical8BitPerChannel(const uint8_t *source, const unsigned int width, TTarget *response, const unsigned int sourcePaddingElements)
Horizontal and vertical Sobel filter for a pixel not at the boundary of the frame (in the inner core ...
Definition: FrameFilterSobel.h:830
static void filterPixelCoreHorizontalVertical3Squared1Channel8Bit(const uint8_t *source, const unsigned int width, TTarget *responses, const unsigned int paddingElements)
Determines the squared Sobel filter responses (three products) for a 1 channel 8 bit pixel based on a...
Definition: FrameFilterSobel.h:879
static void filterPixelHorizontalVertical8BitPerChannel(const uint8_t *source, const unsigned int width, const unsigned int height, const unsigned int x, const unsigned int y, TTarget *response, const unsigned int sourcePaddingElements)
Horizontal and vertical Sobel filter for a pixel.
Definition: FrameFilterSobel.h:803
static void filterHorizontalVertical1Channel8BitBlock14SSE(const uint8_t *source, const unsigned int strideElements, int16_t *response)
SSE block based horizontal and vertical Sobel filter for 1 channel 8 bit frame.
Definition: FrameFilterSobel.h:1093
static void filter8BitPerChannel(const uint8_t *source, TTarget *target, const unsigned int width, const unsigned int height, const unsigned int sourcePaddingElements, const unsigned int targetPaddingElements, Worker *worker=nullptr)
Horizontal, vertical, and diagonal Sobel filter for images.
Definition: FrameFilterSobel.h:378
static void filterHorizontalVerticalRow(const TSource *sourceRow, TTarget *targetRow, const unsigned int width, const unsigned int height, unsigned int rowIndex, const unsigned int sourceStrideElements, const unsigned int targetStrideElements)
Applies the horizontal and vertical Sobel filter to one row of a source frame.
Definition: FrameFilterSobel.h:408
static void filterHorizontalVerticalMaximumAbsolute8BitPerChannel(const uint8_t *source, TTarget *target, const unsigned int width, const unsigned int height, const unsigned int sourcePaddingElements, const unsigned int targetPaddingElements, Worker *worker=nullptr)
Determines the maximum of the absolute horizontal and vertical Sobel filter.
Definition: FrameFilterSobel.h:393
static void filterDiagonalRow(const TSource *sourceRow, TTarget *targetRow, const unsigned int width, const unsigned int height, unsigned int rowIndex, const unsigned int sourceStrideElements, const unsigned int targetStrideElements)
Applies the diagonal (45 and 135 degree) Sobel filter to one row of a source frame.
Definition: FrameFilterSobel.h:534
static void filterPixelHorizontalVerticalMaximum8BitPerChannel(const uint8_t *const source, const unsigned int width, const unsigned int height, const unsigned int x, const unsigned int y, TTarget *const response, unsigned int sourcePaddingElements)
Determines the maximum of the absolute horizontal and vertical Sobel filter for a given pixel.
Definition: FrameFilterSobel.h:904
static void filterHorizontalVertical3Squared1Channel8BitRow(const uint8_t *row, const unsigned int width, const unsigned int elements, const unsigned int paddingElements, int16_t *responsesXX, int16_t *responsesYY, int16_t *responsesXY)
Determines the squared Sobel filter responses (three products) for a 1 channel 8 bit row based on a h...
static void filterHorizontalVertical8BitBlock14SSE(const uint8_t *source0, const uint8_t *source1, const uint8_t *source2, __m128i &response_x_low, __m128i &response_x_high, __m128i &response_y_low, __m128i &response_y_high)
Block based SSE implementation of horizontal and vertical Sobel filter for 8 bit pixel.
Definition: FrameFilterSobel.h:973
static void filterDiagonal8BitPerChannel(const uint8_t *source, TTarget *target, const unsigned int width, const unsigned int height, const unsigned int sourcePaddingElements, const unsigned int targetPaddingElements, Worker *worker=nullptr)
Diagonal 45 and 135 degree Sobel filter for images.
Definition: FrameFilterSobel.h:363
static void filterRow(const TSource *sourceRow, TTarget *targetRow, const unsigned int width, const unsigned int height, unsigned int rowIndex, const unsigned int sourceStrideElements, const unsigned int targetStrideElements)
Applies the horizontal, vertical, and diagonal Sobel filter to one row of a source frame.
Definition: FrameFilterSobel.h:617
static __m128i divideByRightShiftSigned16Bit(const __m128i &value, const unsigned int rightShifts)
Divides eight signed 16 bit values by applying a right shift.
Definition: SSE.h:3066
This class implements Ocean's image class.
Definition: Frame.h:1792
DataType
Definition of individual channel data type.
Definition: Frame.h:37
@ DT_SIGNED_INTEGER_8
Signed 8 bit integer data type (int8_t).
Definition: Frame.h:43
This class implements a worker able to distribute function calls over different threads.
Definition: Worker.h:33
The namespace covering the entire Ocean framework.
Definition: Accessor.h:15