709 lines
		
	
	
		
			20 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			709 lines
		
	
	
		
			20 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
#include "test_precomp.hpp"
 | 
						|
 | 
						|
using namespace cv;
 | 
						|
using namespace std;
 | 
						|
 | 
						|
#undef RGB
 | 
						|
#undef YUV
 | 
						|
 | 
						|
typedef Vec3b YUV;
 | 
						|
typedef Vec3b RGB;
 | 
						|
 | 
						|
int countOfDifferencies(const Mat& gold, const Mat& result, int maxAllowedDifference = 1)
 | 
						|
{
 | 
						|
    Mat diff;
 | 
						|
    absdiff(gold, result, diff);
 | 
						|
    return countNonZero(diff.reshape(1) > maxAllowedDifference);
 | 
						|
}
 | 
						|
 | 
						|
class YUVreader
 | 
						|
{
 | 
						|
public:
 | 
						|
    virtual ~YUVreader() {}
 | 
						|
    virtual YUV read(const Mat& yuv, int row, int col) = 0;
 | 
						|
    virtual int channels() = 0;
 | 
						|
    virtual Size size(Size imgSize) = 0;
 | 
						|
 | 
						|
    virtual bool requiresEvenHeight() { return true; }
 | 
						|
    virtual bool requiresEvenWidth() { return true; }
 | 
						|
 | 
						|
    static YUVreader* getReader(int code);
 | 
						|
};
 | 
						|
 | 
						|
class RGBreader
 | 
						|
{
 | 
						|
public:
 | 
						|
    virtual ~RGBreader() {}
 | 
						|
    virtual RGB read(const Mat& rgb, int row, int col) = 0;
 | 
						|
    virtual int channels() = 0;
 | 
						|
 | 
						|
    static RGBreader* getReader(int code);
 | 
						|
};
 | 
						|
 | 
						|
class RGBwriter
 | 
						|
{
 | 
						|
public:
 | 
						|
    virtual ~RGBwriter() {}
 | 
						|
 | 
						|
    virtual void write(Mat& rgb, int row, int col, const RGB& val) = 0;
 | 
						|
    virtual int channels() = 0;
 | 
						|
 | 
						|
    static RGBwriter* getWriter(int code);
 | 
						|
};
 | 
						|
 | 
						|
class GRAYwriter
 | 
						|
{
 | 
						|
public:
 | 
						|
    virtual ~GRAYwriter() {}
 | 
						|
 | 
						|
    virtual void write(Mat& gray, int row, int col, const uchar& val)
 | 
						|
    {
 | 
						|
        gray.at<uchar>(row, col) = val;
 | 
						|
    }
 | 
						|
 | 
						|
    virtual int channels() { return 1; }
 | 
						|
 | 
						|
    static GRAYwriter* getWriter(int code);
 | 
						|
};
 | 
						|
 | 
						|
class YUVwriter
 | 
						|
{
 | 
						|
public:
 | 
						|
    virtual ~YUVwriter() {}
 | 
						|
 | 
						|
    virtual void write(Mat& yuv, int row, int col, const YUV& val) = 0;
 | 
						|
    virtual int channels() = 0;
 | 
						|
    virtual Size size(Size imgSize) = 0;
 | 
						|
 | 
						|
    virtual bool requiresEvenHeight() { return true; }
 | 
						|
    virtual bool requiresEvenWidth() { return true; }
 | 
						|
 | 
						|
    static YUVwriter* getWriter(int code);
 | 
						|
};
 | 
						|
 | 
						|
class RGB888Writer : public RGBwriter
 | 
						|
{
 | 
						|
    void write(Mat& rgb, int row, int col, const RGB& val)
 | 
						|
    {
 | 
						|
        rgb.at<Vec3b>(row, col) = val;
 | 
						|
    }
 | 
						|
 | 
						|
    int channels() { return 3; }
 | 
						|
};
 | 
						|
 | 
						|
class BGR888Writer : public RGBwriter
 | 
						|
{
 | 
						|
    void write(Mat& rgb, int row, int col, const RGB& val)
 | 
						|
    {
 | 
						|
        Vec3b tmp(val[2], val[1], val[0]);
 | 
						|
        rgb.at<Vec3b>(row, col) = tmp;
 | 
						|
    }
 | 
						|
 | 
						|
    int channels() { return 3; }
 | 
						|
};
 | 
						|
 | 
						|
class RGBA8888Writer : public RGBwriter
 | 
						|
{
 | 
						|
    void write(Mat& rgb, int row, int col, const RGB& val)
 | 
						|
    {
 | 
						|
        Vec4b tmp(val[0], val[1], val[2], 255);
 | 
						|
        rgb.at<Vec4b>(row, col) = tmp;
 | 
						|
    }
 | 
						|
 | 
						|
    int channels() { return 4; }
 | 
						|
};
 | 
						|
 | 
						|
