Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Tetragramm
GitHub Repository: Tetragramm/opencv
Path: blob/master/modules/imgproc/test/test_thresh.cpp
16354 views
1
/*M///////////////////////////////////////////////////////////////////////////////////////
2
//
3
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
4
//
5
// By downloading, copying, installing or using the software you agree to this license.
6
// If you do not agree to this license, do not download, install,
7
// copy or use the software.
8
//
9
//
10
// Intel License Agreement
11
// For Open Source Computer Vision Library
12
//
13
// Copyright (C) 2000, Intel Corporation, all rights reserved.
14
// Third party copyrights are property of their respective owners.
15
//
16
// Redistribution and use in source and binary forms, with or without modification,
17
// are permitted provided that the following conditions are met:
18
//
19
// * Redistribution's of source code must retain the above copyright notice,
20
// this list of conditions and the following disclaimer.
21
//
22
// * Redistribution's in binary form must reproduce the above copyright notice,
23
// this list of conditions and the following disclaimer in the documentation
24
// and/or other materials provided with the distribution.
25
//
26
// * The name of Intel Corporation may not be used to endorse or promote products
27
// derived from this software without specific prior written permission.
28
//
29
// This software is provided by the copyright holders and contributors "as is" and
30
// any express or implied warranties, including, but not limited to, the implied
31
// warranties of merchantability and fitness for a particular purpose are disclaimed.
32
// In no event shall the Intel Corporation or contributors be liable for any direct,
33
// indirect, incidental, special, exemplary, or consequential damages
34
// (including, but not limited to, procurement of substitute goods or services;
35
// loss of use, data, or profits; or business interruption) however caused
36
// and on any theory of liability, whether in contract, strict liability,
37
// or tort (including negligence or otherwise) arising in any way out of
38
// the use of this software, even if advised of the possibility of such damage.
39
//
40
//M*/
41
42
#include "test_precomp.hpp"
43
44
namespace opencv_test { namespace {
45
46
class CV_ThreshTest : public cvtest::ArrayTest
47
{
48
public:
49
CV_ThreshTest();
50
51
protected:
52
void get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types );
53
double get_success_error_level( int test_case_idx, int i, int j );
54
void run_func();
55
void prepare_to_validation( int );
56
57
int thresh_type;
58
double thresh_val;
59
double max_val;
60
};
61
62
63
CV_ThreshTest::CV_ThreshTest()
64
{
65
test_array[INPUT].push_back(NULL);
66
test_array[OUTPUT].push_back(NULL);
67
test_array[REF_OUTPUT].push_back(NULL);
68
optional_mask = false;
69
element_wise_relative_error = true;
70
}
71
72
73
void CV_ThreshTest::get_test_array_types_and_sizes( int test_case_idx,
74
vector<vector<Size> >& sizes, vector<vector<int> >& types )
75
{
76
RNG& rng = ts->get_rng();
77
int depth = cvtest::randInt(rng) % 5, cn = cvtest::randInt(rng) % 4 + 1;
78
cvtest::ArrayTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
79
depth = depth == 0 ? CV_8U : depth == 1 ? CV_16S : depth == 2 ? CV_16U : depth == 3 ? CV_32F : CV_64F;
80
81
types[INPUT][0] = types[OUTPUT][0] = types[REF_OUTPUT][0] = CV_MAKETYPE(depth,cn);
82
thresh_type = cvtest::randInt(rng) % 5;
83
84
if( depth == CV_8U )
85
{
86
thresh_val = (cvtest::randReal(rng)*350. - 50.);
87
max_val = (cvtest::randReal(rng)*350. - 50.);
88
if( cvtest::randInt(rng)%4 == 0 )
89
max_val = 255.f;
90
}
91
else if( depth == CV_16S )
92
{
93
double min_val = SHRT_MIN-100.f;
94
max_val = SHRT_MAX+100.f;
95
thresh_val = (cvtest::randReal(rng)*(max_val - min_val) + min_val);
96
max_val = (cvtest::randReal(rng)*(max_val - min_val) + min_val);
97
if( cvtest::randInt(rng)%4 == 0 )
98
max_val = (double)SHRT_MAX;
99
}
100
else if( depth == CV_16U )
101
{
102
double min_val = -100.f;
103
max_val = USHRT_MAX+100.f;
104
thresh_val = (cvtest::randReal(rng)*(max_val - min_val) + min_val);
105
max_val = (cvtest::randReal(rng)*(max_val - min_val) + min_val);
106
if( cvtest::randInt(rng)%4 == 0 )
107
max_val = (double)USHRT_MAX;
108
}
109
else
110
{
111
thresh_val = (cvtest::randReal(rng)*1000. - 500.);
112
max_val = (cvtest::randReal(rng)*1000. - 500.);
113
}
114
}
115
116
117
double CV_ThreshTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ )
118
{
119
return FLT_EPSILON*10;
120
}
121
122
123
void CV_ThreshTest::run_func()
124
{
125
cvThreshold( test_array[INPUT][0], test_array[OUTPUT][0],
126
thresh_val, max_val, thresh_type );
127
}
128
129
130
static void test_threshold( const Mat& _src, Mat& _dst,
131
double thresh, double maxval, int thresh_type )
132
{
133
int i, j;
134
int depth = _src.depth(), cn = _src.channels();
135
int width_n = _src.cols*cn, height = _src.rows;
136
int ithresh = cvFloor(thresh);
137
int imaxval, ithresh2;
138
139
if( depth == CV_8U )
140
{
141
ithresh2 = saturate_cast<uchar>(ithresh);
142
imaxval = saturate_cast<uchar>(maxval);
143
}
144
else if( depth == CV_16S )
145
{
146
ithresh2 = saturate_cast<short>(ithresh);
147
imaxval = saturate_cast<short>(maxval);
148
}
149
else if( depth == CV_16U )
150
{
151
ithresh2 = saturate_cast<ushort>(ithresh);
152
imaxval = saturate_cast<ushort>(maxval);
153
}
154
else
155
{
156
ithresh2 = cvRound(ithresh);
157
imaxval = cvRound(maxval);
158
}
159
160
assert( depth == CV_8U || depth == CV_16S || depth == CV_16U || depth == CV_32F || depth == CV_64F );
161
162
switch( thresh_type )
163
{
164
case CV_THRESH_BINARY:
165
for( i = 0; i < height; i++ )
166
{
167
if( depth == CV_8U )
168
{
169
const uchar* src = _src.ptr<uchar>(i);
170
uchar* dst = _dst.ptr<uchar>(i);
171
for( j = 0; j < width_n; j++ )
172
dst[j] = (uchar)(src[j] > ithresh ? imaxval : 0);
173
}
174
else if( depth == CV_16S )
175
{
176
const short* src = _src.ptr<short>(i);
177
short* dst = _dst.ptr<short>(i);
178
for( j = 0; j < width_n; j++ )
179
dst[j] = (short)(src[j] > ithresh ? imaxval : 0);
180
}
181
else if( depth == CV_16U )
182
{
183
const ushort* src = _src.ptr<ushort>(i);
184
ushort* dst = _dst.ptr<ushort>(i);
185
for( j = 0; j < width_n; j++ )
186
dst[j] = (ushort)(src[j] > ithresh ? imaxval : 0);
187
}
188
else if( depth == CV_32F )
189
{
190
const float* src = _src.ptr<float>(i);
191
float* dst = _dst.ptr<float>(i);
192
for( j = 0; j < width_n; j++ )
193
dst[j] = (float)(src[j] > thresh ? maxval : 0.f);
194
}
195
else
196
{
197
const double* src = _src.ptr<double>(i);
198
double* dst = _dst.ptr<double>(i);
199
for( j = 0; j < width_n; j++ )
200
dst[j] = src[j] > thresh ? maxval : 0.0;
201
}
202
}
203
break;
204
case CV_THRESH_BINARY_INV:
205
for( i = 0; i < height; i++ )
206
{
207
if( depth == CV_8U )
208
{
209
const uchar* src = _src.ptr<uchar>(i);
210
uchar* dst = _dst.ptr<uchar>(i);
211
for( j = 0; j < width_n; j++ )
212
dst[j] = (uchar)(src[j] > ithresh ? 0 : imaxval);
213
}
214
else if( depth == CV_16S )
215
{
216
const short* src = _src.ptr<short>(i);
217
short* dst = _dst.ptr<short>(i);
218
for( j = 0; j < width_n; j++ )
219
dst[j] = (short)(src[j] > ithresh ? 0 : imaxval);
220
}
221
else if( depth == CV_16U )
222
{
223
const ushort* src = _src.ptr<ushort>(i);
224
ushort* dst = _dst.ptr<ushort>(i);
225
for( j = 0; j < width_n; j++ )
226
dst[j] = (ushort)(src[j] > ithresh ? 0 : imaxval);
227
}
228
else if( depth == CV_32F )
229
{
230
const float* src = _src.ptr<float>(i);
231
float* dst = _dst.ptr<float>(i);
232
for( j = 0; j < width_n; j++ )
233
dst[j] = (float)(src[j] > thresh ? 0.f : maxval);
234
}
235
else
236
{
237
const double* src = _src.ptr<double>(i);
238
double* dst = _dst.ptr<double>(i);
239
for( j = 0; j < width_n; j++ )
240
dst[j] = src[j] > thresh ? 0.0 : maxval;
241
}
242
}
243
break;
244
case CV_THRESH_TRUNC:
245
for( i = 0; i < height; i++ )
246
{
247
if( depth == CV_8U )
248
{
249
const uchar* src = _src.ptr<uchar>(i);
250
uchar* dst = _dst.ptr<uchar>(i);
251
for( j = 0; j < width_n; j++ )
252
{
253
int s = src[j];
254
dst[j] = (uchar)(s > ithresh ? ithresh2 : s);
255
}
256
}
257
else if( depth == CV_16S )
258
{
259
const short* src = _src.ptr<short>(i);
260
short* dst = _dst.ptr<short>(i);
261
for( j = 0; j < width_n; j++ )
262
{
263
int s = src[j];
264
dst[j] = (short)(s > ithresh ? ithresh2 : s);
265
}
266
}
267
else if( depth == CV_16U )
268
{
269
const ushort* src = _src.ptr<ushort>(i);
270
ushort* dst = _dst.ptr<ushort>(i);
271
for( j = 0; j < width_n; j++ )
272
{
273
int s = src[j];
274
dst[j] = (ushort)(s > ithresh ? ithresh2 : s);
275
}
276
}
277
else if( depth == CV_32F )
278
{
279
const float* src = _src.ptr<float>(i);
280
float* dst = _dst.ptr<float>(i);
281
for( j = 0; j < width_n; j++ )
282
{
283
float s = src[j];
284
dst[j] = (float)(s > thresh ? thresh : s);
285
}
286
}
287
else
288
{
289
const double* src = _src.ptr<double>(i);
290
double* dst = _dst.ptr<double>(i);
291
for( j = 0; j < width_n; j++ )
292
{
293
double s = src[j];
294
dst[j] = s > thresh ? thresh : s;
295
}
296
}
297
}
298
break;
299
case CV_THRESH_TOZERO:
300
for( i = 0; i < height; i++ )
301
{
302
if( depth == CV_8U )
303
{
304
const uchar* src = _src.ptr<uchar>(i);
305
uchar* dst = _dst.ptr<uchar>(i);
306
for( j = 0; j < width_n; j++ )
307
{
308
int s = src[j];
309
dst[j] = (uchar)(s > ithresh ? s : 0);
310
}
311
}
312
else if( depth == CV_16S )
313
{
314
const short* src = _src.ptr<short>(i);
315
short* dst = _dst.ptr<short>(i);
316
for( j = 0; j < width_n; j++ )
317
{
318
int s = src[j];
319
dst[j] = (short)(s > ithresh ? s : 0);
320
}
321
}
322
else if( depth == CV_16U )
323
{
324
const ushort* src = _src.ptr<ushort>(i);
325
ushort* dst = _dst.ptr<ushort>(i);
326
for( j = 0; j < width_n; j++ )
327
{
328
int s = src[j];
329
dst[j] = (ushort)(s > ithresh ? s : 0);
330
}
331
}
332
else if( depth == CV_32F )
333
{
334
const float* src = _src.ptr<float>(i);
335
float* dst = _dst.ptr<float>(i);
336
for( j = 0; j < width_n; j++ )
337
{
338
float s = src[j];
339
dst[j] = s > thresh ? s : 0.f;
340
}
341
}
342
else
343
{
344
const double* src = _src.ptr<double>(i);
345
double* dst = _dst.ptr<double>(i);
346
for( j = 0; j < width_n; j++ )
347
{
348
double s = src[j];
349
dst[j] = s > thresh ? s : 0.0;
350
}
351
}
352
}
353
break;
354
case CV_THRESH_TOZERO_INV:
355
for( i = 0; i < height; i++ )
356
{
357
if( depth == CV_8U )
358
{
359
const uchar* src = _src.ptr<uchar>(i);
360
uchar* dst = _dst.ptr<uchar>(i);
361
for( j = 0; j < width_n; j++ )
362
{
363
int s = src[j];
364
dst[j] = (uchar)(s > ithresh ? 0 : s);
365
}
366
}
367
else if( depth == CV_16S )
368
{
369
const short* src = _src.ptr<short>(i);
370
short* dst = _dst.ptr<short>(i);
371
for( j = 0; j < width_n; j++ )
372
{
373
int s = src[j];
374
dst[j] = (short)(s > ithresh ? 0 : s);
375
}
376
}
377
else if( depth == CV_16U )
378
{
379
const ushort* src = _src.ptr<ushort>(i);
380
ushort* dst = _dst.ptr<ushort>(i);
381
for( j = 0; j < width_n; j++ )
382
{
383
int s = src[j];
384
dst[j] = (ushort)(s > ithresh ? 0 : s);
385
}
386
}
387
else if (depth == CV_32F)
388
{
389
const float* src = _src.ptr<float>(i);
390
float* dst = _dst.ptr<float>(i);
391
for( j = 0; j < width_n; j++ )
392
{
393
float s = src[j];
394
dst[j] = s > thresh ? 0.f : s;
395
}
396
}
397
else
398
{
399
const double* src = _src.ptr<double>(i);
400
double* dst = _dst.ptr<double>(i);
401
for( j = 0; j < width_n; j++ )
402
{
403
double s = src[j];
404
dst[j] = s > thresh ? 0.0 : s;
405
}
406
}
407
}
408
break;
409
default:
410
assert(0);
411
}
412
}
413
414
415
void CV_ThreshTest::prepare_to_validation( int /*test_case_idx*/ )
416
{
417
test_threshold( test_mat[INPUT][0], test_mat[REF_OUTPUT][0],
418
thresh_val, max_val, thresh_type );
419
}
420
421
TEST(Imgproc_Threshold, accuracy) { CV_ThreshTest test; test.safe_run(); }
422
423
BIGDATA_TEST(Imgproc_Threshold, huge)
424
{
425
Mat m(65000, 40000, CV_8U);
426
ASSERT_FALSE(m.isContinuous());
427
428
uint64 i, n = (uint64)m.rows*m.cols;
429
for( i = 0; i < n; i++ )
430
m.data[i] = (uchar)(i & 255);
431
432
cv::threshold(m, m, 127, 255, cv::THRESH_BINARY);
433
int nz = cv::countNonZero(m); // FIXIT 'int' is not enough here (overflow is possible with other inputs)
434
ASSERT_EQ((uint64)nz, n / 2);
435
}
436
437
}} // namespace
438
439