Home | History | Annotate | Download | only in test
      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