class BGRA8888Writer : public RGBwriter
 | 
						|
{
 | 
						|
    void write(Mat& rgb, int row, int col, const RGB& val)
 | 
						|
    {
 | 
						|
        Vec4b tmp(val[2], val[1], val[0], 255);
 | 
						|
        rgb.at<Vec4b>(row, col) = tmp;
 | 
						|
    }
 | 
						|
 | 
						|
    int channels() { return 4; }
 | 
						|
};
 | 
						|
 | 
						|
class YUV420pWriter: public YUVwriter
 | 
						|
{
 | 
						|
    int channels() { return 1; }
 | 
						|
    Size size(Size imgSize) { return Size(imgSize.width, imgSize.height + imgSize.height/2); }
 | 
						|
};
 | 
						|
 | 
						|
class YV12Writer: public YUV420pWriter
 | 
						|
{
 | 
						|
    void write(Mat& yuv, int row, int col, const YUV& val)
 | 
						|
    {
 | 
						|
        int h = yuv.rows * 2 / 3;
 | 
						|
 | 
						|
        yuv.ptr<uchar>(row)[col] = val[0];
 | 
						|
        if( row % 2 == 0 && col % 2 == 0 )
 | 
						|
        {
 | 
						|
            yuv.ptr<uchar>(h + row/4)[col/2 + ((row/2) % 2) * (yuv.cols/2)] = val[2];
 | 
						|
            yuv.ptr<uchar>(h + (row/2 + h/2)/2)[col/2 + ((row/2 + h/2) % 2) * (yuv.cols/2)] = val[1];
 | 
						|
        }
 | 
						|
    }
 | 
						|
};
 | 
						|
 | 
						|
class I420Writer: public YUV420pWriter
 | 
						|
{
 | 
						|
    void write(Mat& yuv, int row, int col, const YUV& val)
 | 
						|
    {
 | 
						|
        int h = yuv.rows * 2 / 3;
 | 
						|
 | 
						|
        yuv.ptr<uchar>(row)[col] = val[0];
 | 
						|
        if( row % 2 == 0 && col % 2 == 0 )
 | 
						|
        {
 | 
						|
            yuv.ptr<uchar>(h + row/4)[col/2 + ((row/2) % 2) * (yuv.cols/2)] = val[1];
 | 
						|
            yuv.ptr<uchar>(h + (row/2 + h/2)/2)[col/2 + ((row/2 + h/2) % 2) * (yuv.cols/2)] = val[2];
 | 
						|
        }
 | 
						|
    }
 | 
						|
};
 | 
						|
 | 
						|
class YUV420Reader: public YUVreader
 | 
						|
{
 | 
						|
    int channels() { return 1; }
 | 
						|
    Size size(Size imgSize) { return Size(imgSize.width, imgSize.height * 3 / 2); }
 | 
						|
};
 | 
						|
 | 
						|
class YUV422Reader: public YUVreader
 | 
						|
{
 | 
						|
    int channels() { return 2; }
 | 
						|
    Size size(Size imgSize) { return imgSize; }
 | 
						|
    bool requiresEvenHeight() { return false; }
 | 
						|
};
 | 
						|
 | 
						|
