diff --git a/modules/imgproc/src/histogram.cpp b/modules/imgproc/src/histogram.cpp index 123cb83556..a966c45aff 100644 --- a/modules/imgproc/src/histogram.cpp +++ b/modules/imgproc/src/histogram.cpp @@ -260,16 +260,74 @@ calcHist_( std::vector& _ptrs, const std::vector& _deltas, for( ; imsize.height--; p0 += step0, mask += mstep ) { if( !mask ) - for( x = 0; x < imsize.width; x++, p0 += d0 ) + { +#if (CV_SIMD || CV_SIMD_SCALABLE) + if( d0 == 1 && sizeof(T) == 2 ) { - double v0 = (double)*p0; - int idx = cvFloor(v0*a + b); - if (v0 < v0_lo || v0 >= v0_hi) - continue; - idx = CV_CLAMP_INT(idx, 0, sz - 1); - CV_DbgAssert((unsigned)idx < (unsigned)sz); - ((int*)H)[idx]++; + const ushort* p = (const ushort*)p0; + const int nlanes = VTraits::vlanes(); + + const v_float32 va = vx_setall_f32((float)a); + const v_float32 vb = vx_setall_f32((float)b); + const v_float32 vlo = vx_setall_f32((float)v0_lo); + const v_float32 vhi = vx_setall_f32((float)v0_hi); + const v_int32 vi0 = vx_setall_s32(0); + const v_int32 visz = vx_setall_s32(sz - 1); + + x = 0; + for( ; x <= imsize.width - nlanes; x += nlanes ) + { + v_uint16 pix = vx_load(&p[x]); + v_uint32 lo32, hi32; + v_expand(pix, lo32, hi32); + v_float32 flo = v_cvt_f32(v_reinterpret_as_s32(lo32)); + v_float32 fhi = v_cvt_f32(v_reinterpret_as_s32(hi32)); + v_uint32 rlo = v_reinterpret_as_u32(v_and(v_ge(flo, vlo), v_lt(flo, vhi))); + v_uint32 rhi = v_reinterpret_as_u32(v_and(v_ge(fhi, vlo), v_lt(fhi, vhi))); + + v_int32 idx_lo = v_max(vi0, v_min(visz, v_floor(v_fma(flo, va, vb)))); + v_int32 idx_hi = v_max(vi0, v_min(visz, v_floor(v_fma(fhi, va, vb)))); + + int idxbuf[2 * VTraits::max_nlanes]; + v_store(idxbuf, idx_lo); + v_store(idxbuf + nlanes / 2, idx_hi); + + if( v_check_all(v_reinterpret_as_s32(rlo)) && v_check_all(v_reinterpret_as_s32(rhi)) ) + { + for( int k = 0; k < nlanes; k++ ) + ((int*)H)[idxbuf[k]]++; + } + else + { + int deltabuf[2 * VTraits::max_nlanes]; + v_store(deltabuf, v_reinterpret_as_s32(rlo)); + v_store(deltabuf + nlanes / 2, v_reinterpret_as_s32(rhi)); + for( int k = 0; k < nlanes; k++ ) + ((int*)H)[idxbuf[k]] += (deltabuf[k] != 0); + } + } + for( ; x < imsize.width; x++ ) + { + double v0 = (double)p[x]; + int delta = int(v0_lo <= v0) & int(v0 < v0_hi); + int idx = CV_CLAMP_INT(cvFloor(v0*a + b), 0, sz-1); + ((int*)H)[idx] += delta; + } + p0 = (const T*)(p + imsize.width); } + else +#endif + for( x = 0; x < imsize.width; x++, p0 += d0 ) + { + double v0 = (double)*p0; + int idx = cvFloor(v0*a + b); + if (v0 < v0_lo || v0 >= v0_hi) + continue; + idx = CV_CLAMP_INT(idx, 0, sz - 1); + CV_DbgAssert((unsigned)idx < (unsigned)sz); + ((int*)H)[idx]++; + } + } else for( x = 0; x < imsize.width; x++, p0 += d0 ) if( mask[x] )