Unverified Commit 5916ebf5 authored by Alexander Alekhin's avatar Alexander Alekhin Committed by GitHub

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