Update 16UC thresholding

This commit is contained in:
Dmitry Kurtaev 2017-09-18 15:42:44 +03:00
parent ca245e995a
commit fa109b94d9
2 changed files with 304 additions and 401 deletions

View File

@ -49,6 +49,78 @@
namespace cv namespace cv
{ {
template <typename T>
static inline T threshBinary(const T& src, const T& thresh, const T& maxval)
{
return src > thresh ? maxval : 0;
}
template <typename T>
static inline T threshBinaryInv(const T& src, const T& thresh, const T& maxval)
{
return src <= thresh ? maxval : 0;
}
template <typename T>
static inline T threshTrunc(const T& src, const T& thresh)
{
return std::min(src, thresh);
}
template <typename T>
static inline T threshToZero(const T& src, const T& thresh)
{
return src > thresh ? src : 0;
}
template <typename T>
static inline T threshToZeroInv(const T& src, const T& thresh)
{
return src <= thresh ? src : 0;
}
template <typename T>
static void threshGeneric(Size roi, const T* src, size_t src_step, T* dst,
size_t dst_step, T thresh, T maxval, int type)
{
int i = 0, j;
switch (type)
{
case THRESH_BINARY:
for (; i < roi.height; i++, src += src_step, dst += dst_step)
for (j = 0; j < roi.width; j++)
dst[j] = threshBinary<T>(src[j], thresh, maxval);
return;
case THRESH_BINARY_INV:
for (; i < roi.height; i++, src += src_step, dst += dst_step)
for (j = 0; j < roi.width; j++)
dst[j] = threshBinaryInv<T>(src[j], thresh, maxval);
return;
case THRESH_TRUNC:
for (; i < roi.height; i++, src += src_step, dst += dst_step)
for (j = 0; j < roi.width; j++)
dst[j] = threshTrunc<T>(src[j], thresh);
return;
case THRESH_TOZERO:
for (; i < roi.height; i++, src += src_step, dst += dst_step)
for (j = 0; j < roi.width; j++)
dst[j] = threshToZero<T>(src[j], thresh);
return;
case THRESH_TOZERO_INV:
for (; i < roi.height; i++, src += src_step, dst += dst_step)
for (j = 0; j < roi.width; j++)
dst[j] = threshToZeroInv<T>(src[j], thresh);
return;
default:
CV_Error( CV_StsBadArg, "" ); return;
}
}
static void static void
thresh_8u( const Mat& _src, Mat& _dst, uchar thresh, uchar maxval, int type ) thresh_8u( const Mat& _src, Mat& _dst, uchar thresh, uchar maxval, int type )
{ {
@ -272,206 +344,148 @@ thresh_8u( const Mat& _src, Mat& _dst, uchar thresh, uchar maxval, int type )
static void static void
thresh_16u(const Mat& _src, Mat& _dst, ushort thresh, ushort maxval, int type) thresh_16u(const Mat& _src, Mat& _dst, ushort thresh, ushort maxval, int type)
{ {
Size roi = _src.size(); Size roi = _src.size();
roi.width *= _src.channels(); roi.width *= _src.channels();
size_t src_step = _src.step; size_t src_step = _src.step / _src.elemSize1();
size_t dst_step = _dst.step; size_t dst_step = _dst.step / _dst.elemSize1();
if (_src.isContinuous() && _dst.isContinuous()) if (_src.isContinuous() && _dst.isContinuous())
{ {
roi.width *= roi.height; roi.width *= roi.height;
roi.height = 1; roi.height = 1;
src_step = dst_step = roi.width; src_step = dst_step = roi.width;
} }
// HAVE_TEGRA_OPTIMIZATION not supported // HAVE_TEGRA_OPTIMIZATION not supported
// HAVE_IPP not supported // HAVE_IPP not supported
int j = 0; const ushort* src = _src.ptr<ushort>();
const ushort* src = _src.ptr<ushort>(); ushort* dst = _dst.ptr<ushort>();
ushort* dst = _dst.ptr<ushort>();
// CV_SIMD128 not supported
#if CV_SIMD128 #if CV_SIMD128
bool useSIMD = checkHardwareSupport(CV_CPU_SSE2) || checkHardwareSupport(CV_CPU_NEON); bool useSIMD = checkHardwareSupport(CV_CPU_SSE2) || checkHardwareSupport(CV_CPU_NEON);
if (useSIMD) if (useSIMD)
{ {
int i; int i, j;
v_uint16x8 thresh_u = v_setall_u16(thresh); v_uint16x8 thresh_u = v_setall_u16(thresh);
v_uint16x8 maxval16 = v_setall_u16(maxval); v_uint16x8 maxval16 = v_setall_u16(maxval);
switch (type) switch (type)
{ {
case THRESH_BINARY: case THRESH_BINARY:
for (i = 0; i < roi.height; i++, src += src_step, dst += dst_step) for (i = 0; i < roi.height; i++, src += src_step, dst += dst_step)
{ {
for (j = 0; j <= roi.width - 16; j += 16) for (j = 0; j <= roi.width - 16; j += 16)
{ {
v_uint16x8 v0, v1; v_uint16x8 v0, v1;
v0 = v_load(src + j); v0 = v_load(src + j);
v1 = v_load(src + j + 8); v1 = v_load(src + j + 8);
v0 = thresh_u < v0; v0 = thresh_u < v0;
v1 = thresh_u < v1; v1 = thresh_u < v1;
v0 = v0 & maxval16; v0 = v0 & maxval16;
v1 = v1 & maxval16; v1 = v1 & maxval16;
v_store(dst + j, v0); v_store(dst + j, v0);
v_store(dst + j + 8, v1); v_store(dst + j + 8, v1);
} }
}
break;
case THRESH_BINARY_INV: for (; j < roi.width; j++)
for (i = 0; i < roi.height; i++, src += src_step, dst += dst_step) dst[j] = threshBinary<ushort>(src[j], thresh, maxval);
{ }
j = 0; break;
for (; j <= roi.width - 16; j += 16)
{
v_uint16x8 v0, v1;
v0 = v_load(src + j);
v1 = v_load(src + j + 8);
v0 = v0 <= thresh_u;
v1 = v1 <= thresh_u;
v0 = v0 & maxval16;
v1 = v1 & maxval16;
v_store(dst + j, v0);
v_store(dst + j + 8, v1);
}
for (; j < roi.width; j++) case THRESH_BINARY_INV:
dst[j] = src[j] <= thresh ? maxval : 0; for (i = 0; i < roi.height; i++, src += src_step, dst += dst_step)
} {
break; j = 0;
for (; j <= roi.width - 16; j += 16)
{
v_uint16x8 v0, v1;
v0 = v_load(src + j);
v1 = v_load(src + j + 8);
v0 = v0 <= thresh_u;
v1 = v1 <= thresh_u;
v0 = v0 & maxval16;
v1 = v1 & maxval16;
v_store(dst + j, v0);
v_store(dst + j + 8, v1);
}
case THRESH_TRUNC: for (; j < roi.width; j++)
for (i = 0; i < roi.height; i++, src += src_step, dst += dst_step) dst[j] = threshBinaryInv<ushort>(src[j], thresh, maxval);
{ }
j = 0; break;
for (; j <= roi.width - 16; j += 16)
{
v_uint16x8 v0, v1;
v0 = v_load(src + j);
v1 = v_load(src + j + 8);
v0 = v_min(v0, thresh_u);
v1 = v_min(v1, thresh_u);
v_store(dst + j, v0);
v_store(dst + j + 8, v1);
}
for (; j < roi.width; j++) case THRESH_TRUNC:
dst[j] = std::min(src[j], thresh); for (i = 0; i < roi.height; i++, src += src_step, dst += dst_step)
} {
break; j = 0;
for (; j <= roi.width - 16; j += 16)
{
v_uint16x8 v0, v1;
v0 = v_load(src + j);
v1 = v_load(src + j + 8);
v0 = v_min(v0, thresh_u);
v1 = v_min(v1, thresh_u);
v_store(dst + j, v0);
v_store(dst + j + 8, v1);
}
case THRESH_TOZERO: for (; j < roi.width; j++)
for (i = 0; i < roi.height; i++, src += src_step, dst += dst_step) dst[j] = threshTrunc<ushort>(src[j], thresh);
{ }
j = 0; break;
for (; j <= roi.width - 16; j += 16)
{
v_uint16x8 v0, v1;
v0 = v_load(src + j);
v1 = v_load(src + j + 8);
v0 = (thresh_u < v0) & v0;
v1 = (thresh_u < v1) & v1;
v_store(dst + j, v0);
v_store(dst + j + 8, v1);
}
for (; j < roi.width; j++) case THRESH_TOZERO:
{ for (i = 0; i < roi.height; i++, src += src_step, dst += dst_step)
short v = src[j]; {
dst[j] = v > thresh ? v : 0; j = 0;
} for (; j <= roi.width - 16; j += 16)
} {
break; v_uint16x8 v0, v1;
v0 = v_load(src + j);
v1 = v_load(src + j + 8);
v0 = (thresh_u < v0) & v0;
v1 = (thresh_u < v1) & v1;
v_store(dst + j, v0);
v_store(dst + j + 8, v1);
}
case THRESH_TOZERO_INV: for (; j < roi.width; j++)
for (i = 0; i < roi.height; i++, src += src_step, dst += dst_step) dst[j] = threshToZero<ushort>(src[j], thresh);
{ }
j = 0; break;
for (; j <= roi.width - 16; j += 16)
{
v_uint16x8 v0, v1;
v0 = v_load(src + j);
v1 = v_load(src + j + 8);
v0 = (v0 <= thresh_u) & v0;
v1 = (v1 <= thresh_u) & v1;
v_store(dst + j, v0);
v_store(dst + j + 8, v1);
}
for (; j < roi.width; j++) case THRESH_TOZERO_INV:
{ for (i = 0; i < roi.height; i++, src += src_step, dst += dst_step)
short v = src[j]; {
dst[j] = v <= thresh ? v : 0; j = 0;
} for (; j <= roi.width - 16; j += 16)
} {
break; v_uint16x8 v0, v1;
} v0 = v_load(src + j);
} v1 = v_load(src + j + 8);
else v0 = (v0 <= thresh_u) & v0;
v1 = (v1 <= thresh_u) & v1;
v_store(dst + j, v0);
v_store(dst + j + 8, v1);
}
for (; j < roi.width; j++)
dst[j] = threshToZeroInv<ushort>(src[j], thresh);
}
break;
}
}
else
#endif #endif
{ {
int i; threshGeneric<ushort>(roi, src, src_step, dst, dst_step, thresh, maxval, type);
switch (type) }
{
case THRESH_BINARY:
for (i = 0; i < roi.height; i++, src += src_step, dst += dst_step)
{
for (j = 0; j < roi.width; j++)
dst[j] = src[j] > thresh ? maxval : 0;
}
break;
case THRESH_BINARY_INV:
for (i = 0; i < roi.height; i++, src += src_step, dst += dst_step)
{
for (j = 0; j < roi.width; j++)
dst[j] = src[j] <= thresh ? maxval : 0;
}
break;
case THRESH_TRUNC:
for (i = 0; i < roi.height; i++, src += src_step, dst += dst_step)
{
for (j = 0; j < roi.width; j++)
dst[j] = std::min(src[j], thresh);
}
break;
case THRESH_TOZERO:
for (i = 0; i < roi.height; i++, src += src_step, dst += dst_step)
{
for (j = 0; j < roi.width; j++)
{
short v = src[j];
dst[j] = v > thresh ? v : 0;
}
}
break;
case THRESH_TOZERO_INV:
for (i = 0; i < roi.height; i++, src += src_step, dst += dst_step)
{
for (j = 0; j < roi.width; j++)
{
short v = src[j];
dst[j] = v <= thresh ? v : 0;
}
}
break;
default:
CV_Error( CV_StsBadArg, "" ); return;
}
}
} }
static void static void
thresh_16s( const Mat& _src, Mat& _dst, short thresh, short maxval, int type ) thresh_16s( const Mat& _src, Mat& _dst, short thresh, short maxval, int type )
{ {
int i, j;
Size roi = _src.size(); Size roi = _src.size();
roi.width *= _src.channels(); roi.width *= _src.channels();
const short* src = _src.ptr<short>(); const short* src = _src.ptr<short>();
@ -546,6 +560,7 @@ thresh_16s( const Mat& _src, Mat& _dst, short thresh, short maxval, int type )
bool useSIMD = checkHardwareSupport( CV_CPU_SSE2 ) || checkHardwareSupport( CV_CPU_NEON ); bool useSIMD = checkHardwareSupport( CV_CPU_SSE2 ) || checkHardwareSupport( CV_CPU_NEON );
if( useSIMD ) if( useSIMD )
{ {
int i, j;
v_int16x8 thresh8 = v_setall_s16( thresh ); v_int16x8 thresh8 = v_setall_s16( thresh );
v_int16x8 maxval8 = v_setall_s16( maxval ); v_int16x8 maxval8 = v_setall_s16( maxval );
@ -569,7 +584,7 @@ thresh_16s( const Mat& _src, Mat& _dst, short thresh, short maxval, int type )
} }
for( ; j < roi.width; j++ ) for( ; j < roi.width; j++ )
dst[j] = src[j] > thresh ? maxval : 0; dst[j] = threshBinary<short>(src[j], thresh, maxval);
} }
break; break;
@ -591,7 +606,7 @@ thresh_16s( const Mat& _src, Mat& _dst, short thresh, short maxval, int type )
} }
for( ; j < roi.width; j++ ) for( ; j < roi.width; j++ )
dst[j] = src[j] <= thresh ? maxval : 0; dst[j] = threshBinaryInv<short>(src[j], thresh, maxval);
} }
break; break;
@ -611,7 +626,7 @@ thresh_16s( const Mat& _src, Mat& _dst, short thresh, short maxval, int type )
} }
for( ; j < roi.width; j++ ) for( ; j < roi.width; j++ )
dst[j] = std::min( src[j], thresh ); dst[j] = threshTrunc<short>( src[j], thresh );
} }
break; break;
@ -631,10 +646,7 @@ thresh_16s( const Mat& _src, Mat& _dst, short thresh, short maxval, int type )
} }
for( ; j < roi.width; j++ ) for( ; j < roi.width; j++ )
{ dst[j] = threshToZero<short>(src[j], thresh);
short v = src[j];
dst[j] = v > thresh ? v : 0;
}
} }
break; break;
@ -654,10 +666,7 @@ thresh_16s( const Mat& _src, Mat& _dst, short thresh, short maxval, int type )
} }
for( ; j < roi.width; j++ ) for( ; j < roi.width; j++ )
{ dst[j] = threshToZeroInv<short>(src[j], thresh);
short v = src[j];
dst[j] = v <= thresh ? v : 0;
}
} }
break; break;
default: default:
@ -667,56 +676,7 @@ thresh_16s( const Mat& _src, Mat& _dst, short thresh, short maxval, int type )
else else
#endif #endif
{ {
switch( type ) threshGeneric<short>(roi, src, src_step, dst, dst_step, thresh, maxval, type);
{
case THRESH_BINARY:
for( i = 0; i < roi.height; i++, src += src_step, dst += dst_step )
{
for( j = 0; j < roi.width; j++ )
dst[j] = src[j] > thresh ? maxval : 0;
}
break;
case THRESH_BINARY_INV:
for( i = 0; i < roi.height; i++, src += src_step, dst += dst_step )
{
for( j = 0; j < roi.width; j++ )
dst[j] = src[j] <= thresh ? maxval : 0;
}
break;
case THRESH_TRUNC:
for( i = 0; i < roi.height; i++, src += src_step, dst += dst_step )
{
for( j = 0; j < roi.width; j++ )
dst[j] = std::min( src[j], thresh );
}
break;
case THRESH_TOZERO:
for( i = 0; i < roi.height; i++, src += src_step, dst += dst_step )
{
for( j = 0; j < roi.width; j++ )
{
short v = src[j];
dst[j] = v > thresh ? v : 0;
}
}
break;
case THRESH_TOZERO_INV:
for( i = 0; i < roi.height; i++, src += src_step, dst += dst_step )
{
for( j = 0; j < roi.width; j++ )
{
short v = src[j];
dst[j] = v <= thresh ? v : 0;
}
}
break;
default:
CV_Error( CV_StsBadArg, "" ); return;
}
} }
} }
@ -724,7 +684,6 @@ thresh_16s( const Mat& _src, Mat& _dst, short thresh, short maxval, int type )
static void static void
thresh_32f( const Mat& _src, Mat& _dst, float thresh, float maxval, int type ) thresh_32f( const Mat& _src, Mat& _dst, float thresh, float maxval, int type )
{ {
int i, j;
Size roi = _src.size(); Size roi = _src.size();
roi.width *= _src.channels(); roi.width *= _src.channels();
const float* src = _src.ptr<float>(); const float* src = _src.ptr<float>();
@ -781,6 +740,7 @@ thresh_32f( const Mat& _src, Mat& _dst, float thresh, float maxval, int type )
bool useSIMD = checkHardwareSupport( CV_CPU_SSE2 ) || checkHardwareSupport( CV_CPU_NEON ); bool useSIMD = checkHardwareSupport( CV_CPU_SSE2 ) || checkHardwareSupport( CV_CPU_NEON );
if( useSIMD ) if( useSIMD )
{ {
int i, j;
v_float32x4 thresh4 = v_setall_f32( thresh ); v_float32x4 thresh4 = v_setall_f32( thresh );
v_float32x4 maxval4 = v_setall_f32( maxval ); v_float32x4 maxval4 = v_setall_f32( maxval );
@ -804,7 +764,7 @@ thresh_32f( const Mat& _src, Mat& _dst, float thresh, float maxval, int type )
} }
for( ; j < roi.width; j++ ) for( ; j < roi.width; j++ )
dst[j] = src[j] > thresh ? maxval : 0; dst[j] = threshBinary<float>(src[j], thresh, maxval);
} }
break; break;
@ -826,7 +786,7 @@ thresh_32f( const Mat& _src, Mat& _dst, float thresh, float maxval, int type )
} }
for( ; j < roi.width; j++ ) for( ; j < roi.width; j++ )
dst[j] = src[j] <= thresh ? maxval : 0; dst[j] = threshBinaryInv<float>(src[j], thresh, maxval);
} }
break; break;
@ -846,7 +806,7 @@ thresh_32f( const Mat& _src, Mat& _dst, float thresh, float maxval, int type )
} }
for( ; j < roi.width; j++ ) for( ; j < roi.width; j++ )
dst[j] = std::min( src[j], thresh ); dst[j] = threshTrunc<float>(src[j], thresh);
} }
break; break;
@ -866,10 +826,7 @@ thresh_32f( const Mat& _src, Mat& _dst, float thresh, float maxval, int type )
} }
for( ; j < roi.width; j++ ) for( ; j < roi.width; j++ )
{ dst[j] = threshToZero<float>(src[j], thresh);
float v = src[j];
dst[j] = v > thresh ? v : 0;
}
} }
break; break;
@ -889,10 +846,7 @@ thresh_32f( const Mat& _src, Mat& _dst, float thresh, float maxval, int type )
} }
for( ; j < roi.width; j++ ) for( ; j < roi.width; j++ )
{ dst[j] = threshToZeroInv<float>(src[j], thresh);
float v = src[j];
dst[j] = v <= thresh ? v : 0;
}
} }
break; break;
default: default:
@ -902,63 +856,13 @@ thresh_32f( const Mat& _src, Mat& _dst, float thresh, float maxval, int type )
else else
#endif #endif
{ {
switch( type ) threshGeneric<float>(roi, src, src_step, dst, dst_step, thresh, maxval, type);
{
case THRESH_BINARY:
for( i = 0; i < roi.height; i++, src += src_step, dst += dst_step )
{
for( j = 0; j < roi.width; j++ )
dst[j] = src[j] > thresh ? maxval : 0;
}
break;
case THRESH_BINARY_INV:
for( i = 0; i < roi.height; i++, src += src_step, dst += dst_step )
{
for( j = 0; j < roi.width; j++ )
dst[j] = src[j] <= thresh ? maxval : 0;
}
break;
case THRESH_TRUNC:
for( i = 0; i < roi.height; i++, src += src_step, dst += dst_step )
{
for( j = 0; j < roi.width; j++ )
dst[j] = std::min( src[j], thresh );
}
break;
case THRESH_TOZERO:
for( i = 0; i < roi.height; i++, src += src_step, dst += dst_step )
{
for( j = 0; j < roi.width; j++ )
{
float v = src[j];
dst[j] = v > thresh ? v : 0;
}
}
break;
case THRESH_TOZERO_INV:
for( i = 0; i < roi.height; i++, src += src_step, dst += dst_step )
{
for( j = 0; j < roi.width; j++ )
{
float v = src[j];
dst[j] = v <= thresh ? v : 0;
}
}
break;
default:
CV_Error( CV_StsBadArg, "" ); return;
}
} }
} }
static void static void
thresh_64f(const Mat& _src, Mat& _dst, double thresh, double maxval, int type) thresh_64f(const Mat& _src, Mat& _dst, double thresh, double maxval, int type)
{ {
int i, j;
Size roi = _src.size(); Size roi = _src.size();
roi.width *= _src.channels(); roi.width *= _src.channels();
const double* src = _src.ptr<double>(); const double* src = _src.ptr<double>();
@ -976,6 +880,7 @@ thresh_64f(const Mat& _src, Mat& _dst, double thresh, double maxval, int type)
bool useSIMD = checkHardwareSupport( CV_CPU_SSE2 ) || checkHardwareSupport( CV_CPU_NEON ); bool useSIMD = checkHardwareSupport( CV_CPU_SSE2 ) || checkHardwareSupport( CV_CPU_NEON );
if( useSIMD ) if( useSIMD )
{ {
int i, j;
v_float64x2 thresh2 = v_setall_f64( thresh ); v_float64x2 thresh2 = v_setall_f64( thresh );
v_float64x2 maxval2 = v_setall_f64( maxval ); v_float64x2 maxval2 = v_setall_f64( maxval );
@ -999,7 +904,7 @@ thresh_64f(const Mat& _src, Mat& _dst, double thresh, double maxval, int type)
} }
for( ; j < roi.width; j++ ) for( ; j < roi.width; j++ )
dst[j] = src[j] > thresh ? maxval : 0; dst[j] = threshBinary<double>(src[j], thresh, maxval);
} }
break; break;
@ -1021,7 +926,7 @@ thresh_64f(const Mat& _src, Mat& _dst, double thresh, double maxval, int type)
} }
for( ; j < roi.width; j++ ) for( ; j < roi.width; j++ )
dst[j] = src[j] <= thresh ? maxval : 0; dst[j] = threshBinaryInv<double>(src[j], thresh, maxval);
} }
break; break;
@ -1041,7 +946,7 @@ thresh_64f(const Mat& _src, Mat& _dst, double thresh, double maxval, int type)
} }
for( ; j < roi.width; j++ ) for( ; j < roi.width; j++ )
dst[j] = std::min( src[j], thresh ); dst[j] = threshTrunc<double>(src[j], thresh);
} }
break; break;
@ -1061,10 +966,7 @@ thresh_64f(const Mat& _src, Mat& _dst, double thresh, double maxval, int type)
} }
for( ; j < roi.width; j++ ) for( ; j < roi.width; j++ )
{ dst[j] = threshToZero<double>(src[j], thresh);
double v = src[j];
dst[j] = v > thresh ? v : 0;
}
} }
break; break;
@ -1084,10 +986,7 @@ thresh_64f(const Mat& _src, Mat& _dst, double thresh, double maxval, int type)
} }
for( ; j < roi.width; j++ ) for( ; j < roi.width; j++ )
{ dst[j] = threshToZeroInv<double>(src[j], thresh);
double v = src[j];
dst[j] = v <= thresh ? v : 0;
}
} }
break; break;
default: default:
@ -1097,61 +996,7 @@ thresh_64f(const Mat& _src, Mat& _dst, double thresh, double maxval, int type)
else else
#endif #endif
{ {
switch( type ) threshGeneric<double>(roi, src, src_step, dst, dst_step, thresh, maxval, type);
{
case THRESH_BINARY:
for( i = 0; i < roi.height; i++, src += src_step, dst += dst_step )
{
j = 0;
for( ; j < roi.width; j++ )
dst[j] = src[j] > thresh ? maxval : 0;
}
break;
case THRESH_BINARY_INV:
for( i = 0; i < roi.height; i++, src += src_step, dst += dst_step )
{
j = 0;
for( ; j < roi.width; j++ )
dst[j] = src[j] <= thresh ? maxval : 0;
}
break;
case THRESH_TRUNC:
for( i = 0; i < roi.height; i++, src += src_step, dst += dst_step )
{
j = 0;
for( ; j < roi.width; j++ )
dst[j] = std::min( src[j], thresh );
}
break;
case THRESH_TOZERO:
for( i = 0; i < roi.height; i++, src += src_step, dst += dst_step )
{
j = 0;
for( ; j < roi.width; j++ )
{
double v = src[j];
dst[j] = v > thresh ? v : 0;
}
}
break;
case THRESH_TOZERO_INV:
for( i = 0; i < roi.height; i++, src += src_step, dst += dst_step )
{
j = 0;
for( ; j < roi.width; j++ )
{
double v = src[j];
dst[j] = v <= thresh ? v : 0;
}
}
break;
default:
CV_Error(CV_StsBadArg, ""); return;
}
} }
} }
@ -1377,7 +1222,7 @@ public:
{ {
thresh_16s( srcStripe, dstStripe, (short)thresh, (short)maxval, thresholdType ); thresh_16s( srcStripe, dstStripe, (short)thresh, (short)maxval, thresholdType );
} }
else if( srcStripe.depth() == CV_16U ) else if( srcStripe.depth() == CV_16U )
{ {
thresh_16u( srcStripe, dstStripe, (ushort)thresh, (ushort)maxval, thresholdType ); thresh_16u( srcStripe, dstStripe, (ushort)thresh, (ushort)maxval, thresholdType );
} }
@ -1624,34 +1469,34 @@ double cv::threshold( InputArray _src, OutputArray _dst, double thresh, double m
thresh = ithresh; thresh = ithresh;
maxval = imaxval; maxval = imaxval;
} }
else if (src.depth() == CV_16U ) else if (src.depth() == CV_16U )
{ {
int ithresh = cvFloor(thresh); int ithresh = cvFloor(thresh);
thresh = ithresh; thresh = ithresh;
int imaxval = cvRound(maxval); int imaxval = cvRound(maxval);
if (type == THRESH_TRUNC) if (type == THRESH_TRUNC)
imaxval = ithresh; imaxval = ithresh;
imaxval = saturate_cast<short>(imaxval); imaxval = saturate_cast<ushort>(imaxval);
int ushrt_min = 0; int ushrt_min = 0;
if (ithresh < ushrt_min || ithresh >= USHRT_MAX) if (ithresh < ushrt_min || ithresh >= USHRT_MAX)
{ {
if (type == THRESH_BINARY || type == THRESH_BINARY_INV || if (type == THRESH_BINARY || type == THRESH_BINARY_INV ||
((type == THRESH_TRUNC || type == THRESH_TOZERO_INV) && ithresh < ushrt_min) || ((type == THRESH_TRUNC || type == THRESH_TOZERO_INV) && ithresh < ushrt_min) ||
(type == THRESH_TOZERO && ithresh >= USHRT_MAX)) (type == THRESH_TOZERO && ithresh >= USHRT_MAX))
{ {
int v = type == THRESH_BINARY ? (ithresh >= USHRT_MAX ? 0 : imaxval) : int v = type == THRESH_BINARY ? (ithresh >= USHRT_MAX ? 0 : imaxval) :
type == THRESH_BINARY_INV ? (ithresh >= USHRT_MAX ? imaxval : 0) : type == THRESH_BINARY_INV ? (ithresh >= USHRT_MAX ? imaxval : 0) :
/*type == THRESH_TRUNC ? imaxval :*/ 0; /*type == THRESH_TRUNC ? imaxval :*/ 0;
dst.setTo(v); dst.setTo(v);
} }
else else
src.copyTo(dst); src.copyTo(dst);
return thresh; return thresh;
} }
thresh = ithresh; thresh = ithresh;
maxval = imaxval; maxval = imaxval;
} }
else if( src.depth() == CV_32F ) else if( src.depth() == CV_32F )
; ;
else if( src.depth() == CV_64F ) else if( src.depth() == CV_64F )

