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