class NV21Reader: public YUV420Reader
 | 
						|
{
 | 
						|
    YUV read(const Mat& yuv, int row, int col)
 | 
						|
    {
 | 
						|
        uchar y = yuv.ptr<uchar>(row)[col];
 | 
						|
        uchar u = yuv.ptr<uchar>(yuv.rows * 2 / 3 + row/2)[(col/2)*2 + 1];
 | 
						|
        uchar v = yuv.ptr<uchar>(yuv.rows * 2 / 3 + row/2)[(col/2)*2];
 | 
						|
 | 
						|
        return YUV(y, u, v);
 | 
						|
    }
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
struct NV12Reader: public YUV420Reader
 | 
						|
{
 | 
						|
    YUV read(const Mat& yuv, int row, int col)
 | 
						|
    {
 | 
						|
        uchar y = yuv.ptr<uchar>(row)[col];
 | 
						|
        uchar u = yuv.ptr<uchar>(yuv.rows * 2 / 3 + row/2)[(col/2)*2];
 | 
						|
        uchar v = yuv.ptr<uchar>(yuv.rows * 2 / 3 + row/2)[(col/2)*2 + 1];
 | 
						|
 | 
						|
        return YUV(y, u, v);
 | 
						|
    }
 | 
						|
};
 | 
						|
 | 
						|
class YV12Reader: public YUV420Reader
 | 
						|
{
 | 
						|
    YUV read(const Mat& yuv, int row, int col)
 | 
						|
    {
 | 
						|
        int h = yuv.rows * 2 / 3;
 | 
						|
        uchar y = yuv.ptr<uchar>(row)[col];
 | 
						|
        uchar u = yuv.ptr<uchar>(h + (row/2 + h/2)/2)[col/2 + ((row/2 + h/2) % 2) * (yuv.cols/2)];
 | 
						|
        uchar v = yuv.ptr<uchar>(h + row/4)[col/2 + ((row/2) % 2) * (yuv.cols/2)];
 | 
						|
 | 
						|
        return YUV(y, u, v);
 | 
						|
    }
 | 
						|
};
 | 
						|
 | 
						|
class IYUVReader: public YUV420Reader
 | 
						|
{
 | 
						|
    YUV read(const Mat& yuv, int row, int col)
 | 
						|
    {
 | 
						|
        int h = yuv.rows * 2 / 3;
 | 
						|
        uchar y = yuv.ptr<uchar>(row)[col];
 | 
						|
        uchar u = yuv.ptr<uchar>(h + row/4)[col/2 + ((row/2) % 2) * (yuv.cols/2)];
 | 
						|
        uchar v = yuv.ptr<uchar>(h + (row/2 + h/2)/2)[col/2 + ((row/2 + h/2) % 2) * (yuv.cols/2)];
 | 
						|
 | 
						|
        return YUV(y, u, v);
 | 
						|
    }
 | 
						|
};
 | 
						|
 | 
						|
class UYVYReader: public YUV422Reader
 | 
						|
{
 | 
						|
    YUV read(const Mat& yuv, int row, int col)
 | 
						|
    {
 | 
						|
        uchar y = yuv.ptr<Vec2b>(row)[col][1];
 | 
						|
        uchar u = yuv.ptr<Vec2b>(row)[(col/2)*2][0];
 | 
						|
        uchar v = yuv.ptr<Vec2b>(row)[(col/2)*2 + 1][0];
 | 
						|
 | 
						|
        return YUV(y, u, v);
 | 
						|
    }
 | 
						|
};
 | 
						|
 | 
						|
class YUY2Reader: public YUV422Reader
 | 
						|
{
 | 
						|
    YUV read(const Mat& yuv, int row, int col)
 | 
						|
    {
 | 
						|
        uchar y = yuv.ptr<Vec2b>(row)[col][0];
 | 
						|
        uchar u = yuv.ptr<Vec2b>(row)[(col/2)*2][1];
 | 
						|
        uchar v = yuv.ptr<Vec2b>(row)[(col/2)*2 + 1][1];
 | 
						|
 | 
						|
        return YUV(y, u, v);
 | 
						|
    }
 | 
						|
};
 | 
						|
 | 
						|
class YVYUReader: public YUV422Reader
 | 
						|
{
 | 
						|
    YUV read(const Mat& yuv, int row, int col)
 | 
						|
    {
 | 
						|
        uchar y = yuv.ptr<Vec2b>(row)[col][0];
 | 
						|
        uchar u = yuv.ptr<Vec2b>(row)[(col/2)*2 + 1][1];
 | 
						|
        uchar v = yuv.ptr<Vec2b>(row)[(col/2)*2][1];
 | 
						|
 | 
						|
        return YUV(y, u, v);
 | 
						|
    }
 | 
						|
};
 | 
						|
 | 
						|
class YUV888Reader : public YUVreader
 | 
						|
{
 | 
						|
    YUV read(const Mat& yuv, int row, int col)
 | 
						|
    {
 | 
						|
        return yuv.at<YUV>(row, col);
 | 
						|
    }
 | 
						|
 | 
						|
    int channels() { return 3; }
 | 
						|
    Size size(Size imgSize) { return imgSize; }
 | 
						|
    bool requiresEvenHeight() { return false; }
 | 
						|
    bool requiresEvenWidth() { return false; }
 | 
						|
};
 | 
						|
 | 
						|
class RGB888Reader : public RGBreader
 | 
						|
{
 | 
						|
    RGB read(const Mat& rgb, int row, int col)
 | 
						|
    {
 | 
						|
        return rgb.at<RGB>(row, col);
 | 
						|
    }
 | 
						|
 | 
						|
    int channels() { return 3; }
 | 
						|
};
 | 
						|
 | 
						|
class BGR888Reader : public RGBreader
 | 
						|
{
 | 
						|
    RGB read(const Mat& rgb, int row, int col)
 | 
						|
    {
 | 
						|
        RGB tmp = rgb.at<RGB>(row, col);
 | 
						|
        return RGB(tmp[2], tmp[1], tmp[0]);
 | 
						|
    }
 | 
						|
 | 
						|
    int channels() { return 3; }
 | 
						|
};
 | 
						|
 | 
						|
class RGBA8888Reader : public RGBreader
 | 
						|
{
 | 
						|
    RGB read(const Mat& rgb, int row, int col)
 | 
						|
    {
 | 
						|
        Vec4b rgba = rgb.at<Vec4b>(row, col);
 | 
						|
        return RGB(rgba[0], rgba[1], rgba[2]);
 | 
						|
    }
 | 
						|
 | 
						|
    int channels() { return 4; }
 | 
						|
};
 | 
						|
 | 
						|
class BGRA8888Reader : public RGBreader
 | 
						|
{
 | 
						|
    RGB read(const Mat& rgb, int row, int col)
 | 
						|
    {
 | 
						|
        Vec4b rgba = rgb.at<Vec4b>(row, col);
 | 
						|
        return RGB(rgba[2], rgba[1], rgba[0]);
 | 
						|
    }
 | 
						|
 | 
						|
    int channels() { return 4; }
 | 
						|
};
 | 
						|
 | 
						|
class YUV2RGB_Converter
 | 
						|
{
 | 
						|
public:
 | 
						|
    RGB convert(YUV yuv)
 | 
						|
    {
 | 
						|
        int y = std::max(0, yuv[0] - 16);
 | 
						|
        int u = yuv[1] - 128;
 | 
						|
        int v = yuv[2] - 128;
 | 
						|
        uchar r = saturate_cast<uchar>(1.164f * y + 1.596f * v);
 | 
						|
        uchar g = saturate_cast<uchar>(1.164f * y - 0.813f * v - 0.391f * u);
 | 
						|
        uchar b = saturate_cast<uchar>(1.164f * y + 2.018f * u);
 | 
						|
 | 
						|
        return RGB(r, g, b);
 | 
						|
    }
 | 
						|
};
 | 
						|
 | 
						|
class YUV2GRAY_Converter
 | 
						|
{
 | 
						|
public:
 | 
						|
    uchar convert(YUV yuv)
 | 
						|
    {
 | 
						|
        return yuv[0];
 | 
						|
    }
 | 
						|
};
 | 
						|
 | 
						|
class RGB2YUV_Converter
 | 
						|
{
 | 
						|
public:
 | 
						|
    YUV convert(RGB rgb)
 | 
						|
    {
 | 
						|
        int r = rgb[0];
 | 
						|
        int g = rgb[1];
 | 
						|
        int b = rgb[2];
 | 
						|
 | 
						|
        uchar y = saturate_cast<uchar>((int)( 0.257f*r + 0.504f*g + 0.098f*b + 0.5f) + 16);
 | 
						|
        uchar u = saturate_cast<uchar>((int)(-0.148f*r - 0.291f*g + 0.439f*b + 0.5f) + 128);
 | 
						|
        uchar v = saturate_cast<uchar>((int)( 0.439f*r - 0.368f*g - 0.071f*b + 0.5f) + 128);
 | 
						|
 | 
						|
        return YUV(y, u, v);
 | 
						|
    }
 | 
						|
};
 | 
						|
 | 
						|
YUVreader* YUVreader::getReader(int code)
 | 
						|
{
 | 
						|
    switch(code)
 | 
						|
    {
 | 
						|
    case CV_YUV2RGB_NV12:
 | 
						|
    case CV_YUV2BGR_NV12:
 | 
						|
    case CV_YUV2RGBA_NV12:
 | 
						|
    case CV_YUV2BGRA_NV12:
 | 
						|
        return new NV12Reader();
 | 
						|
    case CV_YUV2RGB_NV21:
 | 
						|
    case CV_YUV2BGR_NV21:
 | 
						|
    case CV_YUV2RGBA_NV21:
 | 
						|
    case CV_YUV2BGRA_NV21:
 | 
						|
        return new NV21Reader();
 | 
						|
    case CV_YUV2RGB_YV12:
 | 
						|
    case CV_YUV2BGR_YV12:
 | 
						|
    case CV_YUV2RGBA_YV12:
 | 
						|
    case CV_YUV2BGRA_YV12:
 | 
						|
        return new YV12Reader();
 | 
						|
    case CV_YUV2RGB_IYUV:
 | 
						|
    case CV_YUV2BGR_IYUV:
 | 
						|
    case CV_YUV2RGBA_IYUV:
 | 
						|
    case CV_YUV2BGRA_IYUV:
 | 
						|
        return new IYUVReader();
 | 
						|
    case CV_YUV2RGB_UYVY:
 | 
						|
    case CV_YUV2BGR_UYVY:
 | 
						|
    case CV_YUV2RGBA_UYVY:
 | 
						|
    case CV_YUV2BGRA_UYVY:
 | 
						|
        return new UYVYReader();
 | 
						|
    //case CV_YUV2RGB_VYUY = 109,
 | 
						|
    //case CV_YUV2BGR_VYUY = 110,
 | 
						|
    //case CV_YUV2RGBA_VYUY = 113,
 | 
						|
    //case CV_YUV2BGRA_VYUY = 114,
 | 
						|
    //    return ??
 | 
						|
    case CV_YUV2RGB_YUY2:
 | 
						|
    case CV_YUV2BGR_YUY2:
 | 
						|
    case CV_YUV2RGBA_YUY2:
 | 
						|
    case CV_YUV2BGRA_YUY2:
 | 
						|
        return new YUY2Reader();
 | 
						|
    case CV_YUV2RGB_YVYU:
 | 
						|
    case CV_YUV2BGR_YVYU:
 | 
						|
    case CV_YUV2RGBA_YVYU:
 | 
						|
    case CV_YUV2BGRA_YVYU:
 | 
						|
        return new YVYUReader();
 | 
						|
    case CV_YUV2GRAY_420:
 | 
						|
        return new NV21Reader();
 | 
						|
    case CV_YUV2GRAY_UYVY:
 | 
						|
        return new UYVYReader();
 | 
						|
    case CV_YUV2GRAY_YUY2:
 | 
						|
        return new YUY2Reader();
 | 
						|
    case CV_YUV2BGR:
 | 
						|
    case CV_YUV2RGB:
 | 
						|
        return new YUV888Reader();
 | 
						|
    default:
 | 
						|
        return 0;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
RGBreader* RGBreader::getReader(int code)
 | 
						|
{
 | 
						|
    switch(code)
 | 
						|
    {
 | 
						|
    case CV_RGB2YUV_YV12:
 | 
						|
    case CV_RGB2YUV_I420:
 | 
						|
        return new RGB888Reader();
 | 
						|
    case CV_BGR2YUV_YV12:
 | 
						|
    case CV_BGR2YUV_I420:
 | 
						|
        return new BGR888Reader();
 | 
						|
    case CV_RGBA2YUV_I420:
 | 
						|
    case CV_RGBA2YUV_YV12:
 | 
						|
        return new RGBA8888Reader();
 | 
						|
    case CV_BGRA2YUV_YV12:
 | 
						|
    case CV_BGRA2YUV_I420:
 | 
						|
        return new BGRA8888Reader();
 | 
						|
    default:
 | 
						|
        return 0;
 | 
						|
    };
 | 
						|
}
 | 
						|
 | 
						|
RGBwriter* RGBwriter::getWriter(int code)
 | 
						|
{
 | 
						|
    switch(code)
 | 
						|
    {
 | 
						|
    case CV_YUV2RGB_NV12:
 | 
						|
    case CV_YUV2RGB_NV21:
 | 
						|
    case CV_YUV2RGB_YV12:
 | 
						|
    case CV_YUV2RGB_IYUV:
 | 
						|
    case CV_YUV2RGB_UYVY:
 | 
						|
    //case CV_YUV2RGB_VYUY:
 | 
						|
    case CV_YUV2RGB_YUY2:
 | 
						|
    case CV_YUV2RGB_YVYU:
 | 
						|
    case CV_YUV2RGB:
 | 
						|
        return new RGB888Writer();
 | 
						|
    case CV_YUV2BGR_NV12:
 | 
						|
    case CV_YUV2BGR_NV21:
 | 
						|
    case CV_YUV2BGR_YV12:
 | 
						|
    case CV_YUV2BGR_IYUV:
 | 
						|
    case CV_YUV2BGR_UYVY:
 | 
						|
    //case CV_YUV2BGR_VYUY:
 | 
						|
    case CV_YUV2BGR_YUY2:
 | 
						|
    case CV_YUV2BGR_YVYU:
 | 
						|
    case CV_YUV2BGR:
 | 
						|
        return new BGR888Writer();
 | 
						|
    case CV_YUV2RGBA_NV12:
 | 
						|
    case CV_YUV2RGBA_NV21:
 | 
						|
    case CV_YUV2RGBA_YV12:
 | 
						|
    case CV_YUV2RGBA_IYUV:
 | 
						|
    case CV_YUV2RGBA_UYVY:
 | 
						|
    //case CV_YUV2RGBA_VYUY:
 | 
						|
    case CV_YUV2RGBA_YUY2:
 | 
						|
    case CV_YUV2RGBA_YVYU:
 | 
						|
        return new RGBA8888Writer();
 | 
						|
    case CV_YUV2BGRA_NV12:
 | 
						|
    case CV_YUV2BGRA_NV21:
 | 
						|
    case CV_YUV2BGRA_YV12:
 | 
						|
    case CV_YUV2BGRA_IYUV:
 | 
						|
    case CV_YUV2BGRA_UYVY:
 | 
						|
    //case CV_YUV2BGRA_VYUY:
 | 
						|
    case CV_YUV2BGRA_YUY2:
 | 
						|
    case CV_YUV2BGRA_YVYU:
 | 
						|
        return new BGRA8888Writer();
 | 
						|
    default:
 | 
						|
        return 0;
 | 
						|
    };
 | 
						|
}
 | 
						|
 | 
						|
GRAYwriter* GRAYwriter::getWriter(int code)
 | 
						|
{
 | 
						|
    switch(code)
 | 
						|
    {
 | 
						|
    case CV_YUV2GRAY_420:
 | 
						|
    case CV_YUV2GRAY_UYVY:
 | 
						|
    case CV_YUV2GRAY_YUY2:
 | 
						|
        return new GRAYwriter();
 | 
						|
    default:
 | 
						|
        return 0;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
YUVwriter* YUVwriter::getWriter(int code)
 | 
						|
{
 | 
						|
    switch(code)
 | 
						|
    {
 | 
						|
    case CV_RGB2YUV_YV12:
 | 
						|
    case CV_BGR2YUV_YV12:
 | 
						|
    case CV_RGBA2YUV_YV12:
 | 
						|
    case CV_BGRA2YUV_YV12:
 | 
						|
        return new YV12Writer();
 | 
						|
    case CV_RGB2YUV_I420:
 | 
						|
    case CV_BGR2YUV_I420:
 | 
						|
    case CV_RGBA2YUV_I420:
 | 
						|
    case CV_BGRA2YUV_I420:
 | 
						|
        return new I420Writer();
 | 
						|
    default:
 | 
						|
        return 0;
 | 
						|
    };
 | 
						|
}
 | 
						|
 | 
						|
template<class convertor>
 | 
						|
void referenceYUV2RGB(const Mat& yuv, Mat& rgb, YUVreader* yuvReader, RGBwriter* rgbWriter)
 | 
						|
{
 | 
						|
    convertor cvt;
 | 
						|
 | 
						|
    for(int row = 0; row < rgb.rows; ++row)
 | 
						|
        for(int col = 0; col < rgb.cols; ++col)
 | 
						|
            rgbWriter->write(rgb, row, col, cvt.convert(yuvReader->read(yuv, row, col)));
 | 
						|
}
 | 
						|
 | 
						|
template<class convertor>
 | 
						|
void referenceYUV2GRAY(const Mat& yuv, Mat& rgb, YUVreader* yuvReader, GRAYwriter* grayWriter)
 | 
						|
{
 | 
						|
    convertor cvt;
 | 
						|
 | 
						|
    for(int row = 0; row < rgb.rows; ++row)
 | 
						|
        for(int col = 0; col < rgb.cols; ++col)
 | 
						|
            grayWriter->write(rgb, row, col, cvt.convert(yuvReader->read(yuv, row, col)));
 | 
						|
}
 | 
						|
 | 
						|
template<class convertor>
 | 
						|
void referenceRGB2YUV(const Mat& rgb, Mat& yuv, RGBreader* rgbReader, YUVwriter* yuvWriter)
 | 
						|
{
 | 
						|
    convertor cvt;
 | 
						|
 | 
						|
    for(int row = 0; row < rgb.rows; ++row)
 | 
						|
        for(int col = 0; col < rgb.cols; ++col)
 | 
						|
            yuvWriter->write(yuv, row, col, cvt.convert(rgbReader->read(rgb, row, col)));
 | 
						|
}
 | 
						|
 | 
						|
struct ConversionYUV
 | 
						|
{
 | 
						|
    ConversionYUV( const int code )
 | 
						|
    {
 | 
						|
        yuvReader_  = YUVreader :: getReader(code);
 | 
						|
        yuvWriter_  = YUVwriter :: getWriter(code);
 | 
						|
        rgbReader_  = RGBreader :: getReader(code);
 | 
						|
        rgbWriter_  = RGBwriter :: getWriter(code);
 | 
						|
        grayWriter_ = GRAYwriter:: getWriter(code);
 | 
						|
    }
 | 
						|
 | 
						|
    int getDcn()
 | 
						|
    {
 | 
						|
        return (rgbWriter_ != 0) ? rgbWriter_->channels() : ((grayWriter_ != 0) ? grayWriter_->channels() : yuvWriter_->channels());
 | 
						|
    }
 | 
						|
 | 
						|
    int getScn()
 | 
						|
    {
 | 
						|
        return (yuvReader_ != 0) ? yuvReader_->channels() : rgbReader_->channels();
 | 
						|
    }
 | 
						|
 | 
						|
    Size getSrcSize( const Size& imgSize )
 | 
						|
    {
 | 
						|
        return (yuvReader_ != 0) ? yuvReader_->size(imgSize) : imgSize;
 | 
						|
    }
 | 
						|
 | 
						|
    Size getDstSize( const Size& imgSize )
 | 
						|
    {
 | 
						|
        return (yuvWriter_ != 0) ? yuvWriter_->size(imgSize) : imgSize;
 | 
						|
    }
 | 
						|
 | 
						|
    bool requiresEvenHeight()
 | 
						|
    {
 | 
						|
        return (yuvReader_ != 0) ? yuvReader_->requiresEvenHeight() : ((yuvWriter_ != 0) ? yuvWriter_->requiresEvenHeight() : false);
 | 
						|
    }
 | 
						|
 | 
						|
    bool requiresEvenWidth()
 | 
						|
    {
 | 
						|
        return (yuvReader_ != 0) ? yuvReader_->requiresEvenWidth() : ((yuvWriter_ != 0) ? yuvWriter_->requiresEvenWidth() : false);
 | 
						|
    }
 | 
						|
 | 
						|
    YUVreader*  yuvReader_;
 | 
						|
    YUVwriter*  yuvWriter_;
 | 
						|
    RGBreader*  rgbReader_;
 | 
						|
    RGBwriter*  rgbWriter_;
 | 
						|
    GRAYwriter* grayWriter_;
 | 
						|
};
 | 
						|
 | 
						|
CV_ENUM(YUVCVTS, CV_YUV2RGB_NV12, CV_YUV2BGR_NV12, CV_YUV2RGB_NV21, CV_YUV2BGR_NV21,
 | 
						|
                 CV_YUV2RGBA_NV12, CV_YUV2BGRA_NV12, CV_YUV2RGBA_NV21, CV_YUV2BGRA_NV21,
 | 
						|
                 CV_YUV2RGB_YV12, CV_YUV2BGR_YV12, CV_YUV2RGB_IYUV, CV_YUV2BGR_IYUV,
 | 
						|
                 CV_YUV2RGBA_YV12, CV_YUV2BGRA_YV12, CV_YUV2RGBA_IYUV, CV_YUV2BGRA_IYUV,
 | 
						|
                 CV_YUV2RGB_UYVY, CV_YUV2BGR_UYVY, CV_YUV2RGBA_UYVY, CV_YUV2BGRA_UYVY,
 | 
						|
                 CV_YUV2RGB_YUY2, CV_YUV2BGR_YUY2, CV_YUV2RGB_YVYU, CV_YUV2BGR_YVYU,
 | 
						|
                 CV_YUV2RGBA_YUY2, CV_YUV2BGRA_YUY2, CV_YUV2RGBA_YVYU, CV_YUV2BGRA_YVYU,
 | 
						|
                 CV_YUV2GRAY_420, CV_YUV2GRAY_UYVY, CV_YUV2GRAY_YUY2,
 | 
						|
                 CV_YUV2BGR, CV_YUV2RGB, CV_RGB2YUV_YV12, CV_BGR2YUV_YV12, CV_RGBA2YUV_YV12,
 | 
						|
                 CV_BGRA2YUV_YV12, CV_RGB2YUV_I420, CV_BGR2YUV_I420, CV_RGBA2YUV_I420, CV_BGRA2YUV_I420)
 | 
						|
 | 
						|
typedef ::testing::TestWithParam<YUVCVTS> Imgproc_ColorYUV;
 | 
						|
 | 
						|
TEST_P(Imgproc_ColorYUV, accuracy)
 | 
						|
{
 | 
						|
    int code = GetParam();
 | 
						|
    RNG& random = theRNG();
 | 
						|
 | 
						|
    ConversionYUV cvt(code);
 | 
						|
 | 
						|
    const int scn = cvt.getScn();
 | 
						|
    const int dcn = cvt.getDcn();
 | 
						|
    for(int iter = 0; iter < 30; ++iter)
 | 
						|
    {
 | 
						|
        Size sz(random.uniform(1, 641), random.uniform(1, 481));
 | 
						|
 | 
						|
        if(cvt.requiresEvenWidth())  sz.width  += sz.width % 2;
 | 
						|
        if(cvt.requiresEvenHeight()) sz.height += sz.height % 2;
 | 
						|
 | 
						|
        Size srcSize = cvt.getSrcSize(sz);
 | 
						|
        Mat src = Mat(srcSize.height, srcSize.width * scn, CV_8UC1).reshape(scn);
 | 
						|
 | 
						|
        Size dstSize = cvt.getDstSize(sz);
 | 
						|
        Mat dst = Mat(dstSize.height, dstSize.width * dcn, CV_8UC1).reshape(dcn);
 | 
						|
        Mat gold(dstSize, CV_8UC(dcn));
 | 
						|
 | 
						|
        random.fill(src, RNG::UNIFORM, 0, 256);
 | 
						|
 | 
						|
        if(cvt.rgbWriter_)
 | 
						|
            referenceYUV2RGB<YUV2RGB_Converter>  (src, gold, cvt.yuvReader_, cvt.rgbWriter_);
 | 
						|
        else if(cvt.grayWriter_)
 | 
						|
            referenceYUV2GRAY<YUV2GRAY_Converter>(src, gold, cvt.yuvReader_, cvt.grayWriter_);
 | 
						|
        else if(cvt.yuvWriter_)
 | 
						|
            referenceRGB2YUV<RGB2YUV_Converter>  (src, gold, cvt.rgbReader_, cvt.yuvWriter_);
 | 
						|
 | 
						|
        cv::cvtColor(src, dst, code, -1);
 | 
						|
 | 
						|
        EXPECT_EQ(0, countOfDifferencies(gold, dst));
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
TEST_P(Imgproc_ColorYUV, roi_accuracy)
 | 
						|
{
 | 
						|
    int code = GetParam();
 | 
						|
    RNG& random = theRNG();
 | 
						|
 | 
						|
    ConversionYUV cvt(code);
 | 
						|
 | 
						|
    const int scn = cvt.getScn();
 | 
						|
    const int dcn = cvt.getDcn();
 | 
						|
    for(int iter = 0; iter < 30; ++iter)
 | 
						|
    {
 | 
						|
        Size sz(random.uniform(1, 641), random.uniform(1, 481));
 | 
						|
 | 
						|
        if(cvt.requiresEvenWidth())  sz.width  += sz.width % 2;
 | 
						|
        if(cvt.requiresEvenHeight()) sz.height += sz.height % 2;
 | 
						|
 | 
						|
        int roi_offset_top = random.uniform(0, 6);
 | 
						|
        int roi_offset_bottom = random.uniform(0, 6);
 | 
						|
        int roi_offset_left = random.uniform(0, 6);
 | 
						|
        int roi_offset_right = random.uniform(0, 6);
 | 
						|
 | 
						|
        Size srcSize = cvt.getSrcSize(sz);
 | 
						|
        Mat src_full(srcSize.height + roi_offset_top + roi_offset_bottom, srcSize.width + roi_offset_left + roi_offset_right, CV_8UC(scn));
 | 
						|
 | 
						|
        Size dstSize = cvt.getDstSize(sz);
 | 
						|
        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));
 | 
						|
        Mat gold_full(dst_full.size(), CV_8UC(dcn), Scalar::all(0));
 | 
						|
 | 
						|
        random.fill(src_full, RNG::UNIFORM, 0, 256);
 | 
						|
 | 
						|
        Mat src = src_full(Range(roi_offset_top, roi_offset_top + srcSize.height), Range(roi_offset_left, roi_offset_left + srcSize.width));
 | 
						|
        Mat dst = dst_full(Range(roi_offset_left, roi_offset_left + dstSize.height), Range(roi_offset_top, roi_offset_top + dstSize.width));
 | 
						|
        Mat gold = gold_full(Range(roi_offset_left, roi_offset_left + dstSize.height), Range(roi_offset_top, roi_offset_top + dstSize.width));
 | 
						|
 | 
						|
        if(cvt.rgbWriter_)
 | 
						|
            referenceYUV2RGB<YUV2RGB_Converter>  (src, gold, cvt.yuvReader_, cvt.rgbWriter_);
 | 
						|
        else if(cvt.grayWriter_)
 | 
						|
            referenceYUV2GRAY<YUV2GRAY_Converter>(src, gold, cvt.yuvReader_, cvt.grayWriter_);
 | 
						|
        else if(cvt.yuvWriter_)
 | 
						|
            referenceRGB2YUV<RGB2YUV_Converter>  (src, gold, cvt.rgbReader_, cvt.yuvWriter_);
 | 
						|
 | 
						|
        cv::cvtColor(src, dst, code, -1);
 | 
						|
 | 
						|
        EXPECT_EQ(0, countOfDifferencies(gold_full, dst_full));
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
INSTANTIATE_TEST_CASE_P(cvt420, Imgproc_ColorYUV,
 | 
						|
    ::testing::Values((int)CV_YUV2RGB_NV12, (int)CV_YUV2BGR_NV12, (int)CV_YUV2RGB_NV21, (int)CV_YUV2BGR_NV21,
 | 
						|
                      (int)CV_YUV2RGBA_NV12, (int)CV_YUV2BGRA_NV12, (int)CV_YUV2RGBA_NV21, (int)CV_YUV2BGRA_NV21,
 | 
						|
                      (int)CV_YUV2RGB_YV12, (int)CV_YUV2BGR_YV12, (int)CV_YUV2RGB_IYUV, (int)CV_YUV2BGR_IYUV,
 | 
						|
                      (int)CV_YUV2RGBA_YV12, (int)CV_YUV2BGRA_YV12, (int)CV_YUV2RGBA_IYUV, (int)CV_YUV2BGRA_IYUV,
 | 
						|
                      (int)CV_YUV2GRAY_420, (int)CV_RGB2YUV_YV12, (int)CV_BGR2YUV_YV12, (int)CV_RGBA2YUV_YV12,
 | 
						|
                      (int)CV_BGRA2YUV_YV12, (int)CV_RGB2YUV_I420, (int)CV_BGR2YUV_I420, (int)CV_RGBA2YUV_I420,
 | 
						|
                      (int)CV_BGRA2YUV_I420));
 | 
						|
 | 
						|
INSTANTIATE_TEST_CASE_P(cvt422, Imgproc_ColorYUV,
 | 
						|
    ::testing::Values((int)CV_YUV2RGB_UYVY, (int)CV_YUV2BGR_UYVY, (int)CV_YUV2RGBA_UYVY, (int)CV_YUV2BGRA_UYVY,
 | 
						|
                      (int)CV_YUV2RGB_YUY2, (int)CV_YUV2BGR_YUY2, (int)CV_YUV2RGB_YVYU, (int)CV_YUV2BGR_YVYU,
 | 
						|
                      (int)CV_YUV2RGBA_YUY2, (int)CV_YUV2BGRA_YUY2, (int)CV_YUV2RGBA_YVYU, (int)CV_YUV2BGRA_YVYU,
 | 
						|
                      (int)CV_YUV2GRAY_UYVY, (int)CV_YUV2GRAY_YUY2));
 |