mirror of
https://github.com/opencv/opencv.git
synced 2024-11-29 05:29:54 +08:00
Fix bug in distanceTransform (#12278)
* fix 12218 * Update test_distancetransform.cpp marked the test as "BIGDATA_TEST" in order to skip it on low-mem platforms * modify test * use a smaller image in the test * fix test code
This commit is contained in:
parent
c7cf8fb35c
commit
cb7ee27cd9
@ -45,7 +45,8 @@ namespace cv
|
||||
{
|
||||
|
||||
static const int DIST_SHIFT = 16;
|
||||
static const int INIT_DIST0 = (INT_MAX >> 2);
|
||||
static const int INIT_DIST0 = INT_MAX;
|
||||
static const int DIST_MAX = (INT_MAX >> 2);
|
||||
#define CV_FLT_TO_FIX(x,n) cvRound((x)*(1<<(n)))
|
||||
|
||||
static void
|
||||
@ -71,8 +72,8 @@ distanceTransform_3x3( const Mat& _src, Mat& _temp, Mat& _dist, const float* met
|
||||
{
|
||||
const int BORDER = 1;
|
||||
int i, j;
|
||||
const int HV_DIST = CV_FLT_TO_FIX( metrics[0], DIST_SHIFT );
|
||||
const int DIAG_DIST = CV_FLT_TO_FIX( metrics[1], DIST_SHIFT );
|
||||
const unsigned int HV_DIST = CV_FLT_TO_FIX( metrics[0], DIST_SHIFT );
|
||||
const unsigned int DIAG_DIST = CV_FLT_TO_FIX( metrics[1], DIST_SHIFT );
|
||||
const float scale = 1.f/(1 << DIST_SHIFT);
|
||||
|
||||
const uchar* src = _src.ptr();
|
||||
@ -89,7 +90,7 @@ distanceTransform_3x3( const Mat& _src, Mat& _temp, Mat& _dist, const float* met
|
||||
for( i = 0; i < size.height; i++ )
|
||||
{
|
||||
const uchar* s = src + i*srcstep;
|
||||
int* tmp = (int*)(temp + (i+BORDER)*step) + BORDER;
|
||||
unsigned int* tmp = (unsigned int*)(temp + (i+BORDER)*step) + BORDER;
|
||||
|
||||
for( j = 0; j < BORDER; j++ )
|
||||
tmp[-j-1] = tmp[size.width + j] = INIT_DIST0;
|
||||
@ -100,8 +101,8 @@ distanceTransform_3x3( const Mat& _src, Mat& _temp, Mat& _dist, const float* met
|
||||
tmp[j] = 0;
|
||||
else
|
||||
{
|
||||
int t0 = tmp[j-step-1] + DIAG_DIST;
|
||||
int t = tmp[j-step] + HV_DIST;
|
||||
unsigned int t0 = tmp[j-step-1] + DIAG_DIST;
|
||||
unsigned int t = tmp[j-step] + HV_DIST;
|
||||
if( t0 > t ) t0 = t;
|
||||
t = tmp[j-step+1] + DIAG_DIST;
|
||||
if( t0 > t ) t0 = t;
|
||||
@ -116,14 +117,14 @@ distanceTransform_3x3( const Mat& _src, Mat& _temp, Mat& _dist, const float* met
|
||||
for( i = size.height - 1; i >= 0; i-- )
|
||||
{
|
||||
float* d = (float*)(dist + i*dststep);
|
||||
int* tmp = (int*)(temp + (i+BORDER)*step) + BORDER;
|
||||
unsigned int* tmp = (unsigned int*)(temp + (i+BORDER)*step) + BORDER;
|
||||
|
||||
for( j = size.width - 1; j >= 0; j-- )
|
||||
{
|
||||
int t0 = tmp[j];
|
||||
unsigned int t0 = tmp[j];
|
||||
if( t0 > HV_DIST )
|
||||
{
|
||||
int t = tmp[j+step+1] + DIAG_DIST;
|
||||
unsigned int t = tmp[j+step+1] + DIAG_DIST;
|
||||
if( t0 > t ) t0 = t;
|
||||
t = tmp[j+step] + HV_DIST;
|
||||
if( t0 > t ) t0 = t;
|
||||
@ -133,6 +134,7 @@ distanceTransform_3x3( const Mat& _src, Mat& _temp, Mat& _dist, const float* met
|
||||
if( t0 > t ) t0 = t;
|
||||
tmp[j] = t0;
|
||||
}
|
||||
t0 = (t0 > DIST_MAX) ? DIST_MAX : t0;
|
||||
d[j] = (float)(t0 * scale);
|
||||
}
|
||||
}
|
||||
@ -144,9 +146,9 @@ distanceTransform_5x5( const Mat& _src, Mat& _temp, Mat& _dist, const float* met
|
||||
{
|
||||
const int BORDER = 2;
|
||||
int i, j;
|
||||
const int HV_DIST = CV_FLT_TO_FIX( metrics[0], DIST_SHIFT );
|
||||
const int DIAG_DIST = CV_FLT_TO_FIX( metrics[1], DIST_SHIFT );
|
||||
const int LONG_DIST = CV_FLT_TO_FIX( metrics[2], DIST_SHIFT );
|
||||
const unsigned int HV_DIST = CV_FLT_TO_FIX( metrics[0], DIST_SHIFT );
|
||||
const unsigned int DIAG_DIST = CV_FLT_TO_FIX( metrics[1], DIST_SHIFT );
|
||||
const unsigned int LONG_DIST = CV_FLT_TO_FIX( metrics[2], DIST_SHIFT );
|
||||
const float scale = 1.f/(1 << DIST_SHIFT);
|
||||
|
||||
const uchar* src = _src.ptr();
|
||||
@ -163,7 +165,7 @@ distanceTransform_5x5( const Mat& _src, Mat& _temp, Mat& _dist, const float* met
|
||||
for( i = 0; i < size.height; i++ )
|
||||
{
|
||||
const uchar* s = src + i*srcstep;
|
||||
int* tmp = (int*)(temp + (i+BORDER)*step) + BORDER;
|
||||
unsigned int* tmp = (unsigned int*)(temp + (i+BORDER)*step) + BORDER;
|
||||
|
||||
for( j = 0; j < BORDER; j++ )
|
||||
tmp[-j-1] = tmp[size.width + j] = INIT_DIST0;
|
||||
@ -174,8 +176,8 @@ distanceTransform_5x5( const Mat& _src, Mat& _temp, Mat& _dist, const float* met
|
||||
tmp[j] = 0;
|
||||
else
|
||||
{
|
||||
int t0 = tmp[j-step*2-1] + LONG_DIST;
|
||||
int t = tmp[j-step*2+1] + LONG_DIST;
|
||||
unsigned int t0 = tmp[j-step*2-1] + LONG_DIST;
|
||||
unsigned int t = tmp[j-step*2+1] + LONG_DIST;
|
||||
if( t0 > t ) t0 = t;
|
||||
t = tmp[j-step-2] + LONG_DIST;
|
||||
if( t0 > t ) t0 = t;
|
||||
@ -198,14 +200,14 @@ distanceTransform_5x5( const Mat& _src, Mat& _temp, Mat& _dist, const float* met
|
||||
for( i = size.height - 1; i >= 0; i-- )
|
||||
{
|
||||
float* d = (float*)(dist + i*dststep);
|
||||
int* tmp = (int*)(temp + (i+BORDER)*step) + BORDER;
|
||||
unsigned int* tmp = (unsigned int*)(temp + (i+BORDER)*step) + BORDER;
|
||||
|
||||
for( j = size.width - 1; j >= 0; j-- )
|
||||
{
|
||||
int t0 = tmp[j];
|
||||
unsigned int t0 = tmp[j];
|
||||
if( t0 > HV_DIST )
|
||||
{
|
||||
int t = tmp[j+step*2+1] + LONG_DIST;
|
||||
unsigned int t = tmp[j+step*2+1] + LONG_DIST;
|
||||
if( t0 > t ) t0 = t;
|
||||
t = tmp[j+step*2-1] + LONG_DIST;
|
||||
if( t0 > t ) t0 = t;
|
||||
@ -223,6 +225,7 @@ distanceTransform_5x5( const Mat& _src, Mat& _temp, Mat& _dist, const float* met
|
||||
if( t0 > t ) t0 = t;
|
||||
tmp[j] = t0;
|
||||
}
|
||||
t0 = (t0 > DIST_MAX) ? DIST_MAX : t0;
|
||||
d[j] = (float)(t0 * scale);
|
||||
}
|
||||
}
|
||||
@ -235,9 +238,9 @@ distanceTransformEx_5x5( const Mat& _src, Mat& _temp, Mat& _dist, Mat& _labels,
|
||||
const int BORDER = 2;
|
||||
|
||||
int i, j;
|
||||
const int HV_DIST = CV_FLT_TO_FIX( metrics[0], DIST_SHIFT );
|
||||
const int DIAG_DIST = CV_FLT_TO_FIX( metrics[1], DIST_SHIFT );
|
||||
const int LONG_DIST = CV_FLT_TO_FIX( metrics[2], DIST_SHIFT );
|
||||
const unsigned int HV_DIST = CV_FLT_TO_FIX( metrics[0], DIST_SHIFT );
|
||||
const unsigned int DIAG_DIST = CV_FLT_TO_FIX( metrics[1], DIST_SHIFT );
|
||||
const unsigned int LONG_DIST = CV_FLT_TO_FIX( metrics[2], DIST_SHIFT );
|
||||
const float scale = 1.f/(1 << DIST_SHIFT);
|
||||
|
||||
const uchar* src = _src.ptr();
|
||||
@ -256,7 +259,7 @@ distanceTransformEx_5x5( const Mat& _src, Mat& _temp, Mat& _dist, Mat& _labels,
|
||||
for( i = 0; i < size.height; i++ )
|
||||
{
|
||||
const uchar* s = src + i*srcstep;
|
||||
int* tmp = (int*)(temp + (i+BORDER)*step) + BORDER;
|
||||
unsigned int* tmp = (unsigned int*)(temp + (i+BORDER)*step) + BORDER;
|
||||
int* lls = (int*)(labels + i*lstep);
|
||||
|
||||
for( j = 0; j < BORDER; j++ )
|
||||
@ -271,7 +274,7 @@ distanceTransformEx_5x5( const Mat& _src, Mat& _temp, Mat& _dist, Mat& _labels,
|
||||
}
|
||||
else
|
||||
{
|
||||
int t0 = INIT_DIST0, t;
|
||||
unsigned int t0 = INIT_DIST0, t;
|
||||
int l0 = 0;
|
||||
|
||||
t = tmp[j-step*2-1] + LONG_DIST;
|
||||
@ -333,16 +336,16 @@ distanceTransformEx_5x5( const Mat& _src, Mat& _temp, Mat& _dist, Mat& _labels,
|
||||
for( i = size.height - 1; i >= 0; i-- )
|
||||
{
|
||||
float* d = (float*)(dist + i*dststep);
|
||||
int* tmp = (int*)(temp + (i+BORDER)*step) + BORDER;
|
||||
unsigned int* tmp = (unsigned int*)(temp + (i+BORDER)*step) + BORDER;
|
||||
int* lls = (int*)(labels + i*lstep);
|
||||
|
||||
for( j = size.width - 1; j >= 0; j-- )
|
||||
{
|
||||
int t0 = tmp[j];
|
||||
unsigned int t0 = tmp[j];
|
||||
int l0 = lls[j];
|
||||
if( t0 > HV_DIST )
|
||||
{
|
||||
int t = tmp[j+step*2+1] + LONG_DIST;
|
||||
unsigned int t = tmp[j+step*2+1] + LONG_DIST;
|
||||
if( t0 > t )
|
||||
{
|
||||
t0 = t;
|
||||
@ -393,6 +396,7 @@ distanceTransformEx_5x5( const Mat& _src, Mat& _temp, Mat& _dist, Mat& _labels,
|
||||
tmp[j] = t0;
|
||||
lls[j] = l0;
|
||||
}
|
||||
t0 = (t0 > DIST_MAX) ? DIST_MAX : t0;
|
||||
d[j] = (float)(t0 * scale);
|
||||
}
|
||||
}
|
||||
|
@ -283,4 +283,23 @@ void CV_DisTransTest::prepare_to_validation( int /*test_case_idx*/ )
|
||||
|
||||
TEST(Imgproc_DistanceTransform, accuracy) { CV_DisTransTest test; test.safe_run(); }
|
||||
|
||||
BIGDATA_TEST(Imgproc_DistanceTransform, large_image_12218)
|
||||
{
|
||||
const int lls_maxcnt = 79992000; // labels's maximum count
|
||||
const int lls_mincnt = 1; // labels's minimum count
|
||||
int i, j, nz;
|
||||
Mat src(8000, 20000, CV_8UC1), dst, labels;
|
||||
for( i = 0; i < src.rows; i++ )
|
||||
for( j = 0; j < src.cols; j++ )
|
||||
src.at<uchar>(i, j) = (j > (src.cols / 2)) ? 0 : 255;
|
||||
|
||||
distanceTransform(src, dst, labels, cv::DIST_L2, cv::DIST_MASK_3, DIST_LABEL_PIXEL);
|
||||
|
||||
double scale = (double)lls_mincnt / (double)lls_maxcnt;
|
||||
labels.convertTo(labels, CV_32SC1, scale);
|
||||
Size size = labels.size();
|
||||
nz = cv::countNonZero(labels);
|
||||
EXPECT_EQ(nz, (size.height*size.width / 2));
|
||||
}
|
||||
|
||||
}} // namespace
|
||||
|
Loading…
Reference in New Issue
Block a user