View File

@ -75,9 +75,9 @@ void CV_ThreshTest::get_test_array_types_and_sizes( int test_case_idx,
vector<vector<Size> >& sizes, vector<vector<int> >& types ) vector<vector<Size> >& sizes, vector<vector<int> >& types )
{ {
RNG& rng = ts->get_rng(); RNG& rng = ts->get_rng();
int depth = cvtest::randInt(rng) % 4, cn = cvtest::randInt(rng) % 4 + 1; int depth = cvtest::randInt(rng) % 5, cn = cvtest::randInt(rng) % 4 + 1;
cvtest::ArrayTest::get_test_array_types_and_sizes( test_case_idx, sizes, types ); cvtest::ArrayTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
depth = depth == 0 ? CV_8U : depth == 1 ? CV_16S : depth == 2 ? CV_32F : CV_64F; depth = depth == 0 ? CV_8U : depth == 1 ? CV_16S : depth == 2 ? CV_16U : depth == 3 ? CV_32F : CV_64F;
types[INPUT][0] = types[OUTPUT][0] = types[REF_OUTPUT][0] = CV_MAKETYPE(depth,cn); types[INPUT][0] = types[OUTPUT][0] = types[REF_OUTPUT][0] = CV_MAKETYPE(depth,cn);
thresh_type = cvtest::randInt(rng) % 5; thresh_type = cvtest::randInt(rng) % 5;
@ -98,6 +98,15 @@ void CV_ThreshTest::get_test_array_types_and_sizes( int test_case_idx,
if( cvtest::randInt(rng)%4 == 0 ) if( cvtest::randInt(rng)%4 == 0 )
max_val = (double)SHRT_MAX; max_val = (double)SHRT_MAX;
} }
else if( depth == CV_16U )
{
double min_val = -100.f;
max_val = USHRT_MAX+100.f;
thresh_val = (cvtest::randReal(rng)*(max_val - min_val) + min_val);
max_val = (cvtest::randReal(rng)*(max_val - min_val) + min_val);
if( cvtest::randInt(rng)%4 == 0 )
max_val = (double)USHRT_MAX;
}
else else
{ {
thresh_val = (cvtest::randReal(rng)*1000. - 500.); thresh_val = (cvtest::randReal(rng)*1000. - 500.);
@ -138,13 +147,18 @@ static void test_threshold( const Mat& _src, Mat& _dst,
ithresh2 = saturate_cast<short>(ithresh); ithresh2 = saturate_cast<short>(ithresh);
imaxval = saturate_cast<short>(maxval); imaxval = saturate_cast<short>(maxval);
} }
else if( depth == CV_16U )
{
ithresh2 = saturate_cast<ushort>(ithresh);
imaxval = saturate_cast<ushort>(maxval);
}
else else
{ {
ithresh2 = cvRound(ithresh); ithresh2 = cvRound(ithresh);
imaxval = cvRound(maxval); imaxval = cvRound(maxval);
} }
assert( depth == CV_8U || depth == CV_16S || depth == CV_32F || depth == CV_64F ); assert( depth == CV_8U || depth == CV_16S || depth == CV_16U || depth == CV_32F || depth == CV_64F );
switch( thresh_type ) switch( thresh_type )
{ {
@ -165,6 +179,13 @@ static void test_threshold( const Mat& _src, Mat& _dst,
for( j = 0; j < width_n; j++ ) for( j = 0; j < width_n; j++ )
dst[j] = (short)(src[j] > ithresh ? imaxval : 0); dst[j] = (short)(src[j] > ithresh ? imaxval : 0);
} }
else if( depth == CV_16U )
{
const ushort* src = _src.ptr<ushort>(i);
ushort* dst = _dst.ptr<ushort>(i);
for( j = 0; j < width_n; j++ )
dst[j] = (ushort)(src[j] > ithresh ? imaxval : 0);
}
else if( depth == CV_32F ) else if( depth == CV_32F )
{ {
const float* src = _src.ptr<float>(i); const float* src = _src.ptr<float>(i);
@ -198,6 +219,13 @@ static void test_threshold( const Mat& _src, Mat& _dst,
for( j = 0; j < width_n; j++ ) for( j = 0; j < width_n; j++ )
dst[j] = (short)(src[j] > ithresh ? 0 : imaxval); dst[j] = (short)(src[j] > ithresh ? 0 : imaxval);
} }
else if( depth == CV_16U )
{
const ushort* src = _src.ptr<ushort>(i);
ushort* dst = _dst.ptr<ushort>(i);
for( j = 0; j < width_n; j++ )
dst[j] = (ushort)(src[j] > ithresh ? 0 : imaxval);
}
else if( depth == CV_32F ) else if( depth == CV_32F )
{ {
const float* src = _src.ptr<float>(i); const float* src = _src.ptr<float>(i);
@ -237,6 +265,16 @@ static void test_threshold( const Mat& _src, Mat& _dst,
dst[j] = (short)(s > ithresh ? ithresh2 : s); dst[j] = (short)(s > ithresh ? ithresh2 : s);
} }
} }
else if( depth == CV_16U )
{
const ushort* src = _src.ptr<ushort>(i);
ushort* dst = _dst.ptr<ushort>(i);
for( j = 0; j < width_n; j++ )
{
int s = src[j];
dst[j] = (ushort)(s > ithresh ? ithresh2 : s);
}
}
else if( depth == CV_32F ) else if( depth == CV_32F )
{ {
const float* src = _src.ptr<float>(i); const float* src = _src.ptr<float>(i);
@ -282,6 +320,16 @@ static void test_threshold( const Mat& _src, Mat& _dst,
dst[j] = (short)(s > ithresh ? s : 0); dst[j] = (short)(s > ithresh ? s : 0);
} }
} }
else if( depth == CV_16U )
{
const ushort* src = _src.ptr<ushort>(i);
ushort* dst = _dst.ptr<ushort>(i);
for( j = 0; j < width_n; j++ )
{
int s = src[j];
dst[j] = (ushort)(s > ithresh ? s : 0);
}
}
else if( depth == CV_32F ) else if( depth == CV_32F )
{ {
const float* src = _src.ptr<float>(i); const float* src = _src.ptr<float>(i);
@ -327,6 +375,16 @@ static void test_threshold( const Mat& _src, Mat& _dst,
dst[j] = (short)(s > ithresh ? 0 : s); dst[j] = (short)(s > ithresh ? 0 : s);
} }
} }
else if( depth == CV_16U )
{
const ushort* src = _src.ptr<ushort>(i);
ushort* dst = _dst.ptr<ushort>(i);
for( j = 0; j < width_n; j++ )
{
int s = src[j];
dst[j] = (ushort)(s > ithresh ? 0 : s);
}
}
else if (depth == CV_32F) else if (depth == CV_32F)
{ {
const float* src = _src.ptr<float>(i); const float* src = _src.ptr<float>(i);