diff --git a/docs/2026.html b/docs/2026.html index 5916a8cb52..c07ca3e5ef 100644 --- a/docs/2026.html +++ b/docs/2026.html @@ -60,6 +60,8 @@
Removing
  • Function SimdFill.
  • Function SimdFillBgr.
  • Function SimdFillBgra.
  • +
  • Function SimdHogDirectionHistograms.
  • +
  • C++ wrapper Simd::HogDirectionHistograms.
  • Python wrapper

    @@ -90,6 +92,7 @@
    Removing
  • Tests for verifying functionality of function Fill.
  • Tests for verifying functionality of function FillBgr.
  • Tests for verifying functionality of function FillBgra.
  • +
  • Tests for verifying functionality of function HogDirectionHistograms.
  • Documentation

    diff --git a/src/Simd/SimdAvx2.h b/src/Simd/SimdAvx2.h index 9f50675ab3..923476f3c0 100644 --- a/src/Simd/SimdAvx2.h +++ b/src/Simd/SimdAvx2.h @@ -267,9 +267,6 @@ namespace Simd void AbsSecondDerivativeHistogram(const uint8_t *src, size_t width, size_t height, size_t stride, size_t step, size_t indent, uint32_t * histogram); - void HogDirectionHistograms(const uint8_t * src, size_t stride, size_t width, size_t height, - size_t cellX, size_t cellY, size_t quantization, float * histograms); - void HogExtractFeatures(const uint8_t * src, size_t stride, size_t width, size_t height, float * features); void HogDeinterleave(const float * src, size_t srcStride, size_t width, size_t height, size_t count, float ** dst, size_t dstStride); diff --git a/src/Simd/SimdAvx2Hog.cpp b/src/Simd/SimdAvx2Hog.cpp index 550acfeace..5474d0d966 100644 --- a/src/Simd/SimdAvx2Hog.cpp +++ b/src/Simd/SimdAvx2Hog.cpp @@ -22,7 +22,6 @@ * SOFTWARE. */ #include "Simd/SimdStore.h" -#include "Simd/SimdBase.h" #include "Simd/SimdArray.h" #include "Simd/SimdUnpack.h" @@ -31,377 +30,6 @@ namespace Simd #ifdef SIMD_AVX2_ENABLE namespace Avx2 { - namespace - { - struct Buffer - { - const int size; - __m256 * cos, *sin; - __m256i * pos, *neg; - int * index; - float * value; - - Buffer(size_t width, size_t quantization) - : size((int)quantization / 2) - { - width = AlignHi(width, A / sizeof(float)); - _p = Allocate(width*(sizeof(int) + sizeof(float)) + (sizeof(__m256i) + sizeof(__m256)) * 2 * size); - index = (int*)_p - 1; - value = (float*)index + width; - cos = (__m256*)(value + width + 1); - sin = cos + size; - pos = (__m256i*)(sin + size); - neg = pos + size; - for (int i = 0; i < size; ++i) - { - cos[i] = _mm256_set1_ps((float)::cos(i*M_PI / size)); - sin[i] = _mm256_set1_ps((float)::sin(i*M_PI / size)); - pos[i] = _mm256_set1_epi32(i); - neg[i] = _mm256_set1_epi32(size + i); - } - } - - ~Buffer() - { - Free(_p); - } - - private: - void *_p; - }; - } - - template SIMD_INLINE void HogDirectionHistograms(const __m256 & dx, const __m256 & dy, Buffer & buffer, size_t col) - { - __m256 bestDot = _mm256_setzero_ps(); - __m256i bestIndex = _mm256_setzero_si256(); - for (int i = 0; i < buffer.size; ++i) - { - __m256 dot = _mm256_fmadd_ps(dx, buffer.cos[i], _mm256_mul_ps(dy, buffer.sin[i])); - __m256 mask = _mm256_cmp_ps(dot, bestDot, _CMP_GT_OS); - bestDot = _mm256_max_ps(dot, bestDot); - bestIndex = _mm256_blendv_epi8(bestIndex, buffer.pos[i], _mm256_castps_si256(mask)); - - dot = _mm256_sub_ps(_mm256_setzero_ps(), dot); - mask = _mm256_cmp_ps(dot, bestDot, _CMP_GT_OS); - bestDot = _mm256_max_ps(dot, bestDot); - bestIndex = _mm256_blendv_epi8(bestIndex, buffer.neg[i], _mm256_castps_si256(mask)); - } - Store((__m256i*)(buffer.index + col), bestIndex); - Store(buffer.value + col, Sqrt<0>(_mm256_fmadd_ps(dx, dx, _mm256_mul_ps(dy, dy)))); - } - - template SIMD_INLINE void HogDirectionHistograms(const __m256i & t, const __m256i & l, const __m256i & r, const __m256i & b, Buffer & buffer, size_t col) - { - HogDirectionHistograms( - _mm256_cvtepi32_ps(_mm256_sub_epi32(_mm256_unpacklo_epi16(r, K_ZERO), _mm256_unpacklo_epi16(l, K_ZERO))), - _mm256_cvtepi32_ps(_mm256_sub_epi32(_mm256_unpacklo_epi16(b, K_ZERO), _mm256_unpacklo_epi16(t, K_ZERO))), - buffer, col + 0); - HogDirectionHistograms( - _mm256_cvtepi32_ps(_mm256_sub_epi32(_mm256_unpackhi_epi16(r, K_ZERO), _mm256_unpackhi_epi16(l, K_ZERO))), - _mm256_cvtepi32_ps(_mm256_sub_epi32(_mm256_unpackhi_epi16(b, K_ZERO), _mm256_unpackhi_epi16(t, K_ZERO))), - buffer, col + 8); - } - - template SIMD_INLINE void HogDirectionHistograms(const uint8_t * src, size_t stride, Buffer & buffer, size_t col) - { - const uint8_t * s = src + col; - __m256i t = LoadPermuted((__m256i*)(s - stride)); - __m256i l = LoadPermuted((__m256i*)(s - 1)); - __m256i r = LoadPermuted((__m256i*)(s + 1)); - __m256i b = LoadPermuted((__m256i*)(s + stride)); - HogDirectionHistograms(PermutedUnpackLoU8(t), PermutedUnpackLoU8(l), PermutedUnpackLoU8(r), PermutedUnpackLoU8(b), buffer, col + 0); - HogDirectionHistograms(PermutedUnpackHiU8(t), PermutedUnpackHiU8(l), PermutedUnpackHiU8(r), PermutedUnpackHiU8(b), buffer, col + 16); - } - - namespace Custom_8x8_18 - { - struct Buffer - { - __m256i pos[5]; - __m256 cos[5], sin[5]; - __m128 kx[8], ky[8]; - - int * index; - float * value; - __m128 * hist; - size_t hs; - - Buffer(size_t width) - { - width = AlignHi(width, A / sizeof(float)); - hs = (width / 8 + 1) * 18 * sizeof(__m128); - _p = Allocate(width*(sizeof(int) + sizeof(float)) + hs); - index = (int*)_p - 1; - value = (float*)index + width; - hist = (__m128*)(value + width + 1); - - for (int i = 0; i < 5; ++i) - { - cos[i] = _mm256_set1_ps((float)::cos(i*M_PI / 9)); - sin[i] = _mm256_set1_ps((float)::sin(i*M_PI / 9)); - pos[i] = _mm256_set1_epi32(i); - } - for (int i = 0; i < 8; ++i) - { - float k0 = float((15 - i * 2) / 16.0f); - float k1 = 1.0f - k0; - kx[i] = _mm_setr_ps(k0, k1, k0, k1); - ky[i] = _mm_setr_ps(k0, k0, k1, k1); - } - ClearHist(); - } - - ~Buffer() - { - Free(_p); - } - - void ClearHist() - { - memset(hist, 0, hs); - } - - private: - void *_p; - }; - - const __m256i K32_1 = SIMD_MM256_SET1_EPI32(1); - const __m256i K32_9 = SIMD_MM256_SET1_EPI32(9); - const __m256i K32_18 = SIMD_MM256_SET1_EPI32(18); - - template SIMD_INLINE void HogDirectionHistograms(const __m256 & dx, const __m256 & dy, Buffer & buffer, size_t col) - { - __m256 _0 = _mm256_set1_ps(-0.0f); - __m256 adx = _mm256_andnot_ps(_0, dx); - __m256 ady = _mm256_andnot_ps(_0, dy); - __m256 bestDot = _mm256_fmadd_ps(adx, buffer.cos[0], _mm256_mul_ps(ady, buffer.sin[0])); - __m256i bestIndex = buffer.pos[0]; - for (int i = 1; i < 5; ++i) - { - __m256 dot = _mm256_fmadd_ps(adx, buffer.cos[i], _mm256_mul_ps(ady, buffer.sin[i])); - __m256 mask = _mm256_cmp_ps(dot, bestDot, _CMP_GT_OS); - bestDot = _mm256_max_ps(dot, bestDot); - bestIndex = _mm256_blendv_epi8(bestIndex, buffer.pos[i], _mm256_castps_si256(mask)); - } - __m256i maskDx = _mm256_castps_si256(_mm256_cmp_ps(dx, _mm256_setzero_ps(), _CMP_LT_OS)); - bestIndex = _mm256_blendv_epi8(bestIndex, _mm256_sub_epi32(K32_9, bestIndex), maskDx); - - __m256i maskDy = _mm256_castps_si256(_mm256_cmp_ps(dy, _mm256_setzero_ps(), _CMP_LT_OS)); - __m256i corr = _mm256_and_si256(_mm256_castps_si256(_mm256_cmp_ps(adx, _mm256_setzero_ps(), _CMP_EQ_OS)), K32_1); - bestIndex = _mm256_blendv_epi8(bestIndex, _mm256_sub_epi32(K32_18, _mm256_add_epi32(bestIndex, corr)), maskDy); - - bestIndex = _mm256_andnot_si256(_mm256_cmpeq_epi32(bestIndex, K32_18), bestIndex); - - Store((__m256i*)(buffer.index + col), bestIndex); - Store(buffer.value + col, Sqrt<0>(_mm256_fmadd_ps(adx, adx, _mm256_mul_ps(ady, ady)))); - } - - template SIMD_INLINE __m256 CovertDifference(const __m128i & a, const __m128i & b) - { - return _mm256_cvtepi32_ps(_mm256_cvtepi16_epi32(Sse41::SubUnpackedU8(a, b))); - } - - template SIMD_INLINE void HogDirectionHistograms(const uint8_t * src, size_t stride, Buffer & buffer, size_t col) - { - const uint8_t * s = src + col; - __m128i t = Sse41::Load((__m128i*)(s - stride)); - __m128i l = Sse41::Load((__m128i*)(s - 1)); - __m128i r = Sse41::Load((__m128i*)(s + 1)); - __m128i b = Sse41::Load((__m128i*)(s + stride)); - HogDirectionHistograms(CovertDifference<0>(r, l), CovertDifference<0>(b, t), buffer, col + 0); - HogDirectionHistograms(CovertDifference<1>(r, l), CovertDifference<1>(b, t), buffer, col + 8); - } - - void AddRowToBuffer(const uint8_t * src, size_t stride, Buffer & buffer, size_t row, size_t width, size_t aligned) - { - const uint8_t * s = src + stride * row; - for (size_t col = 1; col < aligned; col += HA) - HogDirectionHistograms(s, stride, buffer, col); - HogDirectionHistograms(s, stride, buffer, width - 1 - HA); - - __m128 ky = buffer.ky[(row + 4) & 7]; - __m128 * hist = buffer.hist; - size_t cellEnd = width / 8; - - for (size_t col = 1; col < 4; ++col) - { - int index = buffer.index[col]; - __m128 value = _mm_set1_ps(buffer.value[col]); - __m128 kx = buffer.kx[(col + 4) & 7]; - hist[index] = _mm_fmadd_ps(_mm_mul_ps(ky, kx), value, hist[index]); - } - hist += 18; - - for (size_t cell = 1, col = 4; cell < cellEnd; ++cell) - { - for (size_t i = 0; i < 8; ++i, ++col) - { - int index = buffer.index[col]; - __m128 value = _mm_set1_ps(buffer.value[col]); - __m128 kx = buffer.kx[i]; - hist[index] = _mm_fmadd_ps(_mm_mul_ps(ky, kx), value, hist[index]); - } - hist += 18; - } - - for (size_t col = width - 4; col < width - 1; ++col) - { - int index = buffer.index[col]; - __m128 value = _mm_set1_ps(buffer.value[col]); - __m128 kx = buffer.kx[(col + 4) & 7]; - hist[index] = _mm_fmadd_ps(_mm_mul_ps(ky, kx), value, hist[index]); - } - } - - void AddToHistogram(Buffer & buffer, size_t row, size_t width, size_t height, float * histograms) - { - typedef float f18_t[18]; - - float * src = (float*)buffer.hist; - f18_t * h0 = (f18_t*)histograms + row * width - width - 1; - f18_t * h1 = h0 + width; - - if (row == 0) - { - for (size_t i = 0; i < 18; ++i) - h1[1][i] += src[i * 4 + 3]; - h1++; - src += 72; - for (size_t cell = 1; cell < width; ++cell) - { - for (size_t i = 0; i < 18; ++i) - { - h1[0][i] += src[i * 4 + 2]; - h1[1][i] += src[i * 4 + 3]; - } - h1++; - src += 72; - } - for (size_t i = 0; i < 18; ++i) - h1[0][i] += src[i * 4 + 2]; - } - else if (row == height) - { - for (size_t i = 0; i < 18; ++i) - h0[1][i] += src[i * 4 + 1]; - h0++; - src += 72; - for (size_t cell = 1; cell < width; ++cell) - { - for (size_t i = 0; i < 18; ++i) - { - h0[0][i] += src[i * 4 + 0]; - h0[1][i] += src[i * 4 + 1]; - } - h0++; - src += 72; - } - for (size_t i = 0; i < 18; ++i) - h0[0][i] += src[i * 4 + 0]; - } - else - { - for (size_t i = 0; i < 18; ++i) - { - h0[1][i] += src[i * 4 + 1]; - h1[1][i] += src[i * 4 + 3]; - } - h0++; - h1++; - src += 72; - for (size_t cell = 1; cell < width; ++cell) - { - for (size_t i = 0; i < 16; i += F) - { - const float * s = src + i * 4; - __m256 a0 = Load(s + 0x00, s + 0x10); - __m256 a1 = Load(s + 0x04, s + 0x14); - __m256 a2 = Load(s + 0x08, s + 0x18); - __m256 a3 = Load(s + 0x0C, s + 0x1C); - __m256 b0 = _mm256_unpacklo_ps(a0, a2); - __m256 b1 = _mm256_unpackhi_ps(a0, a2); - __m256 b2 = _mm256_unpacklo_ps(a1, a3); - __m256 b3 = _mm256_unpackhi_ps(a1, a3); - Store(h0[0] + i, _mm256_add_ps(Load(h0[0] + i), _mm256_unpacklo_ps(b0, b2))); - Store(h0[1] + i, _mm256_add_ps(Load(h0[1] + i), _mm256_unpackhi_ps(b0, b2))); - Store(h1[0] + i, _mm256_add_ps(Load(h1[0] + i), _mm256_unpacklo_ps(b1, b3))); - Store(h1[1] + i, _mm256_add_ps(Load(h1[1] + i), _mm256_unpackhi_ps(b1, b3))); - } - for (size_t i = 16; i < 18; ++i) - { - h0[0][i] += src[i * 4 + 0]; - h0[1][i] += src[i * 4 + 1]; - h1[0][i] += src[i * 4 + 2]; - h1[1][i] += src[i * 4 + 3]; - } - h0++; - h1++; - src += 72; - } - for (size_t i = 0; i < 18; ++i) - { - h0[0][i] += src[i * 4 + 0]; - h1[0][i] += src[i * 4 + 2]; - } - } - buffer.ClearHist(); - } - - void HogDirectionHistograms(const uint8_t * src, size_t stride, size_t width, size_t height, float * histograms) - { - const size_t quantization = 18; - - size_t sizeX = width / 8, sizeY = height / 8; - - memset(histograms, 0, quantization*sizeX*sizeY * sizeof(float)); - - Buffer buffer(width); - - size_t aligned = AlignLo(width - 2, HA) + 1; - - for (size_t row = 1; row < 4; ++row) - AddRowToBuffer(src, stride, buffer, row, width, aligned); - AddToHistogram(buffer, 0, sizeX, sizeY, histograms); - for (size_t row = 4, cell = 1; row < height - 4; ++row) - { - AddRowToBuffer(src, stride, buffer, row, width, aligned); - if ((row & 7) == 3) - AddToHistogram(buffer, cell++, sizeX, sizeY, histograms); - } - for (size_t row = height - 4; row < height - 1; ++row) - AddRowToBuffer(src, stride, buffer, row, width, aligned); - AddToHistogram(buffer, sizeY, sizeX, sizeY, histograms); - } - } - - void HogDirectionHistograms(const uint8_t * src, size_t stride, size_t width, size_t height, - size_t cellX, size_t cellY, size_t quantization, float * histograms) - { - assert(width%cellX == 0 && height%cellY == 0 && quantization % 2 == 0); - assert(width >= A + 2); - - if (cellX == 8 && cellY == 8 && quantization == 18) - Custom_8x8_18::HogDirectionHistograms(src, stride, width, height, histograms); - else - { - memset(histograms, 0, quantization*(width / cellX)*(height / cellY) * sizeof(float)); - - Buffer buffer(width, quantization); - - size_t alignedWidth = AlignLo(width - 2, A) + 1; - - for (size_t row = 1; row < height - 1; ++row) - { - const uint8_t * s = src + stride * row; - for (size_t col = 1; col < alignedWidth; col += A) - HogDirectionHistograms(s, stride, buffer, col); - HogDirectionHistograms(s, stride, buffer, width - 1 - A); - Base::AddRowToHistograms(buffer.index, buffer.value, row, width, height, cellX, cellY, quantization, histograms); - } - } - } - class HogFeatureExtractor { static const size_t C = 8; diff --git a/src/Simd/SimdAvx512bw.h b/src/Simd/SimdAvx512bw.h index 1d1b18aaa0..6eb9e57ce0 100644 --- a/src/Simd/SimdAvx512bw.h +++ b/src/Simd/SimdAvx512bw.h @@ -261,9 +261,6 @@ namespace Simd void Gemm32fNT(size_t M, size_t N, size_t K, const float* alpha, const float* A, size_t lda, const float* B, size_t ldb, const float* beta, float* C, size_t ldc); - void HogDirectionHistograms(const uint8_t * src, size_t stride, size_t width, size_t height, - size_t cellX, size_t cellY, size_t quantization, float * histograms); - void HogExtractFeatures(const uint8_t * src, size_t stride, size_t width, size_t height, float * features); void HogDeinterleave(const float * src, size_t srcStride, size_t width, size_t height, size_t count, float ** dst, size_t dstStride); diff --git a/src/Simd/SimdAvx512bwHog.cpp b/src/Simd/SimdAvx512bwHog.cpp index 5b6264558f..49cdf0d96c 100644 --- a/src/Simd/SimdAvx512bwHog.cpp +++ b/src/Simd/SimdAvx512bwHog.cpp @@ -22,7 +22,6 @@ * SOFTWARE. */ #include "Simd/SimdStore.h" -#include "Simd/SimdBase.h" #include "Simd/SimdArray.h" #include "Simd/SimdUnpack.h" @@ -31,355 +30,11 @@ namespace Simd #ifdef SIMD_AVX512BW_ENABLE namespace Avx512bw { - namespace - { - struct Buffer - { - const int size; - __m512 * cos, *sin; - __m512i * pos, *neg; - int * index; - float * value; - - Buffer(size_t width, size_t quantization) - : size((int)quantization / 2) - { - width = AlignHi(width, A / sizeof(float)); - _p = Allocate(width*(sizeof(int) + sizeof(float)) + (sizeof(__m512i) + sizeof(__m512)) * 2 * size); - index = (int*)_p - 1; - value = (float*)index + width; - cos = (__m512*)(value + width + 1); - sin = cos + size; - pos = (__m512i*)(sin + size); - neg = pos + size; - for (int i = 0; i < size; ++i) - { - cos[i] = _mm512_set1_ps((float)::cos(i*M_PI / size)); - sin[i] = _mm512_set1_ps((float)::sin(i*M_PI / size)); - pos[i] = _mm512_set1_epi32(i); - neg[i] = _mm512_set1_epi32(size + i); - } - } - - ~Buffer() - { - Free(_p); - } - - private: - void *_p; - }; - } - - template SIMD_INLINE void HogDirectionHistograms(const __m512 & dx, const __m512 & dy, Buffer & buffer, size_t col) - { - __m512 bestDot = _mm512_setzero_ps(); - __m512i bestIndex = _mm512_setzero_si512(); - for (int i = 0; i < buffer.size; ++i) - { - __m512 dot = _mm512_fmadd_ps(dx, buffer.cos[i], _mm512_mul_ps(dy, buffer.sin[i])); - bestIndex = _mm512_mask_blend_epi32(_mm512_cmp_ps_mask(dot, bestDot, _CMP_GT_OS), bestIndex, buffer.pos[i]); - bestDot = _mm512_max_ps(dot, bestDot); - - dot = _mm512_sub_ps(_mm512_setzero_ps(), dot); - bestIndex = _mm512_mask_blend_epi32(_mm512_cmp_ps_mask(dot, bestDot, _CMP_GT_OS), bestIndex, buffer.neg[i]); - bestDot = _mm512_max_ps(dot, bestDot); - } - Store(buffer.index + col, bestIndex); - Store(buffer.value + col, _mm512_sqrt_ps(_mm512_fmadd_ps(dx, dx, _mm512_mul_ps(dy, dy)))); - } - template SIMD_INLINE __m512 CovertDifference(const __m256i & a, const __m256i & b) { return _mm512_cvtepi32_ps(_mm512_cvtepi16_epi32(Avx2::SubUnpackedU8(a, b))); } - template SIMD_INLINE void HogDirectionHistograms(const uint8_t * src, size_t stride, Buffer & buffer, size_t col) - { - const uint8_t * s = src + col; - __m256i t = Avx2::LoadPermuted((__m256i*)(s - stride)); - __m256i l = Avx2::LoadPermuted((__m256i*)(s - 1)); - __m256i r = Avx2::LoadPermuted((__m256i*)(s + 1)); - __m256i b = Avx2::LoadPermuted((__m256i*)(s + stride)); - HogDirectionHistograms(CovertDifference<0>(r, l), CovertDifference<0>(b, t), buffer, col + 0); - HogDirectionHistograms(CovertDifference<1>(r, l), CovertDifference<1>(b, t), buffer, col + F); - } - - namespace Custom_8x8_18 - { - struct Buffer - { - __m512i pos[5]; - __m512 cos[5], sin[5]; - __m128 kx[8], ky[8]; - - int * index; - float * value; - __m128 * hist; - size_t hs; - - Buffer(size_t width) - { - width = AlignHi(width, A / sizeof(float)); - hs = (width / 8 + 1) * 18 * sizeof(__m128); - _p = Allocate(width*(sizeof(int) + sizeof(float)) + hs); - index = (int*)_p - 1; - value = (float*)index + width; - hist = (__m128*)(value + width + 1); - - for (int i = 0; i < 5; ++i) - { - cos[i] = _mm512_set1_ps((float)::cos(i*M_PI / 9)); - sin[i] = _mm512_set1_ps((float)::sin(i*M_PI / 9)); - pos[i] = _mm512_set1_epi32(i); - } - for (int i = 0; i < 8; ++i) - { - float k0 = float((15 - i * 2) / 16.0f); - float k1 = 1.0f - k0; - kx[i] = _mm_setr_ps(k0, k1, k0, k1); - ky[i] = _mm_setr_ps(k0, k0, k1, k1); - } - ClearHist(); - } - - ~Buffer() - { - Free(_p); - } - - void ClearHist() - { - memset(hist, 0, hs); - } - - private: - void *_p; - }; - - const __m512i K32_9 = SIMD_MM512_SET1_EPI32(9); - const __m512i K32_18 = SIMD_MM512_SET1_EPI32(18); - - template SIMD_INLINE void HogDirectionHistograms(const __m512 & dx, const __m512 & dy, Buffer & buffer, size_t col) - { - __m512 _0 = _mm512_set1_ps(-0.0f); - __m512 adx = _mm512_andnot_ps(_0, dx); - __m512 ady = _mm512_andnot_ps(_0, dy); - __m512 bestDot = _mm512_fmadd_ps(adx, buffer.cos[0], _mm512_mul_ps(ady, buffer.sin[0])); - __m512i bestIndex = buffer.pos[0]; - for (int i = 1; i < 5; ++i) - { - __m512 dot = _mm512_fmadd_ps(adx, buffer.cos[i], _mm512_mul_ps(ady, buffer.sin[i])); - bestIndex = _mm512_mask_blend_epi32(_mm512_cmp_ps_mask(dot, bestDot, _CMP_GT_OS), bestIndex, buffer.pos[i]); - bestDot = _mm512_max_ps(dot, bestDot); - } - bestIndex = _mm512_mask_sub_epi32(bestIndex, _mm512_cmp_ps_mask(dx, _0, _CMP_LT_OS), K32_9, bestIndex); - - __m512i corr = _mm512_maskz_set1_epi32(_mm512_cmp_ps_mask(adx, _mm512_setzero_ps(), _CMP_EQ_OS), 1); - bestIndex = _mm512_mask_sub_epi32(bestIndex, _mm512_cmp_ps_mask(dy, _0, _CMP_LT_OS), K32_18, _mm512_add_epi32(bestIndex, corr)); - - bestIndex = _mm512_mask_set1_epi32(bestIndex, _mm512_cmpeq_epi32_mask(bestIndex, K32_18), 0); - - Store(buffer.index + col, bestIndex); - Store(buffer.value + col, _mm512_sqrt_ps(_mm512_fmadd_ps(adx, adx, _mm512_mul_ps(ady, ady)))); - } - - template SIMD_INLINE void HogDirectionHistograms(const uint8_t * src, size_t stride, Buffer & buffer, size_t col) - { - const uint8_t * s = src + col; - __m256i t = Avx2::LoadPermuted((__m256i*)(s - stride)); - __m256i l = Avx2::LoadPermuted((__m256i*)(s - 1)); - __m256i r = Avx2::LoadPermuted((__m256i*)(s + 1)); - __m256i b = Avx2::LoadPermuted((__m256i*)(s + stride)); - HogDirectionHistograms(CovertDifference<0>(r, l), CovertDifference<0>(b, t), buffer, col + 0); - HogDirectionHistograms(CovertDifference<1>(r, l), CovertDifference<1>(b, t), buffer, col + F); - } - - void AddRowToBuffer(const uint8_t * src, size_t stride, Buffer & buffer, size_t row, size_t width, size_t aligned) - { - const uint8_t * s = src + stride * row; - for (size_t col = 1; col < aligned; col += HA) - HogDirectionHistograms(s, stride, buffer, col); - HogDirectionHistograms(s, stride, buffer, width - 1 - HA); - - __m128 ky = buffer.ky[(row + 4) & 7]; - __m128 * hist = buffer.hist; - size_t cellEnd = width / 8; - - for (size_t col = 1; col < 4; ++col) - { - int index = buffer.index[col]; - __m128 value = _mm_set1_ps(buffer.value[col]); - __m128 kx = buffer.kx[(col + 4) & 7]; - hist[index] = _mm_fmadd_ps(_mm_mul_ps(ky, kx), value, hist[index]); - } - hist += 18; - - for (size_t cell = 1, col = 4; cell < cellEnd; ++cell) - { - for (size_t i = 0; i < 8; ++i, ++col) - { - int index = buffer.index[col]; - __m128 value = _mm_set1_ps(buffer.value[col]); - __m128 kx = buffer.kx[i]; - hist[index] = _mm_fmadd_ps(_mm_mul_ps(ky, kx), value, hist[index]); - } - hist += 18; - } - - for (size_t col = width - 4; col < width - 1; ++col) - { - int index = buffer.index[col]; - __m128 value = _mm_set1_ps(buffer.value[col]); - __m128 kx = buffer.kx[(col + 4) & 7]; - hist[index] = _mm_fmadd_ps(_mm_mul_ps(ky, kx), value, hist[index]); - } - } - - void AddToHistogram(Buffer & buffer, size_t row, size_t width, size_t height, float * histograms) - { - typedef float f18_t[18]; - - float * src = (float*)buffer.hist; - f18_t * h0 = (f18_t*)histograms + row * width - width - 1; - f18_t * h1 = h0 + width; - - if (row == 0) - { - for (size_t i = 0; i < 18; ++i) - h1[1][i] += src[i * 4 + 3]; - h1++; - src += 72; - for (size_t cell = 1; cell < width; ++cell) - { - for (size_t i = 0; i < 18; ++i) - { - h1[0][i] += src[i * 4 + 2]; - h1[1][i] += src[i * 4 + 3]; - } - h1++; - src += 72; - } - for (size_t i = 0; i < 18; ++i) - h1[0][i] += src[i * 4 + 2]; - } - else if (row == height) - { - for (size_t i = 0; i < 18; ++i) - h0[1][i] += src[i * 4 + 1]; - h0++; - src += 72; - for (size_t cell = 1; cell < width; ++cell) - { - for (size_t i = 0; i < 18; ++i) - { - h0[0][i] += src[i * 4 + 0]; - h0[1][i] += src[i * 4 + 1]; - } - h0++; - src += 72; - } - for (size_t i = 0; i < 18; ++i) - h0[0][i] += src[i * 4 + 0]; - } - else - { - for (size_t i = 0; i < 18; ++i) - { - h0[1][i] += src[i * 4 + 1]; - h1[1][i] += src[i * 4 + 3]; - } - h0++; - h1++; - src += 72; - for (size_t cell = 1; cell < width; ++cell) - { - __m512 a0 = Load(src + 0x00, src + 0x10, src + 0x20, src + 0x30); - __m512 a1 = Load(src + 0x04, src + 0x14, src + 0x24, src + 0x34); - __m512 a2 = Load(src + 0x08, src + 0x18, src + 0x28, src + 0x38); - __m512 a3 = Load(src + 0x0C, src + 0x1C, src + 0x2C, src + 0x3C); - __m512 b0 = _mm512_unpacklo_ps(a0, a2); - __m512 b1 = _mm512_unpackhi_ps(a0, a2); - __m512 b2 = _mm512_unpacklo_ps(a1, a3); - __m512 b3 = _mm512_unpackhi_ps(a1, a3); - Store(h0[0], _mm512_add_ps(Load(h0[0]), _mm512_unpacklo_ps(b0, b2))); - Store(h0[1], _mm512_add_ps(Load(h0[1]), _mm512_unpackhi_ps(b0, b2))); - Store(h1[0], _mm512_add_ps(Load(h1[0]), _mm512_unpacklo_ps(b1, b3))); - Store(h1[1], _mm512_add_ps(Load(h1[1]), _mm512_unpackhi_ps(b1, b3))); - for (size_t i = 16; i < 18; ++i) - { - h0[0][i] += src[i * 4 + 0]; - h0[1][i] += src[i * 4 + 1]; - h1[0][i] += src[i * 4 + 2]; - h1[1][i] += src[i * 4 + 3]; - } - h0++; - h1++; - src += 72; - } - for (size_t i = 0; i < 18; ++i) - { - h0[0][i] += src[i * 4 + 0]; - h1[0][i] += src[i * 4 + 2]; - } - } - buffer.ClearHist(); - } - - void HogDirectionHistograms(const uint8_t * src, size_t stride, size_t width, size_t height, float * histograms) - { - const size_t quantization = 18; - - size_t sizeX = width / 8, sizeY = height / 8; - - memset(histograms, 0, quantization*sizeX*sizeY * sizeof(float)); - - Buffer buffer(width); - - size_t aligned = AlignLo(width - 2, HA) + 1; - - for (size_t row = 1; row < 4; ++row) - AddRowToBuffer(src, stride, buffer, row, width, aligned); - AddToHistogram(buffer, 0, sizeX, sizeY, histograms); - for (size_t row = 4, cell = 1; row < height - 4; ++row) - { - AddRowToBuffer(src, stride, buffer, row, width, aligned); - if ((row & 7) == 3) - AddToHistogram(buffer, cell++, sizeX, sizeY, histograms); - } - for (size_t row = height - 4; row < height - 1; ++row) - AddRowToBuffer(src, stride, buffer, row, width, aligned); - AddToHistogram(buffer, sizeY, sizeX, sizeY, histograms); - } - } - - void HogDirectionHistograms(const uint8_t * src, size_t stride, size_t width, size_t height, - size_t cellX, size_t cellY, size_t quantization, float * histograms) - { - assert(width%cellX == 0 && height%cellY == 0 && quantization % 2 == 0); - assert(width >= HA + 2); - - if (cellX == 8 && cellY == 8 && quantization == 18) - Custom_8x8_18::HogDirectionHistograms(src, stride, width, height, histograms); - else - { - memset(histograms, 0, quantization*(width / cellX)*(height / cellY) * sizeof(float)); - - Buffer buffer(width, quantization); - - size_t alignedWidth = AlignLo(width - 2, HA) + 1; - - for (size_t row = 1; row < height - 1; ++row) - { - const uint8_t * s = src + stride * row; - for (size_t col = 1; col < alignedWidth; col += HA) - HogDirectionHistograms(s, stride, buffer, col); - HogDirectionHistograms(s, stride, buffer, width - 1 - HA); - Base::AddRowToHistograms(buffer.index, buffer.value, row, width, height, cellX, cellY, quantization, histograms); - } - } - } - class HogFeatureExtractor { static const size_t C = 8; diff --git a/src/Simd/SimdBase.h b/src/Simd/SimdBase.h index de54e6a112..a2a32c1f8c 100644 --- a/src/Simd/SimdBase.h +++ b/src/Simd/SimdBase.h @@ -309,12 +309,6 @@ namespace Simd void NormalizeHistogram(const uint8_t * src, size_t srcStride, size_t width, size_t height, uint8_t * dst, size_t dstStride); - void AddRowToHistograms(int * indexes, float * values, size_t row, size_t width, size_t height, - size_t cellX, size_t cellY, size_t quantization, float * histograms); - - void HogDirectionHistograms(const uint8_t * src, size_t stride, size_t width, size_t height, - size_t cellX, size_t cellY, size_t quantization, float * histograms); - void HogExtractFeatures(const uint8_t * src, size_t stride, size_t width, size_t height, float * features); void HogDeinterleave(const float * src, size_t srcStride, size_t width, size_t height, size_t count, float ** dst, size_t dstStride); diff --git a/src/Simd/SimdBaseHog.cpp b/src/Simd/SimdBaseHog.cpp index fa26e4fe0a..cd940bd666 100644 --- a/src/Simd/SimdBaseHog.cpp +++ b/src/Simd/SimdBaseHog.cpp @@ -27,219 +27,6 @@ namespace Simd { namespace Base { - namespace - { - struct Buffer - { - const int size; - float * cos, *sin; - int * index; - float * value; - - Buffer(size_t width, size_t quantization) - : size((int)quantization / 2) - { - _p = Allocate(width*(sizeof(int) + sizeof(float)) + sizeof(float) * 2 * size); - index = (int*)_p; - value = (float*)index + width; - cos = value + width; - sin = cos + size; - for (int i = 0; i < size; ++i) - { - cos[i] = (float)::cos(i*M_PI / size); - sin[i] = (float)::sin(i*M_PI / size); - } - } - - ~Buffer() - { - Free(_p); - } - - private: - void *_p; - }; - } - - void AddRowToHistograms(int * indexes, float * values, size_t row, size_t width, size_t height, size_t cellX, size_t cellY, size_t quantization, float * histograms) - { - int blockX = int(width / cellX); - int blockY = int(height / cellY); - int blockStride = int(quantization*blockX); - - float yp = ((float)row + 0.5f) / (float)cellY - 0.5f; - int iyp = (int)floor(yp); - float vy0 = yp - iyp; - float vy1 = 1.0f - vy0; - - size_t noseEnd = cellX / 2; - size_t bodyEnd = width - cellX / 2; - - if (iyp < 0) - { - float * h = histograms + (iyp + 1)*blockStride; - for (size_t col = 1; col < width - 1; ++col) - { - float value = values[col]; - int index = indexes[col]; - - float xp = ((float)col + 0.5f) / (float)cellX - 0.5f; - int ixp = (int)floor(xp); - float vx0 = xp - ixp; - float vx1 = 1.0f - vx0; - - if (ixp >= 0) - h[ixp*quantization + index] += vx1 * vy0*value; - if (ixp + 1 < blockX) - h[(ixp + 1)*quantization + index] += vx0 * vy0*value; - } - } - else if (iyp + 1 == blockY) - { - float * h = histograms + iyp * blockStride; - for (size_t col = 1; col < width - 1; ++col) - { - float value = values[col]; - int index = indexes[col]; - - float xp = ((float)col + 0.5f) / (float)cellX - 0.5f; - int ixp = (int)floor(xp); - float vx0 = xp - ixp; - float vx1 = 1.0f - vx0; - - if (ixp >= 0) - h[ixp*quantization + index] += vx1 * vy1*value; - if (ixp + 1 < blockX) - h[(ixp + 1)*quantization + index] += vx0 * vy1*value; - } - } - else - { - float * h0 = histograms + iyp * blockStride; - float * h1 = histograms + (iyp + 1)*blockStride; - size_t col = 1; - for (; col < noseEnd; ++col) - { - float value = values[col]; - int index = indexes[col]; - - float xp = ((float)col + 0.5f) / (float)cellX - 0.5f; - int ixp = (int)floor(xp); - float vx0 = xp - ixp; - - h0[(ixp + 1)*quantization + index] += vx0 * vy1*value; - h1[(ixp + 1)*quantization + index] += vx0 * vy0*value; - } - - for (; col < bodyEnd; ++col) - { - float value = values[col]; - int index = indexes[col]; - - float xp = ((float)col + 0.5f) / (float)cellX - 0.5f; - int ixp = (int)floor(xp); - float vx0 = xp - ixp; - float vx1 = 1.0f - vx0; - - h0[ixp*quantization + index] += vx1 * vy1*value; - h1[ixp*quantization + index] += vx1 * vy0*value; - h0[(ixp + 1)*quantization + index] += vx0 * vy1*value; - h1[(ixp + 1)*quantization + index] += vx0 * vy0*value; - } - - for (; col < width - 1; ++col) - { - float value = values[col]; - int index = indexes[col]; - - float xp = ((float)col + 0.5f) / (float)cellX - 0.5f; - int ixp = (int)floor(xp); - float vx0 = xp - ixp; - float vx1 = 1.0f - vx0; - - h0[ixp*quantization + index] += vx1 * vy1*value; - h1[ixp*quantization + index] += vx1 * vy0*value; - } - } - } - - void HogDirectionHistograms(const uint8_t * src, size_t stride, size_t width, size_t height, - size_t cellX, size_t cellY, size_t quantization, float * histograms) - { - assert(width%cellX == 0 && height%cellY == 0 && quantization % 2 == 0); - - Buffer buffer(width, quantization); - - memset(histograms, 0, quantization*(width / cellX)*(height / cellY) * sizeof(float)); - - for (size_t row = 1; row < height - 1; ++row) - { - const uint8_t * src1 = src + stride * row; - const uint8_t * src0 = src1 - stride; - const uint8_t * src2 = src1 + stride; - -#if 1 - for (size_t col = 1; col < width - 1; ++col) - { - float dy = (float)(src2[col] - src0[col]); - float dx = (float)(src1[col + 1] - src1[col - 1]); - float value = (float)::sqrt(dx*dx + dy * dy); - - float bestDot = 0; - int index = 0; - for (int direction = 0; direction < buffer.size; direction++) - { - float dot = buffer.cos[direction] * dx + buffer.sin[direction] * dy; - if (dot > bestDot) - { - bestDot = dot; - index = direction; - } - else if (-dot > bestDot) - { - bestDot = -dot; - index = direction + buffer.size; - } - } - - buffer.value[col] = value; - buffer.index[col] = index; - } -#else - size_t size = (buffer.size + 1) / 2; - for (size_t col = 1; col < width - 1; ++col) - { - float dy = (float)(src2[col] - src0[col]); - float dx = (float)(src1[col + 1] - src1[col - 1]); - float value = (float)::sqrt(dx*dx + dy * dy); - float ady = Simd::Abs(dy); - float adx = Simd::Abs(dx); - - float bestDot = 0; - int index = 0; - for (int direction = 0; direction < size; direction++) - { - float dot = buffer.cos[direction] * adx + buffer.sin[direction] * ady; - if (dot > bestDot) - { - bestDot = dot; - index = direction; - } - } - if (dx < 0) - index = buffer.size - index; - if (dy < 0 && index != 0) - index = buffer.size * 2 - index - (dx == 0); - - buffer.value[col] = value; - buffer.index[col] = index; - } -#endif - - AddRowToHistograms(buffer.index, buffer.value, row, width, height, cellX, cellY, quantization, histograms); - } - } - class HogFeatureExtractor { static const size_t C = 8; diff --git a/src/Simd/SimdLib.cpp b/src/Simd/SimdLib.cpp index 72e348ae87..e711eac978 100644 --- a/src/Simd/SimdLib.cpp +++ b/src/Simd/SimdLib.cpp @@ -3218,38 +3218,6 @@ SIMD_API void SimdNormalizeHistogram(const uint8_t * src, size_t srcStride, size Base::NormalizeHistogram(src, srcStride, width, height, dst, dstStride); } -SIMD_API void SimdHogDirectionHistograms(const uint8_t * src, size_t stride, size_t width, size_t height, - size_t cellX, size_t cellY, size_t quantization, float * histograms) -{ - SIMD_EMPTY(); -#ifdef SIMD_AVX512BW_ENABLE - if (Avx512bw::Enable && width >= Avx512bw::HA + 2) - Avx512bw::HogDirectionHistograms(src, stride, width, height, cellX, cellY, quantization, histograms); - else -#endif -#ifdef SIMD_AVX2_ENABLE - if(Avx2::Enable && width >= Avx2::A + 2) - Avx2::HogDirectionHistograms(src, stride, width, height, cellX, cellY, quantization, histograms); - else -#endif -#ifdef SIMD_SSE41_ENABLE - if (Sse41::Enable && width >= Sse41::A + 2) - Sse41::HogDirectionHistograms(src, stride, width, height, cellX, cellY, quantization, histograms); - else -#endif -#ifdef SIMD_SVE2_ENABLE - if (Sve2::Enable && width >= 3) - Sve2::HogDirectionHistograms(src, stride, width, height, cellX, cellY, quantization, histograms); - else -#endif -#ifdef SIMD_NEON_ENABLE - if (Neon::Enable && width >= Neon::A + 2) - Neon::HogDirectionHistograms(src, stride, width, height, cellX, cellY, quantization, histograms); - else -#endif - Base::HogDirectionHistograms(src, stride, width, height, cellX, cellY, quantization, histograms); -} - SIMD_API void SimdHogExtractFeatures(const uint8_t * src, size_t stride, size_t width, size_t height, float * features) { SIMD_EMPTY(); diff --git a/src/Simd/SimdLib.h b/src/Simd/SimdLib.h index e34c65bbfa..b2000a6b44 100644 --- a/src/Simd/SimdLib.h +++ b/src/Simd/SimdLib.h @@ -4410,40 +4410,6 @@ extern "C" */ SIMD_API void SimdNormalizeHistogram(const uint8_t * src, size_t srcStride, size_t width, size_t height, uint8_t * dst, size_t dstStride); - /*! @ingroup hog - - \fn void SimdHogDirectionHistograms(const uint8_t * src, size_t stride, size_t width, size_t height, size_t cellX, size_t cellY, size_t quantization, float * histograms); - - \short Calculates HOG direction histograms for an 8-bit gray image. - - \deprecated This function will be removed in the nearest future. - - The function uses central differences for pixels except the one-pixel image border: - \verbatim - dx = src[x + 1, y] - src[x - 1, y]; - dy = src[x, y + 1] - src[x, y - 1]; - magnitude = Sqrt(dx*dx + dy*dy); - direction = index with maximal absolute dot product against quantization directions; - \endverbatim - - Pixel magnitudes are bilinearly distributed to neighboring cells. The output buffer is - cleared and then filled in row-major cell order: - histograms[(cellYIndex*(width/cellX) + cellXIndex)*quantization + direction]. - - \note This function has a C++ wrapper Simd::HogDirectionHistograms(const View & src, const Point & cell, size_t quantization, float * histograms). - - \param [in] src - a pointer to pixels data of input 8-bit gray image. - \param [in] stride - a row size of the image (in bytes). - \param [in] width - an image width. It must be a multiple of cellX. - \param [in] height - an image height. It must be a multiple of cellY. - \param [in] cellX - a width of cell. - \param [in] cellY - a height of cell. - \param [in] quantization - a direction quantization. Must be even. - \param [out] histograms - a pointer to buffer with histograms. Array must have size greater or equal to (width/cellX)*(height/cellY)*quantization. - */ - SIMD_DEPRECATED SIMD_API void SimdHogDirectionHistograms(const uint8_t * src, size_t stride, size_t width, size_t height, - size_t cellX, size_t cellY, size_t quantization, float * histograms); - /*! @ingroup hog \fn void SimdHogExtractFeatures(const uint8_t * src, size_t stride, size_t width, size_t height, float * features); diff --git a/src/Simd/SimdLib.hpp b/src/Simd/SimdLib.hpp index 515ee4aa74..806c3ea94d 100644 --- a/src/Simd/SimdLib.hpp +++ b/src/Simd/SimdLib.hpp @@ -2482,40 +2482,6 @@ namespace Simd return (uint8_t)bestThreshold; } - /*! @ingroup hog - - \fn void HogDirectionHistograms(const View & src, const Point & cell, size_t quantization, float * histograms); - - \short Calculates HOG direction histograms for an 8-bit gray image. - - \deprecated This function will be removed in the nearest future. - - The function uses central differences for pixels except the one-pixel image border: - \verbatim - dx = src[x + 1, y] - src[x - 1, y]; - dy = src[x, y + 1] - src[x, y - 1]; - magnitude = Sqrt(dx*dx + dy*dy); - direction = index with maximal absolute dot product against quantization directions; - \endverbatim - - Pixel magnitudes are bilinearly distributed to neighboring cells. The output buffer is - cleared and then filled in row-major cell order: - histograms[(cellYIndex*(src.width/cell.x) + cellXIndex)*quantization + direction]. - - \note This function is a C++ wrapper for function ::SimdHogDirectionHistograms. - - \param [in] src - an input 8-bit gray image. Its width must be a multiple of cell.x and its height must be a multiple of cell.y. - \param [in] cell - a cell size in pixels. - \param [in] quantization - a direction quantization. Must be even. - \param [out] histograms - a pointer to buffer with histograms. Array must have size greater or equal to (src.width/cell.x)*(src.height/cell.y)*quantization. - */ - template class A> SIMD_DEPRECATED SIMD_INLINE void HogDirectionHistograms(const View & src, const Point & cell, size_t quantization, float * histograms) - { - assert(src.format == View::Gray8 && src.width%cell.x == 0 && src.height%cell.y == 0 && quantization % 2 == 0); - - SimdHogDirectionHistograms(src.data, src.stride, src.width, src.height, cell.x, cell.y, quantization, histograms); - } - /*! @ingroup hog \fn void HogExtractFeatures(const View & src, float * features) diff --git a/src/Simd/SimdNeon.h b/src/Simd/SimdNeon.h index fe952b3f0d..25764874a5 100644 --- a/src/Simd/SimdNeon.h +++ b/src/Simd/SimdNeon.h @@ -275,9 +275,6 @@ namespace Simd void HogDeinterleave(const float * src, size_t srcStride, size_t width, size_t height, size_t count, float ** dst, size_t dstStride); - void HogDirectionHistograms(const uint8_t * src, size_t stride, size_t width, size_t height, - size_t cellX, size_t cellY, size_t quantization, float * histograms); - void HogExtractFeatures(const uint8_t * src, size_t stride, size_t width, size_t height, float * features); void HogFilterSeparable(const float * src, size_t srcStride, size_t width, size_t height, const float * rowFilter, size_t rowSize, const float * colFilter, size_t colSize, float * dst, size_t dstStride, int add); diff --git a/src/Simd/SimdNeonHog.cpp b/src/Simd/SimdNeonHog.cpp index bf5efaa4ae..908297f160 100644 --- a/src/Simd/SimdNeonHog.cpp +++ b/src/Simd/SimdNeonHog.cpp @@ -23,7 +23,6 @@ */ #include "Simd/SimdArray.h" #include "Simd/SimdStore.h" -#include "Simd/SimdBase.h" #include "Simd/SimdSet.h" #include "Simd/SimdExtract.h" @@ -78,104 +77,6 @@ namespace Simd } } - namespace - { - struct Buffer - { - const int size; - float32x4_t * cos, *sin; - int32x4_t * pos, *neg; - int * index; - float * value; - - Buffer(size_t width, size_t quantization) - : size((int)quantization / 2) - { - width = AlignHi(width, A / sizeof(float)); - _p = Allocate(width*(sizeof(int) + sizeof(float)) + (sizeof(int32x4_t) + sizeof(float32x4_t)) * 2 * size); - index = (int*)_p - 1; - value = (float*)index + width; - cos = (float32x4_t*)(value + width + 1); - sin = cos + size; - pos = (int32x4_t*)(sin + size); - neg = pos + size; - for (int i = 0; i < size; ++i) - { - cos[i] = vdupq_n_f32((float)::cos(i*M_PI / size)); - sin[i] = vdupq_n_f32((float)::sin(i*M_PI / size)); - pos[i] = vdupq_n_s32(i); - neg[i] = vdupq_n_s32(size + i); - } - } - - ~Buffer() - { - Free(_p); - } - - private: - void *_p; - }; - } - - template SIMD_INLINE void HogDirectionHistograms32(const float32x4_t & dx, const float32x4_t & dy, Buffer & buffer, size_t col) - { - float32x4_t bestDot = vdupq_n_f32(0); - int32x4_t bestIndex = vdupq_n_s32(0); - for (int i = 0; i < buffer.size; ++i) - { - float32x4_t dot = vaddq_f32(vmulq_f32(dx, buffer.cos[i]), vmulq_f32(dy, buffer.sin[i])); - uint32x4_t mask = vcgtq_f32(dot, bestDot); - bestDot = vmaxq_f32(dot, bestDot); - bestIndex = vbslq_s32(mask, buffer.pos[i], bestIndex); - - dot = vnegq_f32(dot); - mask = vcgtq_f32(dot, bestDot); - bestDot = vmaxq_f32(dot, bestDot); - bestIndex = vbslq_s32(mask, buffer.neg[i], bestIndex); - } - Store(buffer.index + col, bestIndex); - Store(buffer.value + col, Sqrt(vaddq_f32(vmulq_f32(dx, dx), vmulq_f32(dy, dy)))); - } - - template SIMD_INLINE void HogDirectionHistograms16(const int16x8_t & dx, const int16x8_t & dy, Buffer & buffer, size_t col) - { - HogDirectionHistograms32(Int16ToFloat<0>(dx), Int16ToFloat<0>(dy), buffer, col + 0); - HogDirectionHistograms32(Int16ToFloat<1>(dx), Int16ToFloat<1>(dy), buffer, col + 4); - } - - template SIMD_INLINE void HogDirectionHistograms(const uint8_t * src, size_t stride, Buffer & buffer, size_t col) - { - const uint8_t * s = src + col; - uint8x16_t t = Load(s - stride); - uint8x16_t l = Load(s - 1); - uint8x16_t r = Load(s + 1); - uint8x16_t b = Load(s + stride); - HogDirectionHistograms16(Sub<0>(r, l), Sub<0>(b, t), buffer, col + 0); - HogDirectionHistograms16(Sub<1>(r, l), Sub<1>(b, t), buffer, col + 8); - } - - void HogDirectionHistograms(const uint8_t * src, size_t stride, size_t width, size_t height, - size_t cellX, size_t cellY, size_t quantization, float * histograms) - { - assert(width%cellX == 0 && height%cellY == 0 && quantization % 2 == 0); - - Buffer buffer(width, quantization); - - memset(histograms, 0, quantization*(width / cellX)*(height / cellY) * sizeof(float)); - - size_t alignedWidth = AlignLo(width - 2, A) + 1; - - for (size_t row = 1; row < height - 1; ++row) - { - const uint8_t * s = src + stride*row; - for (size_t col = 1; col < alignedWidth; col += A) - HogDirectionHistograms(s, stride, buffer, col); - HogDirectionHistograms(s, stride, buffer, width - 1 - A); - Base::AddRowToHistograms(buffer.index, buffer.value, row, width, height, cellX, cellY, quantization, histograms); - } - } - class HogFeatureExtractor { static const size_t C = 8; diff --git a/src/Simd/SimdSse41.h b/src/Simd/SimdSse41.h index e0a9da30b7..b517df495b 100644 --- a/src/Simd/SimdSse41.h +++ b/src/Simd/SimdSse41.h @@ -253,8 +253,6 @@ namespace Simd void HogDeinterleave(const float* src, size_t srcStride, size_t width, size_t height, size_t count, float** dst, size_t dstStride); - void HogDirectionHistograms(const uint8_t * src, size_t stride, size_t width, size_t height, size_t cellX, size_t cellY, size_t quantization, float * histograms); - void HogExtractFeatures(const uint8_t * src, size_t stride, size_t width, size_t height, float * features); void HogFilterSeparable(const float* src, size_t srcStride, size_t width, size_t height, const float* rowFilter, size_t rowSize, const float* colFilter, size_t colSize, float* dst, size_t dstStride, int add); diff --git a/src/Simd/SimdSse41Hog.cpp b/src/Simd/SimdSse41Hog.cpp index 46dca95018..8bad710cc3 100644 --- a/src/Simd/SimdSse41Hog.cpp +++ b/src/Simd/SimdSse41Hog.cpp @@ -22,7 +22,6 @@ * SOFTWARE. */ #include "Simd/SimdStore.h" -#include "Simd/SimdBase.h" #include "Simd/SimdArray.h" #include "Simd/SimdUnpack.h" @@ -81,387 +80,6 @@ namespace Simd } } - //----------------------------------------------------------------------------------------- - - namespace Common - { - struct Buffer - { - const int size; - __m128* cos, * sin; - __m128i* pos, * neg; - int* index; - float* value; - - Buffer(size_t width, size_t quantization) - : size((int)quantization / 2) - { - width = AlignHi(width, A / sizeof(float)); - _p = Allocate(width * (sizeof(int) + sizeof(float)) + (sizeof(__m128i) + sizeof(__m128)) * 2 * size); - index = (int*)_p - 1; - value = (float*)index + width; - cos = (__m128*)(value + width + 1); - sin = cos + size; - pos = (__m128i*)(sin + size); - neg = pos + size; - for (int i = 0; i < size; ++i) - { - cos[i] = _mm_set1_ps((float)::cos(i * M_PI / size)); - sin[i] = _mm_set1_ps((float)::sin(i * M_PI / size)); - pos[i] = _mm_set1_epi32(i); - neg[i] = _mm_set1_epi32(size + i); - } - } - - ~Buffer() - { - Free(_p); - } - - private: - void* _p; - }; - - template SIMD_INLINE void HogDirectionHistograms(const __m128& dx, const __m128& dy, Buffer& buffer, size_t col) - { - __m128 bestDot = _mm_setzero_ps(); - __m128i bestIndex = _mm_setzero_si128(); - for (int i = 0; i < buffer.size; ++i) - { - __m128 dot = _mm_add_ps(_mm_mul_ps(dx, buffer.cos[i]), _mm_mul_ps(dy, buffer.sin[i])); - __m128 mask = _mm_cmpgt_ps(dot, bestDot); - bestDot = _mm_max_ps(dot, bestDot); - bestIndex = Combine(_mm_castps_si128(mask), buffer.pos[i], bestIndex); - - dot = _mm_sub_ps(_mm_setzero_ps(), dot); - mask = _mm_cmpgt_ps(dot, bestDot); - bestDot = _mm_max_ps(dot, bestDot); - bestIndex = Combine(_mm_castps_si128(mask), buffer.neg[i], bestIndex); - } - Store((__m128i*)(buffer.index + col), bestIndex); - Store(buffer.value + col, Sqrt<0>(_mm_add_ps(_mm_mul_ps(dx, dx), _mm_mul_ps(dy, dy)))); - } - - template SIMD_INLINE void HogDirectionHistograms(const __m128i& t, const __m128i& l, const __m128i& r, const __m128i& b, Buffer& buffer, size_t col) - { - HogDirectionHistograms( - _mm_cvtepi32_ps(_mm_sub_epi32(_mm_unpacklo_epi16(r, K_ZERO), _mm_unpacklo_epi16(l, K_ZERO))), - _mm_cvtepi32_ps(_mm_sub_epi32(_mm_unpacklo_epi16(b, K_ZERO), _mm_unpacklo_epi16(t, K_ZERO))), - buffer, col + 0); - HogDirectionHistograms( - _mm_cvtepi32_ps(_mm_sub_epi32(_mm_unpackhi_epi16(r, K_ZERO), _mm_unpackhi_epi16(l, K_ZERO))), - _mm_cvtepi32_ps(_mm_sub_epi32(_mm_unpackhi_epi16(b, K_ZERO), _mm_unpackhi_epi16(t, K_ZERO))), - buffer, col + 4); - } - - template SIMD_INLINE void HogDirectionHistograms(const uint8_t* src, size_t stride, Buffer& buffer, size_t col) - { - const uint8_t* s = src + col; - __m128i t = Load((__m128i*)(s - stride)); - __m128i l = Load((__m128i*)(s - 1)); - __m128i r = Load((__m128i*)(s + 1)); - __m128i b = Load((__m128i*)(s + stride)); - HogDirectionHistograms(_mm_unpacklo_epi8(t, K_ZERO), _mm_unpacklo_epi8(l, K_ZERO), - _mm_unpacklo_epi8(r, K_ZERO), _mm_unpacklo_epi8(b, K_ZERO), buffer, col + 0); - HogDirectionHistograms(_mm_unpackhi_epi8(t, K_ZERO), _mm_unpackhi_epi8(l, K_ZERO), - _mm_unpackhi_epi8(r, K_ZERO), _mm_unpackhi_epi8(b, K_ZERO), buffer, col + 8); - } - - void HogDirectionHistograms(const uint8_t* src, size_t stride, size_t width, size_t height, - size_t cellX, size_t cellY, size_t quantization, float* histograms) - { - assert(width % cellX == 0 && height % cellY == 0 && quantization % 2 == 0); - assert(width >= A + 2); - - Buffer buffer(width, quantization); - - memset(histograms, 0, quantization * (width / cellX) * (height / cellY) * sizeof(float)); - - size_t alignedWidth = AlignLo(width - 2, A) + 1; - - for (size_t row = 1; row < height - 1; ++row) - { - const uint8_t* s = src + stride * row; - for (size_t col = 1; col < alignedWidth; col += A) - HogDirectionHistograms(s, stride, buffer, col); - HogDirectionHistograms(s, stride, buffer, width - 1 - A); - Base::AddRowToHistograms(buffer.index, buffer.value, row, width, height, cellX, cellY, quantization, histograms); - } - } - } - - namespace Custom_8x8_18 - { - struct Buffer - { - __m128i pos[5]; - __m128 cos[5], sin[5], kx[8], ky[8]; - - int * index; - float * value; - __m128 * hist; - size_t hs; - - Buffer(size_t width) - { - width = AlignHi(width, A / sizeof(float)); - hs = (width / 8 + 1) * 18 * sizeof(__m128); - _p = Allocate(width*(sizeof(int) + sizeof(float)) + hs); - index = (int*)_p - 1; - value = (float*)index + width; - hist = (__m128*)(value + width + 1); - - for (int i = 0; i < 5; ++i) - { - cos[i] = _mm_set1_ps((float)::cos(i*M_PI / 9)); - sin[i] = _mm_set1_ps((float)::sin(i*M_PI / 9)); - pos[i] = _mm_set1_epi32(i); - } - for (int i = 0; i < 8; ++i) - { - float k0 = float((15 - i * 2) / 16.0f); - float k1 = 1.0f - k0; - kx[i] = _mm_setr_ps(k0, k1, k0, k1); - ky[i] = _mm_setr_ps(k0, k0, k1, k1); - } - ClearHist(); - } - - ~Buffer() - { - Free(_p); - } - - SIMD_INLINE void ClearHist() - { - memset(hist, 0, hs); - } - - private: - void *_p; - }; - - const __m128i K32_1 = SIMD_MM_SET1_EPI32(1); - const __m128i K32_9 = SIMD_MM_SET1_EPI32(9); - const __m128i K32_18 = SIMD_MM_SET1_EPI32(18); - - template SIMD_INLINE void HogDirectionHistograms(const __m128 & dx, const __m128 & dy, Buffer & buffer, size_t col) - { - __m128 _0 = _mm_set1_ps(-0.0f); - __m128 adx = _mm_andnot_ps(_0, dx); - __m128 ady = _mm_andnot_ps(_0, dy); - __m128 bestDot = _mm_add_ps(_mm_mul_ps(adx, buffer.cos[0]), _mm_mul_ps(ady, buffer.sin[0])); - __m128i bestIndex = buffer.pos[0]; - for (int i = 1; i < 5; ++i) - { - __m128 dot = _mm_add_ps(_mm_mul_ps(adx, buffer.cos[i]), _mm_mul_ps(ady, buffer.sin[i])); - __m128 mask = _mm_cmpgt_ps(dot, bestDot); - bestDot = _mm_max_ps(dot, bestDot); - bestIndex = _mm_blendv_epi8(bestIndex, buffer.pos[i], _mm_castps_si128(mask)); - } - __m128i maskDx = _mm_castps_si128(_mm_cmplt_ps(dx, _mm_setzero_ps())); - bestIndex = _mm_blendv_epi8(bestIndex, _mm_sub_epi32(K32_9, bestIndex), maskDx); - - __m128i maskDy = _mm_castps_si128(_mm_cmplt_ps(dy, _mm_setzero_ps())); - __m128i corr = _mm_and_si128(_mm_castps_si128(_mm_cmpeq_ps(adx, _mm_setzero_ps())), K32_1); - bestIndex = _mm_blendv_epi8(bestIndex, _mm_sub_epi32(K32_18, _mm_add_epi32(bestIndex, corr)), maskDy); - - bestIndex = _mm_andnot_si128(_mm_cmpeq_epi32(bestIndex, K32_18), bestIndex); - - Store((__m128i*)(buffer.index + col), bestIndex); - Store(buffer.value + col, Sqrt<0>(_mm_add_ps(_mm_mul_ps(adx, adx), _mm_mul_ps(ady, ady)))); - } - - template SIMD_INLINE void HogDirectionHistograms(const __m128i & dx, const __m128i & dy, Buffer & buffer, size_t col) - { - HogDirectionHistograms(_mm_cvtepi32_ps(UnpackI16<0>(dx)), _mm_cvtepi32_ps(UnpackI16<0>(dy)), buffer, col + 0); - HogDirectionHistograms(_mm_cvtepi32_ps(UnpackI16<1>(dx)), _mm_cvtepi32_ps(UnpackI16<1>(dy)), buffer, col + 4); - } - - template SIMD_INLINE void HogDirectionHistograms(const uint8_t * src, size_t stride, Buffer & buffer, size_t col) - { - const uint8_t * s = src + col; - __m128i t = Load((__m128i*)(s - stride)); - __m128i l = Load((__m128i*)(s - 1)); - __m128i r = Load((__m128i*)(s + 1)); - __m128i b = Load((__m128i*)(s + stride)); - HogDirectionHistograms(SubUnpackedU8<0>(r, l), SubUnpackedU8<0>(b, t), buffer, col + 0); - HogDirectionHistograms(SubUnpackedU8<1>(r, l), SubUnpackedU8<1>(b, t), buffer, col + 8); - } - - void AddRowToBuffer(const uint8_t * src, size_t stride, Buffer & buffer, size_t row, size_t width, size_t aligned) - { - const uint8_t * s = src + stride * row; - for (size_t col = 1; col < aligned; col += A) - HogDirectionHistograms(s, stride, buffer, col); - HogDirectionHistograms(s, stride, buffer, width - 1 - A); - - __m128 ky = buffer.ky[(row + 4) & 7]; - __m128 * hist = buffer.hist; - size_t cellEnd = width / 8; - - for (size_t col = 1; col < 4; ++col) - { - int index = buffer.index[col]; - __m128 value = _mm_set1_ps(buffer.value[col]); - __m128 kx = buffer.kx[(col + 4) & 7]; - hist[index] = _mm_add_ps(hist[index], _mm_mul_ps(value, _mm_mul_ps(ky, kx))); - } - hist += 18; - - for (size_t cell = 1, col = 4; cell < cellEnd; ++cell) - { - for (size_t i = 0; i < 8; ++i, ++col) - { - int index = buffer.index[col]; - __m128 value = _mm_set1_ps(buffer.value[col]); - __m128 kx = buffer.kx[i]; - hist[index] = _mm_add_ps(hist[index], _mm_mul_ps(value, _mm_mul_ps(ky, kx))); - } - hist += 18; - } - - for (size_t col = width - 4; col < width - 1; ++col) - { - int index = buffer.index[col]; - __m128 value = _mm_set1_ps(buffer.value[col]); - __m128 kx = buffer.kx[(col + 4) & 7]; - hist[index] = _mm_add_ps(hist[index], _mm_mul_ps(value, _mm_mul_ps(ky, kx))); - } - } - - void AddToHistogram(Buffer & buffer, size_t row, size_t width, size_t height, float * histograms) - { - typedef float f18_t[18]; - - float * src = (float*)buffer.hist; - f18_t * h0 = (f18_t*)histograms + row * width - width - 1; - f18_t * h1 = h0 + width; - - if (row == 0) - { - for (size_t i = 0; i < 18; ++i) - h1[1][i] += src[i * 4 + 3]; - h1++; - src += 72; - for (size_t cell = 1; cell < width; ++cell) - { - for (size_t i = 0; i < 18; ++i) - { - h1[0][i] += src[i * 4 + 2]; - h1[1][i] += src[i * 4 + 3]; - } - h1++; - src += 72; - } - for (size_t i = 0; i < 18; ++i) - h1[0][i] += src[i * 4 + 2]; - } - else if (row == height) - { - for (size_t i = 0; i < 18; ++i) - h0[1][i] += src[i * 4 + 1]; - h0++; - src += 72; - for (size_t cell = 1; cell < width; ++cell) - { - for (size_t i = 0; i < 18; ++i) - { - h0[0][i] += src[i * 4 + 0]; - h0[1][i] += src[i * 4 + 1]; - } - h0++; - src += 72; - } - for (size_t i = 0; i < 18; ++i) - h0[0][i] += src[i * 4 + 0]; - } - else - { - for (size_t i = 0; i < 18; ++i) - { - h0[1][i] += src[i * 4 + 1]; - h1[1][i] += src[i * 4 + 3]; - } - h0++; - h1++; - src += 72; - for (size_t cell = 1; cell < width; ++cell) - { - __m128 * ps = (__m128*)src; - for (size_t i = 0; i < 16; i += 4) - { - __m128 s00 = _mm_unpacklo_ps(ps[i + 0], ps[i + 2]); - __m128 s01 = _mm_unpacklo_ps(ps[i + 1], ps[i + 3]); - __m128 s10 = _mm_unpackhi_ps(ps[i + 0], ps[i + 2]); - __m128 s11 = _mm_unpackhi_ps(ps[i + 1], ps[i + 3]); - - _mm_storeu_ps(h0[0] + i, _mm_add_ps(_mm_loadu_ps(h0[0] + i), _mm_unpacklo_ps(s00, s01))); - _mm_storeu_ps(h0[1] + i, _mm_add_ps(_mm_loadu_ps(h0[1] + i), _mm_unpackhi_ps(s00, s01))); - _mm_storeu_ps(h1[0] + i, _mm_add_ps(_mm_loadu_ps(h1[0] + i), _mm_unpacklo_ps(s10, s11))); - _mm_storeu_ps(h1[1] + i, _mm_add_ps(_mm_loadu_ps(h1[1] + i), _mm_unpackhi_ps(s10, s11))); - } - for (size_t i = 16; i < 18; ++i) - { - h0[0][i] += src[i * 4 + 0]; - h0[1][i] += src[i * 4 + 1]; - h1[0][i] += src[i * 4 + 2]; - h1[1][i] += src[i * 4 + 3]; - } - h0++; - h1++; - src += 72; - } - for (size_t i = 0; i < 18; ++i) - { - h0[0][i] += src[i * 4 + 0]; - h1[0][i] += src[i * 4 + 2]; - } - } - buffer.ClearHist(); - } - - void HogDirectionHistograms(const uint8_t * src, size_t stride, size_t width, size_t height, float * histograms) - { - const size_t quantization = 18; - - size_t sizeX = width / 8, sizeY = height / 8; - - memset(histograms, 0, quantization*sizeX*sizeY * sizeof(float)); - - Buffer buffer(width); - - size_t aligned = AlignLo(width - 2, A) + 1; - - for (size_t row = 1; row < 4; ++row) - AddRowToBuffer(src, stride, buffer, row, width, aligned); - AddToHistogram(buffer, 0, sizeX, sizeY, histograms); - for (size_t row = 4, cell = 1; row < height - 4; ++row) - { - AddRowToBuffer(src, stride, buffer, row, width, aligned); - if ((row & 7) == 3) - AddToHistogram(buffer, cell++, sizeX, sizeY, histograms); - } - for (size_t row = height - 4; row < height - 1; ++row) - AddRowToBuffer(src, stride, buffer, row, width, aligned); - AddToHistogram(buffer, sizeY, sizeX, sizeY, histograms); - } - } - - void HogDirectionHistograms(const uint8_t * src, size_t stride, size_t width, size_t height, - size_t cellX, size_t cellY, size_t quantization, float * histograms) - { - assert(width%cellX == 0 && height%cellY == 0 && quantization % 2 == 0); - assert(width >= A + 2); - - if (cellX == 8 && cellY == 8 && quantization == 18) - Custom_8x8_18::HogDirectionHistograms(src, stride, width, height, histograms); - else - Common::HogDirectionHistograms(src, stride, width, height, cellX, cellY, quantization, histograms); - } - - //----------------------------------------------------------------------------------------- - class HogFeatureExtractor { static const size_t C = 8; diff --git a/src/Simd/SimdSve2.h b/src/Simd/SimdSve2.h index b40ea4ddb5..76e32384c1 100644 --- a/src/Simd/SimdSve2.h +++ b/src/Simd/SimdSve2.h @@ -200,9 +200,6 @@ namespace Simd void Gemm32fNT(size_t M, size_t N, size_t K, const float* alpha, const float* A, size_t lda, const float* B, size_t ldb, const float* beta, float* C, size_t ldc); - void HogDirectionHistograms(const uint8_t* src, size_t stride, size_t width, size_t height, - size_t cellX, size_t cellY, size_t quantization, float* histograms); - void HogExtractFeatures(const uint8_t* src, size_t stride, size_t width, size_t height, float* features); void HogDeinterleave(const float* src, size_t srcStride, size_t width, size_t height, size_t count, float** dst, size_t dstStride); diff --git a/src/Simd/SimdSve2Hog.cpp b/src/Simd/SimdSve2Hog.cpp index 09629f8f8d..6de6a4b284 100644 --- a/src/Simd/SimdSve2Hog.cpp +++ b/src/Simd/SimdSve2Hog.cpp @@ -23,82 +23,18 @@ */ #include "Simd/SimdArray.h" #include "Simd/SimdMemory.h" -#include "Simd/SimdBase.h" namespace Simd { #ifdef SIMD_SVE2_ENABLE namespace Sve2 { - namespace - { - struct Buffer - { - const int size; - float* cos; - float* sin; - int* index; - float* value; - - Buffer(size_t width, size_t quantization) - : size((int)quantization / 2) - { - _p = Allocate(width * (sizeof(int) + sizeof(float)) + sizeof(float) * 2 * size); - index = (int*)_p; - value = (float*)index + width; - cos = value + width; - sin = cos + size; - for (int i = 0; i < size; ++i) - { - cos[i] = (float)::cos(i * M_PI / size); - sin[i] = (float)::sin(i * M_PI / size); - } - } - - ~Buffer() - { - Free(_p); - } - - private: - void* _p; - }; - } - SIMD_INLINE svbool_t HogTailMask(size_t col, size_t end, const svuint32_t& offsets) { const svbool_t mask = svptrue_b32(); return svcmplt_n_u32(mask, svadd_n_u32_x(mask, offsets, (uint32_t)col), (uint32_t)end); } - SIMD_INLINE void HogDirectionHistograms32(const svint32_t& dx, const svint32_t& dy, Buffer& buffer, size_t col, const svuint32_t& offsets, const svbool_t& mask) - { - svfloat32_t _dx = svcvt_f32_s32_x(mask, dx); - svfloat32_t _dy = svcvt_f32_s32_x(mask, dy); - svfloat32_t bestDot = svdup_n_f32(0.0f); - svint32_t bestIndex = svdup_n_s32(0); - for (int i = 0; i < buffer.size; ++i) - { - svfloat32_t dot = svmla_f32_x(mask, svmul_n_f32_x(mask, _dx, buffer.cos[i]), _dy, svdup_n_f32(buffer.sin[i])); - svbool_t positive = svcmpgt_f32(mask, dot, bestDot); - bestDot = svmax_f32_x(mask, dot, bestDot); - bestIndex = svsel_s32(positive, svdup_n_s32(i), bestIndex); - - dot = svneg_f32_x(mask, dot); - svbool_t negative = svcmpgt_f32(mask, dot, bestDot); - bestDot = svmax_f32_x(mask, dot, bestDot); - bestIndex = svsel_s32(negative, svdup_n_s32(buffer.size + i), bestIndex); - } - svst1_scatter_u32index_s32(mask, buffer.index + col, offsets, bestIndex); - svst1_scatter_u32index_f32(mask, buffer.value + col, offsets, svsqrt_f32_x(mask, svmla_f32_x(mask, svmul_f32_x(mask, _dx, _dx), _dy, _dy))); - } - - SIMD_INLINE void HogDirectionHistograms16(const svint16_t& dx, const svint16_t& dy, Buffer& buffer, size_t col, const svuint32_t& loOffsets, const svuint32_t& hiOffsets, const svbool_t& maskLo, const svbool_t& maskHi) - { - HogDirectionHistograms32(svmovlb_s32(dx), svmovlb_s32(dy), buffer, col, loOffsets, maskLo); - HogDirectionHistograms32(svmovlt_s32(dx), svmovlt_s32(dy), buffer, col, hiOffsets, maskHi); - } - SIMD_INLINE svint16_t HogDifferenceLo(const svuint8_t& a, const svuint8_t& b) { svbool_t mask = svptrue_b16(); @@ -111,41 +47,6 @@ namespace Simd return svsub_s16_x(mask, svreinterpret_s16_u16(svmovlt_u16(a)), svreinterpret_s16_u16(svmovlt_u16(b))); } - SIMD_INLINE void HogDirectionHistograms(const uint8_t* src, size_t stride, Buffer& buffer, size_t col, size_t end) - { - const uint8_t* s = src + col; - svbool_t mask = svwhilelt_b8(col, end); - const svuint32_t offsets0 = svindex_u32(0, 4); - const svuint32_t offsets1 = svindex_u32(2, 4); - const svuint32_t offsets2 = svindex_u32(1, 4); - const svuint32_t offsets3 = svindex_u32(3, 4); - svuint8_t t = svld1_u8(mask, s - stride); - svuint8_t l = svld1_u8(mask, s - 1); - svuint8_t r = svld1_u8(mask, s + 1); - svuint8_t b = svld1_u8(mask, s + stride); - HogDirectionHistograms16(HogDifferenceLo(r, l), HogDifferenceLo(b, t), buffer, col, offsets0, offsets1, HogTailMask(col, end, offsets0), HogTailMask(col, end, offsets1)); - HogDirectionHistograms16(HogDifferenceHi(r, l), HogDifferenceHi(b, t), buffer, col, offsets2, offsets3, HogTailMask(col, end, offsets2), HogTailMask(col, end, offsets3)); - } - - void HogDirectionHistograms(const uint8_t* src, size_t stride, size_t width, size_t height, - size_t cellX, size_t cellY, size_t quantization, float* histograms) - { - assert(width % cellX == 0 && height % cellY == 0 && quantization % 2 == 0); - - Buffer buffer(width, quantization); - - memset(histograms, 0, quantization * (width / cellX) * (height / cellY) * sizeof(float)); - - size_t A = svcntb(), end = width - 1; - for (size_t row = 1; row < height - 1; ++row) - { - const uint8_t* s = src + stride * row; - for (size_t col = 1; col < end; col += A) - HogDirectionHistograms(s, stride, buffer, col, end); - Base::AddRowToHistograms(buffer.index, buffer.value, row, width, height, cellX, cellY, quantization, histograms); - } - } - class HogFeatureExtractor { static const size_t C = 8; diff --git a/src/Test/Test.cpp b/src/Test/Test.cpp index 4d3662bfe9..7fd4588843 100644 --- a/src/Test/Test.cpp +++ b/src/Test/Test.cpp @@ -249,7 +249,6 @@ namespace Test TEST_ADD_GROUP_A0(AbsSecondDerivativeHistogram); TEST_ADD_GROUP_A0(ChangeColors); - TEST_ADD_GROUP_A0(HogDirectionHistograms); TEST_ADD_GROUP_A0(HogExtractFeatures); TEST_ADD_GROUP_A0(HogDeinterleave); TEST_ADD_GROUP_A0(HogFilterSeparable); diff --git a/src/Test/TestHog.cpp b/src/Test/TestHog.cpp index 62af977ca5..d31fcd574e 100644 --- a/src/Test/TestHog.cpp +++ b/src/Test/TestHog.cpp @@ -38,98 +38,6 @@ namespace Test { - namespace - { - struct FuncHDH - { - typedef void(*FuncPtr)(const uint8_t * src, size_t stride, size_t width, size_t height, - size_t cellX, size_t cellY, size_t quantization, float * histograms); - - FuncPtr func; - String description; - - FuncHDH(const FuncPtr & f, const String & d) : func(f), description(d) {} - - void Call(const View & src, const Point & cell, size_t quantization, float * histograms) const - { - TEST_PERFORMANCE_TEST(description); - func(src.data, src.stride, src.width, src.height, cell.x, cell.y, quantization, histograms); - } - }; - } - -#define FUNC_HDH(function) FuncHDH(function, #function) - - bool HogDirectionHistogramsAutoTest(const Point & cell, const Point & size, size_t quantization, const FuncHDH & f1, const FuncHDH & f2) - { - bool result = true; - - TEST_LOG_SS(Info, "Test " << f1.description << " & " << f2.description << " [" << size.x*cell.x << ", " << size.y*cell.y << "]."); - - View s(int(size.x*cell.x), int(size.y*cell.y), View::Gray8, NULL, TEST_ALIGN(size.x*cell.x)); - FillRandom(s); - - const size_t _size = quantization*size.x*size.y; - Buffer32f h1(_size, 0), h2(_size, 0); - - TEST_EXECUTE_AT_LEAST_MIN_TIME(f1.Call(s, cell, quantization, h1.data())); - - TEST_EXECUTE_AT_LEAST_MIN_TIME(f2.Call(s, cell, quantization, h2.data())); - - result = result && Compare(h1, h2, EPS, true, 32); - - return result; - } - - bool HogDirectionHistogramsAutoTest(const FuncHDH & f1, const FuncHDH & f2) - { - bool result = true; - - const size_t C = 8; - Point c(C, C), s(W / C, H / C); - const size_t q = 18; - - result = result && HogDirectionHistogramsAutoTest(c, s, q, f1, f2); - result = result && HogDirectionHistogramsAutoTest(c, s + Point(1, 1), q, f1, f2); - - return result; - } - - bool HogDirectionHistogramsAutoTest(const Options & options) - { - bool result = true; - - if (TestBase(options)) - result = result && HogDirectionHistogramsAutoTest(FUNC_HDH(Simd::Base::HogDirectionHistograms), FUNC_HDH(SimdHogDirectionHistograms)); - -#ifdef SIMD_SSE41_ENABLE - if (Simd::Sse41::Enable && TestSse41(options) && W >= Simd::Sse41::A + 2) - result = result && HogDirectionHistogramsAutoTest(FUNC_HDH(Simd::Sse41::HogDirectionHistograms), FUNC_HDH(SimdHogDirectionHistograms)); -#endif - -#ifdef SIMD_AVX2_ENABLE - if (Simd::Avx2::Enable && TestAvx2(options) && W >= Simd::Avx2::A + 2) - result = result && HogDirectionHistogramsAutoTest(FUNC_HDH(Simd::Avx2::HogDirectionHistograms), FUNC_HDH(SimdHogDirectionHistograms)); -#endif - -#ifdef SIMD_AVX512BW_ENABLE - if (Simd::Avx512bw::Enable && TestAvx512bw(options) && W >= Simd::Avx512bw::HA + 2) - result = result && HogDirectionHistogramsAutoTest(FUNC_HDH(Simd::Avx512bw::HogDirectionHistograms), FUNC_HDH(SimdHogDirectionHistograms)); -#endif - -#ifdef SIMD_SVE2_ENABLE - if (Simd::Sve2::Enable && TestSve2(options) && W >= svcntb() + 2) - result = result && HogDirectionHistogramsAutoTest(FUNC_HDH(Simd::Sve2::HogDirectionHistograms), FUNC_HDH(SimdHogDirectionHistograms)); -#endif - -#ifdef SIMD_NEON_ENABLE - if (Simd::Neon::Enable && TestNeon(options) && W >= Simd::Neon::A + 2) - result = result && HogDirectionHistogramsAutoTest(FUNC_HDH(Simd::Neon::HogDirectionHistograms), FUNC_HDH(SimdHogDirectionHistograms)); -#endif - - return result; - } - namespace { struct FuncHEF