Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Tetragramm
GitHub Repository: Tetragramm/opencv
Path: blob/master/modules/imgproc/test/test_cvtyuv.cpp
16344 views
1
#include "test_precomp.hpp"
2
3
namespace opencv_test { namespace {
4
5
#undef RGB
6
#undef YUV
7
8
typedef Vec3b YUV;
9
typedef Vec3b RGB;
10
11
int countOfDifferencies(const Mat& gold, const Mat& result, int maxAllowedDifference = 1)
12
{
13
Mat diff;
14
absdiff(gold, result, diff);
15
return countNonZero(diff.reshape(1) > maxAllowedDifference);
16
}
17
18
class YUVreader
19
{
20
public:
21
virtual ~YUVreader() {}
22
virtual YUV read(const Mat& yuv, int row, int col) = 0;
23
virtual int channels() = 0;
24
virtual Size size(Size imgSize) = 0;
25
26
virtual bool requiresEvenHeight() { return true; }
27
virtual bool requiresEvenWidth() { return true; }
28
29
static YUVreader* getReader(int code);
30
};
31
32
class RGBreader
33
{
34
public:
35
virtual ~RGBreader() {}
36
virtual RGB read(const Mat& rgb, int row, int col) = 0;
37
virtual int channels() = 0;
38
39
static RGBreader* getReader(int code);
40
};
41
42
class RGBwriter
43
{
44
public:
45
virtual ~RGBwriter() {}
46
47
virtual void write(Mat& rgb, int row, int col, const RGB& val) = 0;
48
virtual int channels() = 0;
49
50
static RGBwriter* getWriter(int code);
51
};
52
53
class GRAYwriter
54
{
55
public:
56
virtual ~GRAYwriter() {}
57
58
virtual void write(Mat& gray, int row, int col, const uchar& val)
59
{
60
gray.at<uchar>(row, col) = val;
61
}
62
63
virtual int channels() { return 1; }
64
65
static GRAYwriter* getWriter(int code);
66
};
67
68
class YUVwriter
69
{
70
public:
71
virtual ~YUVwriter() {}
72
73
virtual void write(Mat& yuv, int row, int col, const YUV& val) = 0;
74
virtual int channels() = 0;
75
virtual Size size(Size imgSize) = 0;
76
77
virtual bool requiresEvenHeight() { return true; }
78
virtual bool requiresEvenWidth() { return true; }
79
80
static YUVwriter* getWriter(int code);
81
};
82
83
class RGB888Writer : public RGBwriter
84
{
85
void write(Mat& rgb, int row, int col, const RGB& val)
86
{
87
rgb.at<Vec3b>(row, col) = val;
88
}
89
90
int channels() { return 3; }
91
};
92
93
class BGR888Writer : public RGBwriter
94
{
95
void write(Mat& rgb, int row, int col, const RGB& val)
96
{
97
Vec3b tmp(val[2], val[1], val[0]);
98
rgb.at<Vec3b>(row, col) = tmp;
99
}
100
101
int channels() { return 3; }
102
};
103
104
class RGBA8888Writer : public RGBwriter
105
{
106
void write(Mat& rgb, int row, int col, const RGB& val)
107
{
108
Vec4b tmp(val[0], val[1], val[2], 255);
109
rgb.at<Vec4b>(row, col) = tmp;
110
}
111
112
int channels() { return 4; }
113
};
114
115
class BGRA8888Writer : public RGBwriter
116
{
117
void write(Mat& rgb, int row, int col, const RGB& val)
118
{
119
Vec4b tmp(val[2], val[1], val[0], 255);
120
rgb.at<Vec4b>(row, col) = tmp;
121
}
122
123
int channels() { return 4; }
124
};
125
126
class YUV420pWriter: public YUVwriter
127
{
128
int channels() { return 1; }
129
Size size(Size imgSize) { return Size(imgSize.width, imgSize.height + imgSize.height/2); }
130
};
131
132
class YV12Writer: public YUV420pWriter
133
{
134
void write(Mat& yuv, int row, int col, const YUV& val)
135
{
136
int h = yuv.rows * 2 / 3;
137
138
yuv.ptr<uchar>(row)[col] = val[0];
139
if( row % 2 == 0 && col % 2 == 0 )
140
{
141
yuv.ptr<uchar>(h + row/4)[col/2 + ((row/2) % 2) * (yuv.cols/2)] = val[2];
142
yuv.ptr<uchar>(h + (row/2 + h/2)/2)[col/2 + ((row/2 + h/2) % 2) * (yuv.cols/2)] = val[1];
143
}
144
}
145
};
146
147
class I420Writer: public YUV420pWriter
148
{
149
void write(Mat& yuv, int row, int col, const YUV& val)
150
{
151
int h = yuv.rows * 2 / 3;
152
153
yuv.ptr<uchar>(row)[col] = val[0];
154
if( row % 2 == 0 && col % 2 == 0 )
155
{
156
yuv.ptr<uchar>(h + row/4)[col/2 + ((row/2) % 2) * (yuv.cols/2)] = val[1];
157
yuv.ptr<uchar>(h + (row/2 + h/2)/2)[col/2 + ((row/2 + h/2) % 2) * (yuv.cols/2)] = val[2];
158
}
159
}
160
};
161
162
class YUV420Reader: public YUVreader
163
{
164
int channels() { return 1; }
165
Size size(Size imgSize) { return Size(imgSize.width, imgSize.height * 3 / 2); }
166
};
167
168
class YUV422Reader: public YUVreader
169
{
170
int channels() { return 2; }
171
Size size(Size imgSize) { return imgSize; }
172
bool requiresEvenHeight() { return false; }
173
};
174
175
class NV21Reader: public YUV420Reader
176
{
177
YUV read(const Mat& yuv, int row, int col)
178
{
179
uchar y = yuv.ptr<uchar>(row)[col];
180
uchar u = yuv.ptr<uchar>(yuv.rows * 2 / 3 + row/2)[(col/2)*2 + 1];
181
uchar v = yuv.ptr<uchar>(yuv.rows * 2 / 3 + row/2)[(col/2)*2];
182
183
return YUV(y, u, v);
184
}
185
};
186
187
188
struct NV12Reader: public YUV420Reader
189
{
190
YUV read(const Mat& yuv, int row, int col)
191
{
192
uchar y = yuv.ptr<uchar>(row)[col];
193
uchar u = yuv.ptr<uchar>(yuv.rows * 2 / 3 + row/2)[(col/2)*2];
194
uchar v = yuv.ptr<uchar>(yuv.rows * 2 / 3 + row/2)[(col/2)*2 + 1];
195
196
return YUV(y, u, v);
197
}
198
};
199
200
class YV12Reader: public YUV420Reader
201
{
202
YUV read(const Mat& yuv, int row, int col)
203
{
204
int h = yuv.rows * 2 / 3;
205
uchar y = yuv.ptr<uchar>(row)[col];
206
uchar u = yuv.ptr<uchar>(h + (row/2 + h/2)/2)[col/2 + ((row/2 + h/2) % 2) * (yuv.cols/2)];
207
uchar v = yuv.ptr<uchar>(h + row/4)[col/2 + ((row/2) % 2) * (yuv.cols/2)];
208
209
return YUV(y, u, v);
210
}
211
};
212
213
class IYUVReader: public YUV420Reader
214
{
215
YUV read(const Mat& yuv, int row, int col)
216
{
217
int h = yuv.rows * 2 / 3;
218
uchar y = yuv.ptr<uchar>(row)[col];
219
uchar u = yuv.ptr<uchar>(h + row/4)[col/2 + ((row/2) % 2) * (yuv.cols/2)];
220
uchar v = yuv.ptr<uchar>(h + (row/2 + h/2)/2)[col/2 + ((row/2 + h/2) % 2) * (yuv.cols/2)];
221
222
return YUV(y, u, v);
223
}
224
};
225
226
class UYVYReader: public YUV422Reader
227
{
228
YUV read(const Mat& yuv, int row, int col)
229
{
230
uchar y = yuv.ptr<Vec2b>(row)[col][1];
231
uchar u = yuv.ptr<Vec2b>(row)[(col/2)*2][0];
232
uchar v = yuv.ptr<Vec2b>(row)[(col/2)*2 + 1][0];
233
234
return YUV(y, u, v);
235
}
236
};
237
238
class YUY2Reader: public YUV422Reader
239
{
240
YUV read(const Mat& yuv, int row, int col)
241
{
242
uchar y = yuv.ptr<Vec2b>(row)[col][0];
243
uchar u = yuv.ptr<Vec2b>(row)[(col/2)*2][1];
244
uchar v = yuv.ptr<Vec2b>(row)[(col/2)*2 + 1][1];
245
246
return YUV(y, u, v);
247
}
248
};
249
250
class YVYUReader: public YUV422Reader
251
{
252
YUV read(const Mat& yuv, int row, int col)
253
{
254
uchar y = yuv.ptr<Vec2b>(row)[col][0];
255
uchar u = yuv.ptr<Vec2b>(row)[(col/2)*2 + 1][1];
256
uchar v = yuv.ptr<Vec2b>(row)[(col/2)*2][1];
257
258
return YUV(y, u, v);
259
}
260
};
261
262
class YUV888Reader : public YUVreader
263
{
264
YUV read(const Mat& yuv, int row, int col)
265
{
266
return yuv.at<YUV>(row, col);
267
}
268
269
int channels() { return 3; }
270
Size size(Size imgSize) { return imgSize; }
271
bool requiresEvenHeight() { return false; }
272
bool requiresEvenWidth() { return false; }
273
};
274
275
class RGB888Reader : public RGBreader
276
{
277
RGB read(const Mat& rgb, int row, int col)
278
{
279
return rgb.at<RGB>(row, col);
280
}
281
282
int channels() { return 3; }
283
};
284
285
class BGR888Reader : public RGBreader
286
{
287
RGB read(const Mat& rgb, int row, int col)
288
{
289
RGB tmp = rgb.at<RGB>(row, col);
290
return RGB(tmp[2], tmp[1], tmp[0]);
291
}
292
293
int channels() { return 3; }
294
};
295
296
class RGBA8888Reader : public RGBreader
297
{
298
RGB read(const Mat& rgb, int row, int col)
299
{
300
Vec4b rgba = rgb.at<Vec4b>(row, col);
301
return RGB(rgba[0], rgba[1], rgba[2]);
302
}
303
304
int channels() { return 4; }
305
};
306
307
class BGRA8888Reader : public RGBreader
308
{
309
RGB read(const Mat& rgb, int row, int col)
310
{
311
Vec4b rgba = rgb.at<Vec4b>(row, col);
312
return RGB(rgba[2], rgba[1], rgba[0]);
313
}
314
315
int channels() { return 4; }
316
};
317
318
class YUV2RGB_Converter
319
{
320
public:
321
RGB convert(YUV yuv)
322
{
323
int y = std::max(0, yuv[0] - 16);
324
int u = yuv[1] - 128;
325
int v = yuv[2] - 128;
326
uchar r = saturate_cast<uchar>(1.164f * y + 1.596f * v);
327
uchar g = saturate_cast<uchar>(1.164f * y - 0.813f * v - 0.391f * u);
328
uchar b = saturate_cast<uchar>(1.164f * y + 2.018f * u);
329
330
return RGB(r, g, b);
331
}
332
};
333
334
class YUV2GRAY_Converter
335
{
336
public:
337
uchar convert(YUV yuv)
338
{
339
return yuv[0];
340
}
341
};
342
343
class RGB2YUV_Converter
344
{
345
public:
346
YUV convert(RGB rgb)
347
{
348
int r = rgb[0];
349
int g = rgb[1];
350
int b = rgb[2];
351
352
uchar y = saturate_cast<uchar>((int)( 0.257f*r + 0.504f*g + 0.098f*b + 0.5f) + 16);
353
uchar u = saturate_cast<uchar>((int)(-0.148f*r - 0.291f*g + 0.439f*b + 0.5f) + 128);
354
uchar v = saturate_cast<uchar>((int)( 0.439f*r - 0.368f*g - 0.071f*b + 0.5f) + 128);
355
356
return YUV(y, u, v);
357
}
358
};
359
360
YUVreader* YUVreader::getReader(int code)
361
{
362
switch(code)
363
{
364
case CV_YUV2RGB_NV12:
365
case CV_YUV2BGR_NV12:
366
case CV_YUV2RGBA_NV12:
367
case CV_YUV2BGRA_NV12:
368
return new NV12Reader();
369
case CV_YUV2RGB_NV21:
370
case CV_YUV2BGR_NV21:
371
case CV_YUV2RGBA_NV21:
372
case CV_YUV2BGRA_NV21:
373
return new NV21Reader();
374
case CV_YUV2RGB_YV12:
375
case CV_YUV2BGR_YV12:
376
case CV_YUV2RGBA_YV12:
377
case CV_YUV2BGRA_YV12:
378
return new YV12Reader();
379
case CV_YUV2RGB_IYUV:
380
case CV_YUV2BGR_IYUV:
381
case CV_YUV2RGBA_IYUV:
382
case CV_YUV2BGRA_IYUV:
383
return new IYUVReader();
384
case CV_YUV2RGB_UYVY:
385
case CV_YUV2BGR_UYVY:
386
case CV_YUV2RGBA_UYVY:
387
case CV_YUV2BGRA_UYVY:
388
return new UYVYReader();
389
//case CV_YUV2RGB_VYUY = 109,
390
//case CV_YUV2BGR_VYUY = 110,
391
//case CV_YUV2RGBA_VYUY = 113,
392
//case CV_YUV2BGRA_VYUY = 114,
393
// return ??
394
case CV_YUV2RGB_YUY2:
395
case CV_YUV2BGR_YUY2:
396
case CV_YUV2RGBA_YUY2:
397
case CV_YUV2BGRA_YUY2:
398
return new YUY2Reader();
399
case CV_YUV2RGB_YVYU:
400
case CV_YUV2BGR_YVYU:
401
case CV_YUV2RGBA_YVYU:
402
case CV_YUV2BGRA_YVYU:
403
return new YVYUReader();
404
case CV_YUV2GRAY_420:
405
return new NV21Reader();
406
case CV_YUV2GRAY_UYVY:
407
return new UYVYReader();
408
case CV_YUV2GRAY_YUY2:
409
return new YUY2Reader();
410
case CV_YUV2BGR:
411
case CV_YUV2RGB:
412
return new YUV888Reader();
413
default:
414
return 0;
415
}
416
}
417
418
RGBreader* RGBreader::getReader(int code)
419
{
420
switch(code)
421
{
422
case CV_RGB2YUV_YV12:
423
case CV_RGB2YUV_I420:
424
return new RGB888Reader();
425
case CV_BGR2YUV_YV12:
426
case CV_BGR2YUV_I420:
427
return new BGR888Reader();
428
case CV_RGBA2YUV_I420:
429
case CV_RGBA2YUV_YV12:
430
return new RGBA8888Reader();
431
case CV_BGRA2YUV_YV12:
432
case CV_BGRA2YUV_I420:
433
return new BGRA8888Reader();
434
default:
435
return 0;
436
};
437
}
438
439
RGBwriter* RGBwriter::getWriter(int code)
440
{
441
switch(code)
442
{
443
case CV_YUV2RGB_NV12:
444
case CV_YUV2RGB_NV21:
445
case CV_YUV2RGB_YV12:
446
case CV_YUV2RGB_IYUV:
447
case CV_YUV2RGB_UYVY:
448
//case CV_YUV2RGB_VYUY:
449
case CV_YUV2RGB_YUY2:
450
case CV_YUV2RGB_YVYU:
451
case CV_YUV2RGB:
452
return new RGB888Writer();
453
case CV_YUV2BGR_NV12:
454
case CV_YUV2BGR_NV21:
455
case CV_YUV2BGR_YV12:
456
case CV_YUV2BGR_IYUV:
457
case CV_YUV2BGR_UYVY:
458
//case CV_YUV2BGR_VYUY:
459
case CV_YUV2BGR_YUY2:
460
case CV_YUV2BGR_YVYU:
461
case CV_YUV2BGR:
462
return new BGR888Writer();
463
case CV_YUV2RGBA_NV12:
464
case CV_YUV2RGBA_NV21:
465
case CV_YUV2RGBA_YV12:
466
case CV_YUV2RGBA_IYUV:
467
case CV_YUV2RGBA_UYVY:
468
//case CV_YUV2RGBA_VYUY:
469
case CV_YUV2RGBA_YUY2:
470
case CV_YUV2RGBA_YVYU:
471
return new RGBA8888Writer();
472
case CV_YUV2BGRA_NV12:
473
case CV_YUV2BGRA_NV21:
474
case CV_YUV2BGRA_YV12:
475
case CV_YUV2BGRA_IYUV:
476
case CV_YUV2BGRA_UYVY:
477
//case CV_YUV2BGRA_VYUY:
478
case CV_YUV2BGRA_YUY2:
479
case CV_YUV2BGRA_YVYU:
480
return new BGRA8888Writer();
481
default:
482
return 0;
483
};
484
}
485
486
GRAYwriter* GRAYwriter::getWriter(int code)
487
{
488
switch(code)
489
{
490
case CV_YUV2GRAY_420:
491
case CV_YUV2GRAY_UYVY:
492
case CV_YUV2GRAY_YUY2:
493
return new GRAYwriter();
494
default:
495
return 0;
496
}
497
}
498
499
YUVwriter* YUVwriter::getWriter(int code)
500
{
501
switch(code)
502
{
503
case CV_RGB2YUV_YV12:
504
case CV_BGR2YUV_YV12:
505
case CV_RGBA2YUV_YV12:
506
case CV_BGRA2YUV_YV12:
507
return new YV12Writer();
508
case CV_RGB2YUV_I420:
509
case CV_BGR2YUV_I420:
510
case CV_RGBA2YUV_I420:
511
case CV_BGRA2YUV_I420:
512
return new I420Writer();
513
default:
514
return 0;
515
};
516
}
517
518
template<class convertor>
519
void referenceYUV2RGB(const Mat& yuv, Mat& rgb, YUVreader* yuvReader, RGBwriter* rgbWriter)
520
{
521
convertor cvt;
522
523
for(int row = 0; row < rgb.rows; ++row)
524
for(int col = 0; col < rgb.cols; ++col)
525
rgbWriter->write(rgb, row, col, cvt.convert(yuvReader->read(yuv, row, col)));
526
}
527
528
template<class convertor>
529
void referenceYUV2GRAY(const Mat& yuv, Mat& rgb, YUVreader* yuvReader, GRAYwriter* grayWriter)
530
{
531
convertor cvt;
532
533
for(int row = 0; row < rgb.rows; ++row)
534
for(int col = 0; col < rgb.cols; ++col)
535
grayWriter->write(rgb, row, col, cvt.convert(yuvReader->read(yuv, row, col)));
536
}
537
538
template<class convertor>
539
void referenceRGB2YUV(const Mat& rgb, Mat& yuv, RGBreader* rgbReader, YUVwriter* yuvWriter)
540
{
541
convertor cvt;
542
543
for(int row = 0; row < rgb.rows; ++row)
544
for(int col = 0; col < rgb.cols; ++col)
545
yuvWriter->write(yuv, row, col, cvt.convert(rgbReader->read(rgb, row, col)));
546
}
547
548
struct ConversionYUV
549
{
550
explicit ConversionYUV( const int code )
551
{
552
yuvReader_ = YUVreader :: getReader(code);
553
yuvWriter_ = YUVwriter :: getWriter(code);
554
rgbReader_ = RGBreader :: getReader(code);
555
rgbWriter_ = RGBwriter :: getWriter(code);
556
grayWriter_ = GRAYwriter:: getWriter(code);
557
}
558
559
~ConversionYUV()
560
{
561
if (yuvReader_)
562
delete yuvReader_;
563
564
if (yuvWriter_)
565
delete yuvWriter_;
566
567
if (rgbReader_)
568
delete rgbReader_;
569
570
if (rgbWriter_)
571
delete rgbWriter_;
572
573
if (grayWriter_)
574
delete grayWriter_;
575
}
576
577
int getDcn()
578
{
579
return (rgbWriter_ != 0) ? rgbWriter_->channels() : ((grayWriter_ != 0) ? grayWriter_->channels() : yuvWriter_->channels());
580
}
581
582
int getScn()
583
{
584
return (yuvReader_ != 0) ? yuvReader_->channels() : rgbReader_->channels();
585
}
586
587
Size getSrcSize( const Size& imgSize )
588
{
589
return (yuvReader_ != 0) ? yuvReader_->size(imgSize) : imgSize;
590
}
591
592
Size getDstSize( const Size& imgSize )
593
{
594
return (yuvWriter_ != 0) ? yuvWriter_->size(imgSize) : imgSize;
595
}
596
597
bool requiresEvenHeight()
598
{
599
return (yuvReader_ != 0) ? yuvReader_->requiresEvenHeight() : ((yuvWriter_ != 0) ? yuvWriter_->requiresEvenHeight() : false);
600
}
601
602
bool requiresEvenWidth()
603
{
604
return (yuvReader_ != 0) ? yuvReader_->requiresEvenWidth() : ((yuvWriter_ != 0) ? yuvWriter_->requiresEvenWidth() : false);
605
}
606
607
YUVreader* yuvReader_;
608
YUVwriter* yuvWriter_;
609
RGBreader* rgbReader_;
610
RGBwriter* rgbWriter_;
611
GRAYwriter* grayWriter_;
612
};
613
614
CV_ENUM(YUVCVTS, CV_YUV2RGB_NV12, CV_YUV2BGR_NV12, CV_YUV2RGB_NV21, CV_YUV2BGR_NV21,
615
CV_YUV2RGBA_NV12, CV_YUV2BGRA_NV12, CV_YUV2RGBA_NV21, CV_YUV2BGRA_NV21,
616
CV_YUV2RGB_YV12, CV_YUV2BGR_YV12, CV_YUV2RGB_IYUV, CV_YUV2BGR_IYUV,
617
CV_YUV2RGBA_YV12, CV_YUV2BGRA_YV12, CV_YUV2RGBA_IYUV, CV_YUV2BGRA_IYUV,
618
CV_YUV2RGB_UYVY, CV_YUV2BGR_UYVY, CV_YUV2RGBA_UYVY, CV_YUV2BGRA_UYVY,
619
CV_YUV2RGB_YUY2, CV_YUV2BGR_YUY2, CV_YUV2RGB_YVYU, CV_YUV2BGR_YVYU,
620
CV_YUV2RGBA_YUY2, CV_YUV2BGRA_YUY2, CV_YUV2RGBA_YVYU, CV_YUV2BGRA_YVYU,
621
CV_YUV2GRAY_420, CV_YUV2GRAY_UYVY, CV_YUV2GRAY_YUY2,
622
CV_YUV2BGR, CV_YUV2RGB, CV_RGB2YUV_YV12, CV_BGR2YUV_YV12, CV_RGBA2YUV_YV12,
623
CV_BGRA2YUV_YV12, CV_RGB2YUV_I420, CV_BGR2YUV_I420, CV_RGBA2YUV_I420, CV_BGRA2YUV_I420)
624
625
typedef ::testing::TestWithParam<YUVCVTS> Imgproc_ColorYUV;
626
627
TEST_P(Imgproc_ColorYUV, accuracy)
628
{
629
int code = GetParam();
630
RNG& random = theRNG();
631
632
ConversionYUV cvt(code);
633
634
const int scn = cvt.getScn();
635
const int dcn = cvt.getDcn();
636
for(int iter = 0; iter < 30; ++iter)
637
{
638
Size sz(random.uniform(1, 641), random.uniform(1, 481));
639
640
if(cvt.requiresEvenWidth()) sz.width += sz.width % 2;
641
if(cvt.requiresEvenHeight()) sz.height += sz.height % 2;
642
643
Size srcSize = cvt.getSrcSize(sz);
644
Mat src = Mat(srcSize.height, srcSize.width * scn, CV_8UC1).reshape(scn);
645
646
Size dstSize = cvt.getDstSize(sz);
647
Mat dst = Mat(dstSize.height, dstSize.width * dcn, CV_8UC1).reshape(dcn);
648
Mat gold(dstSize, CV_8UC(dcn));
649
650
random.fill(src, RNG::UNIFORM, 0, 256);
651
652
if(cvt.rgbWriter_)
653
referenceYUV2RGB<YUV2RGB_Converter> (src, gold, cvt.yuvReader_, cvt.rgbWriter_);
654
else if(cvt.grayWriter_)
655
referenceYUV2GRAY<YUV2GRAY_Converter>(src, gold, cvt.yuvReader_, cvt.grayWriter_);
656
else if(cvt.yuvWriter_)
657
referenceRGB2YUV<RGB2YUV_Converter> (src, gold, cvt.rgbReader_, cvt.yuvWriter_);
658
659
cv::cvtColor(src, dst, code, -1);
660
661
EXPECT_EQ(0, countOfDifferencies(gold, dst));
662
}
663
}
664
665
TEST_P(Imgproc_ColorYUV, roi_accuracy)
666
{
667
int code = GetParam();
668
RNG& random = theRNG();
669
670
ConversionYUV cvt(code);
671
672
const int scn = cvt.getScn();
673
const int dcn = cvt.getDcn();
674
for(int iter = 0; iter < 30; ++iter)
675
{
676
Size sz(random.uniform(1, 641), random.uniform(1, 481));
677
678
if(cvt.requiresEvenWidth()) sz.width += sz.width % 2;
679
if(cvt.requiresEvenHeight()) sz.height += sz.height % 2;
680
681
int roi_offset_top = random.uniform(0, 6);
682
int roi_offset_bottom = random.uniform(0, 6);
683
int roi_offset_left = random.uniform(0, 6);
684
int roi_offset_right = random.uniform(0, 6);
685
686
Size srcSize = cvt.getSrcSize(sz);
687
Mat src_full(srcSize.height + roi_offset_top + roi_offset_bottom, srcSize.width + roi_offset_left + roi_offset_right, CV_8UC(scn));
688
689
Size dstSize = cvt.getDstSize(sz);
690
Mat dst_full(dstSize.height + roi_offset_left + roi_offset_right, dstSize.width + roi_offset_top + roi_offset_bottom, CV_8UC(dcn), Scalar::all(0));
691
Mat gold_full(dst_full.size(), CV_8UC(dcn), Scalar::all(0));
692
693
random.fill(src_full, RNG::UNIFORM, 0, 256);
694
695
Mat src = src_full(Range(roi_offset_top, roi_offset_top + srcSize.height), Range(roi_offset_left, roi_offset_left + srcSize.width));
696
Mat dst = dst_full(Range(roi_offset_left, roi_offset_left + dstSize.height), Range(roi_offset_top, roi_offset_top + dstSize.width));
697
Mat gold = gold_full(Range(roi_offset_left, roi_offset_left + dstSize.height), Range(roi_offset_top, roi_offset_top + dstSize.width));
698
699
if(cvt.rgbWriter_)
700
referenceYUV2RGB<YUV2RGB_Converter> (src, gold, cvt.yuvReader_, cvt.rgbWriter_);
701
else if(cvt.grayWriter_)
702
referenceYUV2GRAY<YUV2GRAY_Converter>(src, gold, cvt.yuvReader_, cvt.grayWriter_);
703
else if(cvt.yuvWriter_)
704
referenceRGB2YUV<RGB2YUV_Converter> (src, gold, cvt.rgbReader_, cvt.yuvWriter_);
705
706
cv::cvtColor(src, dst, code, -1);
707
708
EXPECT_EQ(0, countOfDifferencies(gold_full, dst_full));
709
}
710
}
711
712
INSTANTIATE_TEST_CASE_P(cvt420, Imgproc_ColorYUV,
713
::testing::Values((int)CV_YUV2RGB_NV12, (int)CV_YUV2BGR_NV12, (int)CV_YUV2RGB_NV21, (int)CV_YUV2BGR_NV21,
714
(int)CV_YUV2RGBA_NV12, (int)CV_YUV2BGRA_NV12, (int)CV_YUV2RGBA_NV21, (int)CV_YUV2BGRA_NV21,
715
(int)CV_YUV2RGB_YV12, (int)CV_YUV2BGR_YV12, (int)CV_YUV2RGB_IYUV, (int)CV_YUV2BGR_IYUV,
716
(int)CV_YUV2RGBA_YV12, (int)CV_YUV2BGRA_YV12, (int)CV_YUV2RGBA_IYUV, (int)CV_YUV2BGRA_IYUV,
717
(int)CV_YUV2GRAY_420, (int)CV_RGB2YUV_YV12, (int)CV_BGR2YUV_YV12, (int)CV_RGBA2YUV_YV12,
718
(int)CV_BGRA2YUV_YV12, (int)CV_RGB2YUV_I420, (int)CV_BGR2YUV_I420, (int)CV_RGBA2YUV_I420,
719
(int)CV_BGRA2YUV_I420));
720
721
INSTANTIATE_TEST_CASE_P(cvt422, Imgproc_ColorYUV,
722
::testing::Values((int)CV_YUV2RGB_UYVY, (int)CV_YUV2BGR_UYVY, (int)CV_YUV2RGBA_UYVY, (int)CV_YUV2BGRA_UYVY,
723
(int)CV_YUV2RGB_YUY2, (int)CV_YUV2BGR_YUY2, (int)CV_YUV2RGB_YVYU, (int)CV_YUV2BGR_YVYU,
724
(int)CV_YUV2RGBA_YUY2, (int)CV_YUV2BGRA_YUY2, (int)CV_YUV2RGBA_YVYU, (int)CV_YUV2BGRA_YVYU,
725
(int)CV_YUV2GRAY_UYVY, (int)CV_YUV2GRAY_YUY2));
726
727
}} // namespace
728
729