Merge pull request #13679 from alalek:imgproc_median_blur_cleanup

* imgproc: cleanup medianBlur_8u_O1 code

Unnecessary per-channel buffers: H[c] / lut[c]

* imgproc(medianBlur_8u_O1): use CV_SIMD_WIDTH for alignment
pull/13722/head
Alexander Alekhin 6 years ago committed by GitHub
parent d998e70a25
commit 5916ebf500
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 92
      modules/imgproc/src/median_blur.cpp

@ -110,15 +110,19 @@ medianBlur_8u_O1( const Mat& _src, Mat& _dst, int ksize )
int cn = _dst.channels(), m = _dst.rows, r = (ksize-1)/2;
CV_Assert(cn > 0 && cn <= 4);
size_t sstep = _src.step, dstep = _dst.step;
Histogram CV_DECL_ALIGNED(16) H[4];
HT CV_DECL_ALIGNED(16) luc[4][16];
int STRIPE_SIZE = std::min( _dst.cols, 512/cn );
std::vector<HT> _h_coarse(1 * 16 * (STRIPE_SIZE + 2*r) * cn + 16);
std::vector<HT> _h_fine(16 * 16 * (STRIPE_SIZE + 2*r) * cn + 16);
HT* h_coarse = alignPtr(&_h_coarse[0], 16);
HT* h_fine = alignPtr(&_h_fine[0], 16);
#if defined(CV_SIMD_WIDTH) && CV_SIMD_WIDTH >= 16
# define CV_ALIGNMENT CV_SIMD_WIDTH
#else
# define CV_ALIGNMENT 16
#endif
std::vector<HT> _h_coarse(1 * 16 * (STRIPE_SIZE + 2*r) * cn + CV_ALIGNMENT);
std::vector<HT> _h_fine(16 * 16 * (STRIPE_SIZE + 2*r) * cn + CV_ALIGNMENT);
HT* h_coarse = alignPtr(&_h_coarse[0], CV_ALIGNMENT);
HT* h_fine = alignPtr(&_h_fine[0], CV_ALIGNMENT);
for( int x = 0; x < _dst.cols; x += STRIPE_SIZE )
{
@ -148,10 +152,14 @@ medianBlur_8u_O1( const Mat& _src, Mat& _dst, int ksize )
const uchar* p0 = src + sstep * std::max( 0, i-r-1 );
const uchar* p1 = src + sstep * std::min( m-1, i+r );
memset( H, 0, cn*sizeof(H[0]) );
memset( luc, 0, cn*sizeof(luc[0]) );
for( c = 0; c < cn; c++ )
{
Histogram CV_DECL_ALIGNED(CV_ALIGNMENT) H;
HT CV_DECL_ALIGNED(CV_ALIGNMENT) luc[16];
memset(&H, 0, sizeof(H));
memset(luc, 0, sizeof(luc));
// Update column histograms for the entire row.
for( j = 0; j < n; j++ )
{
@ -163,21 +171,21 @@ medianBlur_8u_O1( const Mat& _src, Mat& _dst, int ksize )
for (k = 0; k < 16; ++k)
{
#if CV_SIMD256
v_store(H[c].fine[k], v_mul_wrap(v256_load(h_fine + 16 * n*(16 * c + k)), v256_setall_u16(2 * r + 1)) + v256_load(H[c].fine[k]));
v_store(H.fine[k], v_mul_wrap(v256_load(h_fine + 16 * n*(16 * c + k)), v256_setall_u16(2 * r + 1)) + v256_load(H.fine[k]));
#elif CV_SIMD128
v_store(H[c].fine[k], v_mul_wrap(v_load(h_fine + 16 * n*(16 * c + k)), v_setall_u16((ushort)(2 * r + 1))) + v_load(H[c].fine[k]));
v_store(H[c].fine[k] + 8, v_mul_wrap(v_load(h_fine + 16 * n*(16 * c + k) + 8), v_setall_u16((ushort)(2 * r + 1))) + v_load(H[c].fine[k] + 8));
v_store(H.fine[k], v_mul_wrap(v_load(h_fine + 16 * n*(16 * c + k)), v_setall_u16((ushort)(2 * r + 1))) + v_load(H.fine[k]));
v_store(H.fine[k] + 8, v_mul_wrap(v_load(h_fine + 16 * n*(16 * c + k) + 8), v_setall_u16((ushort)(2 * r + 1))) + v_load(H.fine[k] + 8));
#else
for (int ind = 0; ind < 16; ++ind)
H[c].fine[k][ind] = (HT)(H[c].fine[k][ind] + (2 * r + 1) * h_fine[16 * n*(16 * c + k) + ind]);
H.fine[k][ind] = (HT)(H.fine[k][ind] + (2 * r + 1) * h_fine[16 * n*(16 * c + k) + ind]);
#endif
}
#if CV_SIMD256
v_uint16x16 v_coarse = v256_load(H[c].coarse);
v_uint16x16 v_coarse = v256_load(H.coarse);
#elif CV_SIMD128
v_uint16x8 v_coarsel = v_load(H[c].coarse);
v_uint16x8 v_coarseh = v_load(H[c].coarse + 8);
v_uint16x8 v_coarsel = v_load(H.coarse);
v_uint16x8 v_coarseh = v_load(H.coarse + 8);
#endif
HT* px = h_coarse + 16 * n*c;
for( j = 0; j < 2*r; ++j, px += 16 )
@ -189,7 +197,7 @@ medianBlur_8u_O1( const Mat& _src, Mat& _dst, int ksize )
v_coarseh += v_load(px + 8);
#else
for (int ind = 0; ind < 16; ++ind)
H[c].coarse[ind] += px[ind];
H.coarse[ind] += px[ind];
#endif
}
@ -201,24 +209,24 @@ medianBlur_8u_O1( const Mat& _src, Mat& _dst, int ksize )
px = h_coarse + 16 * (n*c + std::min(j + r, n - 1));
#if CV_SIMD256
v_coarse += v256_load(px);
v_store(H[c].coarse, v_coarse);
v_store(H.coarse, v_coarse);
#elif CV_SIMD128
v_coarsel += v_load(px);
v_coarseh += v_load(px + 8);
v_store(H[c].coarse, v_coarsel);
v_store(H[c].coarse + 8, v_coarseh);
v_store(H.coarse, v_coarsel);
v_store(H.coarse + 8, v_coarseh);
#else
for (int ind = 0; ind < 16; ++ind)
H[c].coarse[ind] += px[ind];
H.coarse[ind] += px[ind];
#endif
// Find median at coarse level
for ( k = 0; k < 16 ; ++k )
{
sum += H[c].coarse[k];
sum += H.coarse[k];
if ( sum > t )
{
sum -= H[c].coarse[k];
sum -= H.coarse[k];
break;
}
}
@ -231,7 +239,7 @@ medianBlur_8u_O1( const Mat& _src, Mat& _dst, int ksize )
v_uint16x8 v_finel;
v_uint16x8 v_fineh;
#endif
if ( luc[c][k] <= j-r )
if ( luc[k] <= j-r )
{
#if CV_SIMD256
v_fine = v256_setzero_u16();
@ -239,10 +247,10 @@ medianBlur_8u_O1( const Mat& _src, Mat& _dst, int ksize )
v_finel = v_setzero_u16();
v_fineh = v_setzero_u16();
#else
memset(&H[c].fine[k], 0, 16 * sizeof(HT));
memset(&H.fine[k], 0, 16 * sizeof(HT));
#endif
px = h_fine + 16 * (n*(16 * c + k) + j - r);
for (luc[c][k] = HT(j - r); luc[c][k] < MIN(j + r + 1, n); ++luc[c][k], px += 16)
for (luc[k] = HT(j - r); luc[k] < MIN(j + r + 1, n); ++luc[k], px += 16)
{
#if CV_SIMD256
v_fine += v256_load(px);
@ -251,11 +259,11 @@ medianBlur_8u_O1( const Mat& _src, Mat& _dst, int ksize )
v_fineh += v_load(px + 8);
#else
for (int ind = 0; ind < 16; ++ind)
H[c].fine[k][ind] += px[ind];
H.fine[k][ind] += px[ind];
#endif
}
if ( luc[c][k] < j+r+1 )
if ( luc[k] < j+r+1 )
{
px = h_fine + 16 * (n*(16 * c + k) + (n - 1));
#if CV_SIMD256
@ -265,50 +273,50 @@ medianBlur_8u_O1( const Mat& _src, Mat& _dst, int ksize )
v_fineh += v_mul_wrap(v_load(px + 8), v_setall_u16((ushort)(j + r + 1 - n)));
#else
for (int ind = 0; ind < 16; ++ind)
H[c].fine[k][ind] = (HT)(H[c].fine[k][ind] + (j + r + 1 - n) * px[ind]);
H.fine[k][ind] = (HT)(H.fine[k][ind] + (j + r + 1 - n) * px[ind]);
#endif
luc[c][k] = (HT)(j+r+1);
luc[k] = (HT)(j+r+1);
}
}
else
{
#if CV_SIMD256
v_fine = v256_load(H[c].fine[k]);
v_fine = v256_load(H.fine[k]);
#elif CV_SIMD128
v_finel = v_load(H[c].fine[k]);
v_fineh = v_load(H[c].fine[k] + 8);
v_finel = v_load(H.fine[k]);
v_fineh = v_load(H.fine[k] + 8);
#endif
px = h_fine + 16*n*(16 * c + k);
for ( ; luc[c][k] < j+r+1; ++luc[c][k] )
for ( ; luc[k] < j+r+1; ++luc[k] )
{
#if CV_SIMD256
v_fine = v_fine + v256_load(px + 16 * MIN(luc[c][k], n - 1)) - v256_load(px + 16 * MAX(luc[c][k] - 2 * r - 1, 0));
v_fine = v_fine + v256_load(px + 16 * MIN(luc[k], n - 1)) - v256_load(px + 16 * MAX(luc[k] - 2 * r - 1, 0));
#elif CV_SIMD128
v_finel = v_finel + v_load(px + 16 * MIN(luc[c][k], n - 1) ) - v_load(px + 16 * MAX(luc[c][k] - 2 * r - 1, 0));
v_fineh = v_fineh + v_load(px + 16 * MIN(luc[c][k], n - 1) + 8) - v_load(px + 16 * MAX(luc[c][k] - 2 * r - 1, 0) + 8);
v_finel = v_finel + v_load(px + 16 * MIN(luc[k], n - 1) ) - v_load(px + 16 * MAX(luc[k] - 2 * r - 1, 0));
v_fineh = v_fineh + v_load(px + 16 * MIN(luc[k], n - 1) + 8) - v_load(px + 16 * MAX(luc[k] - 2 * r - 1, 0) + 8);
#else
for (int ind = 0; ind < 16; ++ind)
H[c].fine[k][ind] += px[16 * MIN(luc[c][k], n - 1) + ind] - px[16 * MAX(luc[c][k] - 2 * r - 1, 0) + ind];
H.fine[k][ind] += px[16 * MIN(luc[k], n - 1) + ind] - px[16 * MAX(luc[k] - 2 * r - 1, 0) + ind];
#endif
}
}
px = h_coarse + 16 * (n*c + MAX(j - r, 0));
#if CV_SIMD256
v_store(H[c].fine[k], v_fine);
v_store(H.fine[k], v_fine);
v_coarse -= v256_load(px);
#elif CV_SIMD128
v_store(H[c].fine[k], v_finel);
v_store(H[c].fine[k] + 8, v_fineh);
v_store(H.fine[k], v_finel);
v_store(H.fine[k] + 8, v_fineh);
v_coarsel -= v_load(px);
v_coarseh -= v_load(px + 8);
#else
for (int ind = 0; ind < 16; ++ind)
H[c].coarse[ind] -= px[ind];
H.coarse[ind] -= px[ind];
#endif
/* Find median in segment */
segment = H[c].fine[k];
segment = H.fine[k];
for ( b = 0; b < 16 ; b++ )
{
sum += segment[b];

Loading…
Cancel
Save