mirror of
https://github.com/opencv/opencv.git
synced 2024-11-28 21:20:18 +08:00
Fixed conversions from YV12 and IYUV on non-continuous input. Added accuracy and performance tests.
This commit is contained in:
parent
a22641aa9c
commit
470f6fafeb
@ -9,207 +9,214 @@ using std::tr1::get;
|
||||
//extra color conversions supported implicitly
|
||||
enum
|
||||
{
|
||||
CX_BGRA2HLS = CV_COLORCVT_MAX + CV_BGR2HLS,
|
||||
CX_BGRA2HLS_FULL = CV_COLORCVT_MAX + CV_BGR2HLS_FULL,
|
||||
CX_BGRA2HSV = CV_COLORCVT_MAX + CV_BGR2HSV,
|
||||
CX_BGRA2HSV_FULL = CV_COLORCVT_MAX + CV_BGR2HSV_FULL,
|
||||
CX_BGRA2Lab = CV_COLORCVT_MAX + CV_BGR2Lab,
|
||||
CX_BGRA2Luv = CV_COLORCVT_MAX + CV_BGR2Luv,
|
||||
CX_BGRA2XYZ = CV_COLORCVT_MAX + CV_BGR2XYZ,
|
||||
CX_BGRA2YCrCb = CV_COLORCVT_MAX + CV_BGR2YCrCb,
|
||||
CX_BGRA2YUV = CV_COLORCVT_MAX + CV_BGR2YUV,
|
||||
CX_HLS2BGRA = CV_COLORCVT_MAX + CV_HLS2BGR,
|
||||
CX_HLS2BGRA_FULL = CV_COLORCVT_MAX + CV_HLS2BGR_FULL,
|
||||
CX_HLS2RGBA = CV_COLORCVT_MAX + CV_HLS2RGB,
|
||||
CX_HLS2RGBA_FULL = CV_COLORCVT_MAX + CV_HLS2RGB_FULL,
|
||||
CX_HSV2BGRA = CV_COLORCVT_MAX + CV_HSV2BGR,
|
||||
CX_HSV2BGRA_FULL = CV_COLORCVT_MAX + CV_HSV2BGR_FULL,
|
||||
CX_HSV2RGBA = CV_COLORCVT_MAX + CV_HSV2RGB,
|
||||
CX_HSV2RGBA_FULL = CV_COLORCVT_MAX + CV_HSV2RGB_FULL,
|
||||
CX_Lab2BGRA = CV_COLORCVT_MAX + CV_Lab2BGR,
|
||||
CX_Lab2LBGRA = CV_COLORCVT_MAX + CV_Lab2LBGR,
|
||||
CX_Lab2LRGBA = CV_COLORCVT_MAX + CV_Lab2LRGB,
|
||||
CX_Lab2RGBA = CV_COLORCVT_MAX + CV_Lab2RGB,
|
||||
CX_LBGRA2Lab = CV_COLORCVT_MAX + CV_LBGR2Lab,
|
||||
CX_LBGRA2Luv = CV_COLORCVT_MAX + CV_LBGR2Luv,
|
||||
CX_LRGBA2Lab = CV_COLORCVT_MAX + CV_LRGB2Lab,
|
||||
CX_LRGBA2Luv = CV_COLORCVT_MAX + CV_LRGB2Luv,
|
||||
CX_Luv2BGRA = CV_COLORCVT_MAX + CV_Luv2BGR,
|
||||
CX_Luv2LBGRA = CV_COLORCVT_MAX + CV_Luv2LBGR,
|
||||
CX_Luv2LRGBA = CV_COLORCVT_MAX + CV_Luv2LRGB,
|
||||
CX_Luv2RGBA = CV_COLORCVT_MAX + CV_Luv2RGB,
|
||||
CX_RGBA2HLS = CV_COLORCVT_MAX + CV_RGB2HLS,
|
||||
CX_RGBA2HLS_FULL = CV_COLORCVT_MAX + CV_RGB2HLS_FULL,
|
||||
CX_RGBA2HSV = CV_COLORCVT_MAX + CV_RGB2HSV,
|
||||
CX_RGBA2HSV_FULL = CV_COLORCVT_MAX + CV_RGB2HSV_FULL,
|
||||
CX_RGBA2Lab = CV_COLORCVT_MAX + CV_RGB2Lab,
|
||||
CX_RGBA2Luv = CV_COLORCVT_MAX + CV_RGB2Luv,
|
||||
CX_RGBA2XYZ = CV_COLORCVT_MAX + CV_RGB2XYZ,
|
||||
CX_RGBA2YCrCb = CV_COLORCVT_MAX + CV_RGB2YCrCb,
|
||||
CX_RGBA2YUV = CV_COLORCVT_MAX + CV_RGB2YUV,
|
||||
CX_XYZ2BGRA = CV_COLORCVT_MAX + CV_XYZ2BGR,
|
||||
CX_XYZ2RGBA = CV_COLORCVT_MAX + CV_XYZ2RGB,
|
||||
CX_YCrCb2BGRA = CV_COLORCVT_MAX + CV_YCrCb2BGR,
|
||||
CX_YCrCb2RGBA = CV_COLORCVT_MAX + CV_YCrCb2RGB,
|
||||
CX_YUV2BGRA = CV_COLORCVT_MAX + CV_YUV2BGR,
|
||||
CX_YUV2RGBA = CV_COLORCVT_MAX + CV_YUV2RGB
|
||||
CX_BGRA2HLS = CV_COLORCVT_MAX + CV_BGR2HLS,
|
||||
CX_BGRA2HLS_FULL = CV_COLORCVT_MAX + CV_BGR2HLS_FULL,
|
||||
CX_BGRA2HSV = CV_COLORCVT_MAX + CV_BGR2HSV,
|
||||
CX_BGRA2HSV_FULL = CV_COLORCVT_MAX + CV_BGR2HSV_FULL,
|
||||
CX_BGRA2Lab = CV_COLORCVT_MAX + CV_BGR2Lab,
|
||||
CX_BGRA2Luv = CV_COLORCVT_MAX + CV_BGR2Luv,
|
||||
CX_BGRA2XYZ = CV_COLORCVT_MAX + CV_BGR2XYZ,
|
||||
CX_BGRA2YCrCb = CV_COLORCVT_MAX + CV_BGR2YCrCb,
|
||||
CX_BGRA2YUV = CV_COLORCVT_MAX + CV_BGR2YUV,
|
||||
CX_HLS2BGRA = CV_COLORCVT_MAX + CV_HLS2BGR,
|
||||
CX_HLS2BGRA_FULL = CV_COLORCVT_MAX + CV_HLS2BGR_FULL,
|
||||
CX_HLS2RGBA = CV_COLORCVT_MAX + CV_HLS2RGB,
|
||||
CX_HLS2RGBA_FULL = CV_COLORCVT_MAX + CV_HLS2RGB_FULL,
|
||||
CX_HSV2BGRA = CV_COLORCVT_MAX + CV_HSV2BGR,
|
||||
CX_HSV2BGRA_FULL = CV_COLORCVT_MAX + CV_HSV2BGR_FULL,
|
||||
CX_HSV2RGBA = CV_COLORCVT_MAX + CV_HSV2RGB,
|
||||
CX_HSV2RGBA_FULL = CV_COLORCVT_MAX + CV_HSV2RGB_FULL,
|
||||
CX_Lab2BGRA = CV_COLORCVT_MAX + CV_Lab2BGR,
|
||||
CX_Lab2LBGRA = CV_COLORCVT_MAX + CV_Lab2LBGR,
|
||||
CX_Lab2LRGBA = CV_COLORCVT_MAX + CV_Lab2LRGB,
|
||||
CX_Lab2RGBA = CV_COLORCVT_MAX + CV_Lab2RGB,
|
||||
CX_LBGRA2Lab = CV_COLORCVT_MAX + CV_LBGR2Lab,
|
||||
CX_LBGRA2Luv = CV_COLORCVT_MAX + CV_LBGR2Luv,
|
||||
CX_LRGBA2Lab = CV_COLORCVT_MAX + CV_LRGB2Lab,
|
||||
CX_LRGBA2Luv = CV_COLORCVT_MAX + CV_LRGB2Luv,
|
||||
CX_Luv2BGRA = CV_COLORCVT_MAX + CV_Luv2BGR,
|
||||
CX_Luv2LBGRA = CV_COLORCVT_MAX + CV_Luv2LBGR,
|
||||
CX_Luv2LRGBA = CV_COLORCVT_MAX + CV_Luv2LRGB,
|
||||
CX_Luv2RGBA = CV_COLORCVT_MAX + CV_Luv2RGB,
|
||||
CX_RGBA2HLS = CV_COLORCVT_MAX + CV_RGB2HLS,
|
||||
CX_RGBA2HLS_FULL = CV_COLORCVT_MAX + CV_RGB2HLS_FULL,
|
||||
CX_RGBA2HSV = CV_COLORCVT_MAX + CV_RGB2HSV,
|
||||
CX_RGBA2HSV_FULL = CV_COLORCVT_MAX + CV_RGB2HSV_FULL,
|
||||
CX_RGBA2Lab = CV_COLORCVT_MAX + CV_RGB2Lab,
|
||||
CX_RGBA2Luv = CV_COLORCVT_MAX + CV_RGB2Luv,
|
||||
CX_RGBA2XYZ = CV_COLORCVT_MAX + CV_RGB2XYZ,
|
||||
CX_RGBA2YCrCb = CV_COLORCVT_MAX + CV_RGB2YCrCb,
|
||||
CX_RGBA2YUV = CV_COLORCVT_MAX + CV_RGB2YUV,
|
||||
CX_XYZ2BGRA = CV_COLORCVT_MAX + CV_XYZ2BGR,
|
||||
CX_XYZ2RGBA = CV_COLORCVT_MAX + CV_XYZ2RGB,
|
||||
CX_YCrCb2BGRA = CV_COLORCVT_MAX + CV_YCrCb2BGR,
|
||||
CX_YCrCb2RGBA = CV_COLORCVT_MAX + CV_YCrCb2RGB,
|
||||
CX_YUV2BGRA = CV_COLORCVT_MAX + CV_YUV2BGR,
|
||||
CX_YUV2RGBA = CV_COLORCVT_MAX + CV_YUV2RGB
|
||||
};
|
||||
|
||||
CV_ENUM(CvtMode,
|
||||
CV_BayerBG2BGR, CV_BayerBG2BGR_VNG, CV_BayerBG2GRAY,
|
||||
CV_BayerGB2BGR, CV_BayerGB2BGR_VNG, CV_BayerGB2GRAY,
|
||||
CV_BayerGR2BGR, CV_BayerGR2BGR_VNG, CV_BayerGR2GRAY,
|
||||
CV_BayerRG2BGR, CV_BayerRG2BGR_VNG, CV_BayerRG2GRAY,
|
||||
|
||||
CV_BGR2BGR555, CV_BGR2BGR565, CV_BGR2BGRA, CV_BGR2GRAY,
|
||||
CV_BGR2HLS, CV_BGR2HLS_FULL, CV_BGR2HSV, CV_BGR2HSV_FULL,
|
||||
CV_BGR2Lab, CV_BGR2Luv, CV_BGR2RGB, CV_BGR2RGBA, CV_BGR2XYZ,
|
||||
CV_BGR2YCrCb, CV_BGR2YUV, CV_BGR5552BGR, CV_BGR5552BGRA,
|
||||
|
||||
CV_BGR5552GRAY, CV_BGR5552RGB, CV_BGR5552RGBA, CV_BGR5652BGR,
|
||||
CV_BGR5652BGRA, CV_BGR5652GRAY, CV_BGR5652RGB, CV_BGR5652RGBA,
|
||||
|
||||
CV_BGRA2BGR, CV_BGRA2BGR555, CV_BGRA2BGR565, CV_BGRA2GRAY, CV_BGRA2RGBA,
|
||||
CX_BGRA2HLS, CX_BGRA2HLS_FULL, CX_BGRA2HSV, CX_BGRA2HSV_FULL,
|
||||
CX_BGRA2Lab, CX_BGRA2Luv, CX_BGRA2XYZ,
|
||||
CX_BGRA2YCrCb, CX_BGRA2YUV,
|
||||
|
||||
CV_GRAY2BGR, CV_GRAY2BGR555, CV_GRAY2BGR565, CV_GRAY2BGRA,
|
||||
CV_ENUM(CvtMode,
|
||||
CV_BayerBG2BGR, CV_BayerBG2BGR_VNG, CV_BayerBG2GRAY,
|
||||
CV_BayerGB2BGR, CV_BayerGB2BGR_VNG, CV_BayerGB2GRAY,
|
||||
CV_BayerGR2BGR, CV_BayerGR2BGR_VNG, CV_BayerGR2GRAY,
|
||||
CV_BayerRG2BGR, CV_BayerRG2BGR_VNG, CV_BayerRG2GRAY,
|
||||
|
||||
CV_HLS2BGR, CV_HLS2BGR_FULL, CV_HLS2RGB, CV_HLS2RGB_FULL,
|
||||
CX_HLS2BGRA, CX_HLS2BGRA_FULL, CX_HLS2RGBA, CX_HLS2RGBA_FULL,
|
||||
|
||||
CV_HSV2BGR, CV_HSV2BGR_FULL, CV_HSV2RGB, CV_HSV2RGB_FULL,
|
||||
CX_HSV2BGRA, CX_HSV2BGRA_FULL, CX_HSV2RGBA, CX_HSV2RGBA_FULL,
|
||||
|
||||
CV_Lab2BGR, CV_Lab2LBGR, CV_Lab2LRGB, CV_Lab2RGB,
|
||||
CX_Lab2BGRA, CX_Lab2LBGRA, CX_Lab2LRGBA, CX_Lab2RGBA,
|
||||
|
||||
CV_LBGR2Lab, CV_LBGR2Luv, CV_LRGB2Lab, CV_LRGB2Luv,
|
||||
CX_LBGRA2Lab, CX_LBGRA2Luv, CX_LRGBA2Lab, CX_LRGBA2Luv,
|
||||
|
||||
CV_Luv2BGR, CV_Luv2LBGR, CV_Luv2LRGB, CV_Luv2RGB,
|
||||
CX_Luv2BGRA, CX_Luv2LBGRA, CX_Luv2LRGBA, CX_Luv2RGBA,
|
||||
|
||||
CV_RGB2BGR555, CV_RGB2BGR565, CV_RGB2GRAY,
|
||||
CV_RGB2HLS, CV_RGB2HLS_FULL, CV_RGB2HSV, CV_RGB2HSV_FULL,
|
||||
CV_RGB2Lab, CV_RGB2Luv, CV_RGB2XYZ, CV_RGB2YCrCb, CV_RGB2YUV,
|
||||
|
||||
CV_RGBA2BGR, CV_RGBA2BGR555, CV_RGBA2BGR565, CV_RGBA2GRAY,
|
||||
CX_RGBA2HLS, CX_RGBA2HLS_FULL, CX_RGBA2HSV, CX_RGBA2HSV_FULL,
|
||||
CX_RGBA2Lab, CX_RGBA2Luv, CX_RGBA2XYZ,
|
||||
CX_RGBA2YCrCb, CX_RGBA2YUV,
|
||||
|
||||
CV_XYZ2BGR, CV_XYZ2RGB, CX_XYZ2BGRA, CX_XYZ2RGBA,
|
||||
|
||||
CV_YCrCb2BGR, CV_YCrCb2RGB, CX_YCrCb2BGRA, CX_YCrCb2RGBA,
|
||||
CV_YUV2BGR, CV_YUV2RGB, CX_YUV2BGRA, CX_YUV2RGBA
|
||||
)
|
||||
CV_BGR2BGR555, CV_BGR2BGR565, CV_BGR2BGRA, CV_BGR2GRAY,
|
||||
CV_BGR2HLS, CV_BGR2HLS_FULL, CV_BGR2HSV, CV_BGR2HSV_FULL,
|
||||
CV_BGR2Lab, CV_BGR2Luv, CV_BGR2RGB, CV_BGR2RGBA, CV_BGR2XYZ,
|
||||
CV_BGR2YCrCb, CV_BGR2YUV, CV_BGR5552BGR, CV_BGR5552BGRA,
|
||||
|
||||
CV_BGR5552GRAY, CV_BGR5552RGB, CV_BGR5552RGBA, CV_BGR5652BGR,
|
||||
CV_BGR5652BGRA, CV_BGR5652GRAY, CV_BGR5652RGB, CV_BGR5652RGBA,
|
||||
|
||||
CV_BGRA2BGR, CV_BGRA2BGR555, CV_BGRA2BGR565, CV_BGRA2GRAY, CV_BGRA2RGBA,
|
||||
CX_BGRA2HLS, CX_BGRA2HLS_FULL, CX_BGRA2HSV, CX_BGRA2HSV_FULL,
|
||||
CX_BGRA2Lab, CX_BGRA2Luv, CX_BGRA2XYZ,
|
||||
CX_BGRA2YCrCb, CX_BGRA2YUV,
|
||||
|
||||
CV_GRAY2BGR, CV_GRAY2BGR555, CV_GRAY2BGR565, CV_GRAY2BGRA,
|
||||
|
||||
CV_HLS2BGR, CV_HLS2BGR_FULL, CV_HLS2RGB, CV_HLS2RGB_FULL,
|
||||
CX_HLS2BGRA, CX_HLS2BGRA_FULL, CX_HLS2RGBA, CX_HLS2RGBA_FULL,
|
||||
|
||||
CV_HSV2BGR, CV_HSV2BGR_FULL, CV_HSV2RGB, CV_HSV2RGB_FULL,
|
||||
CX_HSV2BGRA, CX_HSV2BGRA_FULL, CX_HSV2RGBA, CX_HSV2RGBA_FULL,
|
||||
|
||||
CV_Lab2BGR, CV_Lab2LBGR, CV_Lab2LRGB, CV_Lab2RGB,
|
||||
CX_Lab2BGRA, CX_Lab2LBGRA, CX_Lab2LRGBA, CX_Lab2RGBA,
|
||||
|
||||
CV_LBGR2Lab, CV_LBGR2Luv, CV_LRGB2Lab, CV_LRGB2Luv,
|
||||
CX_LBGRA2Lab, CX_LBGRA2Luv, CX_LRGBA2Lab, CX_LRGBA2Luv,
|
||||
|
||||
CV_Luv2BGR, CV_Luv2LBGR, CV_Luv2LRGB, CV_Luv2RGB,
|
||||
CX_Luv2BGRA, CX_Luv2LBGRA, CX_Luv2LRGBA, CX_Luv2RGBA,
|
||||
|
||||
CV_RGB2BGR555, CV_RGB2BGR565, CV_RGB2GRAY,
|
||||
CV_RGB2HLS, CV_RGB2HLS_FULL, CV_RGB2HSV, CV_RGB2HSV_FULL,
|
||||
CV_RGB2Lab, CV_RGB2Luv, CV_RGB2XYZ, CV_RGB2YCrCb, CV_RGB2YUV,
|
||||
|
||||
CV_RGBA2BGR, CV_RGBA2BGR555, CV_RGBA2BGR565, CV_RGBA2GRAY,
|
||||
CX_RGBA2HLS, CX_RGBA2HLS_FULL, CX_RGBA2HSV, CX_RGBA2HSV_FULL,
|
||||
CX_RGBA2Lab, CX_RGBA2Luv, CX_RGBA2XYZ,
|
||||
CX_RGBA2YCrCb, CX_RGBA2YUV,
|
||||
|
||||
CV_XYZ2BGR, CV_XYZ2RGB, CX_XYZ2BGRA, CX_XYZ2RGBA,
|
||||
|
||||
CV_YCrCb2BGR, CV_YCrCb2RGB, CX_YCrCb2BGRA, CX_YCrCb2RGBA,
|
||||
CV_YUV2BGR, CV_YUV2RGB, CX_YUV2BGRA, CX_YUV2RGBA
|
||||
)
|
||||
|
||||
CV_ENUM(CvtMode2, CV_YUV2BGR_NV12, CV_YUV2BGRA_NV12, CV_YUV2RGB_NV12, CV_YUV2RGBA_NV12, CV_YUV2BGR_NV21, CV_YUV2BGRA_NV21, CV_YUV2RGB_NV21, CV_YUV2RGBA_NV21,
|
||||
CV_YUV2BGR_YV12, CV_YUV2BGRA_YV12, CV_YUV2RGB_YV12, CV_YUV2RGBA_YV12, CV_YUV2BGR_IYUV, CV_YUV2BGRA_IYUV, CV_YUV2RGB_IYUV, CV_YUV2RGBA_IYUV,
|
||||
COLOR_YUV2GRAY_420)
|
||||
|
||||
CV_ENUM(CvtMode2, CV_YUV2BGR_NV12, CV_YUV2BGRA_NV12, CV_YUV2RGB_NV12, CV_YUV2RGBA_NV12, CV_YUV420sp2BGR, CV_YUV420sp2BGRA, CV_YUV420sp2RGB, CV_YUV420sp2RGBA)
|
||||
|
||||
struct ChPair
|
||||
{
|
||||
ChPair(int _scn, int _dcn): scn(_scn), dcn(_dcn) {}
|
||||
int scn, dcn;
|
||||
ChPair(int _scn, int _dcn): scn(_scn), dcn(_dcn) {}
|
||||
int scn, dcn;
|
||||
};
|
||||
|
||||
ChPair getConversionInfo(int cvtMode)
|
||||
{
|
||||
switch(cvtMode)
|
||||
{
|
||||
case CV_BayerBG2GRAY: case CV_BayerGB2GRAY:
|
||||
case CV_BayerGR2GRAY: case CV_BayerRG2GRAY:
|
||||
return ChPair(1,1);
|
||||
case CV_GRAY2BGR555: case CV_GRAY2BGR565:
|
||||
return ChPair(1,2);
|
||||
case CV_BayerBG2BGR: case CV_BayerBG2BGR_VNG:
|
||||
case CV_BayerGB2BGR: case CV_BayerGB2BGR_VNG:
|
||||
case CV_BayerGR2BGR: case CV_BayerGR2BGR_VNG:
|
||||
case CV_BayerRG2BGR: case CV_BayerRG2BGR_VNG:
|
||||
case CV_GRAY2BGR: case CV_YUV2BGR_NV12:
|
||||
case CV_YUV2RGB_NV12: case CV_YUV420sp2BGR:
|
||||
case CV_YUV420sp2RGB:
|
||||
return ChPair(1,3);
|
||||
case CV_GRAY2BGRA: case CV_YUV2BGRA_NV12:
|
||||
case CV_YUV2RGBA_NV12: case CV_YUV420sp2BGRA:
|
||||
case CV_YUV420sp2RGBA:
|
||||
return ChPair(1,4);
|
||||
case CV_BGR5552GRAY: case CV_BGR5652GRAY:
|
||||
return ChPair(2,1);
|
||||
case CV_BGR5552BGR: case CV_BGR5552RGB:
|
||||
case CV_BGR5652BGR: case CV_BGR5652RGB:
|
||||
return ChPair(2,3);
|
||||
case CV_BGR5552BGRA: case CV_BGR5552RGBA:
|
||||
case CV_BGR5652BGRA: case CV_BGR5652RGBA:
|
||||
return ChPair(2,4);
|
||||
case CV_BGR2GRAY: case CV_RGB2GRAY:
|
||||
return ChPair(3,1);
|
||||
case CV_BGR2BGR555: case CV_BGR2BGR565:
|
||||
case CV_RGB2BGR555: case CV_RGB2BGR565:
|
||||
return ChPair(3,2);
|
||||
case CV_BGR2HLS: case CV_BGR2HLS_FULL:
|
||||
case CV_BGR2HSV: case CV_BGR2HSV_FULL:
|
||||
case CV_BGR2Lab: case CV_BGR2Luv:
|
||||
case CV_BGR2RGB: case CV_BGR2XYZ:
|
||||
case CV_BGR2YCrCb: case CV_BGR2YUV:
|
||||
case CV_HLS2BGR: case CV_HLS2BGR_FULL:
|
||||
case CV_HLS2RGB: case CV_HLS2RGB_FULL:
|
||||
case CV_HSV2BGR: case CV_HSV2BGR_FULL:
|
||||
case CV_HSV2RGB: case CV_HSV2RGB_FULL:
|
||||
case CV_Lab2BGR: case CV_Lab2LBGR:
|
||||
case CV_Lab2LRGB: case CV_Lab2RGB:
|
||||
case CV_LBGR2Lab: case CV_LBGR2Luv:
|
||||
case CV_LRGB2Lab: case CV_LRGB2Luv:
|
||||
case CV_Luv2BGR: case CV_Luv2LBGR:
|
||||
case CV_Luv2LRGB: case CV_Luv2RGB:
|
||||
case CV_RGB2HLS: case CV_RGB2HLS_FULL:
|
||||
case CV_RGB2HSV: case CV_RGB2HSV_FULL:
|
||||
case CV_RGB2Lab: case CV_RGB2Luv:
|
||||
case CV_RGB2XYZ: case CV_RGB2YCrCb:
|
||||
case CV_RGB2YUV: case CV_XYZ2BGR:
|
||||
case CV_XYZ2RGB: case CV_YCrCb2BGR:
|
||||
case CV_YCrCb2RGB: case CV_YUV2BGR:
|
||||
case CV_YUV2RGB:
|
||||
return ChPair(3,3);
|
||||
case CV_BGR2BGRA: case CV_BGR2RGBA:
|
||||
case CX_HLS2BGRA: case CX_HLS2BGRA_FULL:
|
||||
case CX_HLS2RGBA: case CX_HLS2RGBA_FULL:
|
||||
case CX_HSV2BGRA: case CX_HSV2BGRA_FULL:
|
||||
case CX_HSV2RGBA: case CX_HSV2RGBA_FULL:
|
||||
case CX_Lab2BGRA: case CX_Lab2LBGRA:
|
||||
case CX_Lab2LRGBA: case CX_Lab2RGBA:
|
||||
case CX_Luv2BGRA: case CX_Luv2LBGRA:
|
||||
case CX_Luv2LRGBA: case CX_Luv2RGBA:
|
||||
case CX_XYZ2BGRA: case CX_XYZ2RGBA:
|
||||
case CX_YCrCb2BGRA: case CX_YCrCb2RGBA:
|
||||
case CX_YUV2BGRA: case CX_YUV2RGBA:
|
||||
return ChPair(3,4);
|
||||
case CV_BGRA2GRAY: case CV_RGBA2GRAY:
|
||||
return ChPair(4,1);
|
||||
case CV_BGRA2BGR555: case CV_BGRA2BGR565:
|
||||
case CV_RGBA2BGR555: case CV_RGBA2BGR565:
|
||||
return ChPair(4,2);
|
||||
case CV_BGRA2BGR: case CX_BGRA2HLS:
|
||||
case CX_BGRA2HLS_FULL: case CX_BGRA2HSV:
|
||||
case CX_BGRA2HSV_FULL: case CX_BGRA2Lab:
|
||||
case CX_BGRA2Luv: case CX_BGRA2XYZ:
|
||||
case CX_BGRA2YCrCb: case CX_BGRA2YUV:
|
||||
case CX_LBGRA2Lab: case CX_LBGRA2Luv:
|
||||
case CX_LRGBA2Lab: case CX_LRGBA2Luv:
|
||||
case CV_RGBA2BGR: case CX_RGBA2HLS:
|
||||
case CX_RGBA2HLS_FULL: case CX_RGBA2HSV:
|
||||
case CX_RGBA2HSV_FULL: case CX_RGBA2Lab:
|
||||
case CX_RGBA2Luv: case CX_RGBA2XYZ:
|
||||
case CX_RGBA2YCrCb: case CX_RGBA2YUV:
|
||||
return ChPair(4,3);
|
||||
case CV_BGRA2RGBA:
|
||||
return ChPair(4,4);
|
||||
default:
|
||||
ADD_FAILURE() << "Unknown conversion type";
|
||||
break;
|
||||
};
|
||||
return ChPair(0,0);
|
||||
switch(cvtMode)
|
||||
{
|
||||
case CV_BayerBG2GRAY: case CV_BayerGB2GRAY:
|
||||
case CV_BayerGR2GRAY: case CV_BayerRG2GRAY:
|
||||
case CV_YUV2GRAY_420:
|
||||
return ChPair(1,1);
|
||||
case CV_GRAY2BGR555: case CV_GRAY2BGR565:
|
||||
return ChPair(1,2);
|
||||
case CV_BayerBG2BGR: case CV_BayerBG2BGR_VNG:
|
||||
case CV_BayerGB2BGR: case CV_BayerGB2BGR_VNG:
|
||||
case CV_BayerGR2BGR: case CV_BayerGR2BGR_VNG:
|
||||
case CV_BayerRG2BGR: case CV_BayerRG2BGR_VNG:
|
||||
case CV_GRAY2BGR:
|
||||
case CV_YUV2BGR_NV12: case CV_YUV2RGB_NV12:
|
||||
case CV_YUV2BGR_NV21: case CV_YUV2RGB_NV21:
|
||||
case CV_YUV2BGR_YV12: case CV_YUV2RGB_YV12:
|
||||
case CV_YUV2BGR_IYUV: case CV_YUV2RGB_IYUV:
|
||||
return ChPair(1,3);
|
||||
case CV_GRAY2BGRA:
|
||||
case CV_YUV2BGRA_NV12: case CV_YUV2RGBA_NV12:
|
||||
case CV_YUV2BGRA_NV21: case CV_YUV2RGBA_NV21:
|
||||
case CV_YUV2BGRA_YV12: case CV_YUV2RGBA_YV12:
|
||||
case CV_YUV2BGRA_IYUV: case CV_YUV2RGBA_IYUV:
|
||||
return ChPair(1,4);
|
||||
case CV_BGR5552GRAY: case CV_BGR5652GRAY:
|
||||
return ChPair(2,1);
|
||||
case CV_BGR5552BGR: case CV_BGR5552RGB:
|
||||
case CV_BGR5652BGR: case CV_BGR5652RGB:
|
||||
return ChPair(2,3);
|
||||
case CV_BGR5552BGRA: case CV_BGR5552RGBA:
|
||||
case CV_BGR5652BGRA: case CV_BGR5652RGBA:
|
||||
return ChPair(2,4);
|
||||
case CV_BGR2GRAY: case CV_RGB2GRAY:
|
||||
return ChPair(3,1);
|
||||
case CV_BGR2BGR555: case CV_BGR2BGR565:
|
||||
case CV_RGB2BGR555: case CV_RGB2BGR565:
|
||||
return ChPair(3,2);
|
||||
case CV_BGR2HLS: case CV_BGR2HLS_FULL:
|
||||
case CV_BGR2HSV: case CV_BGR2HSV_FULL:
|
||||
case CV_BGR2Lab: case CV_BGR2Luv:
|
||||
case CV_BGR2RGB: case CV_BGR2XYZ:
|
||||
case CV_BGR2YCrCb: case CV_BGR2YUV:
|
||||
case CV_HLS2BGR: case CV_HLS2BGR_FULL:
|
||||
case CV_HLS2RGB: case CV_HLS2RGB_FULL:
|
||||
case CV_HSV2BGR: case CV_HSV2BGR_FULL:
|
||||
case CV_HSV2RGB: case CV_HSV2RGB_FULL:
|
||||
case CV_Lab2BGR: case CV_Lab2LBGR:
|
||||
case CV_Lab2LRGB: case CV_Lab2RGB:
|
||||
case CV_LBGR2Lab: case CV_LBGR2Luv:
|
||||
case CV_LRGB2Lab: case CV_LRGB2Luv:
|
||||
case CV_Luv2BGR: case CV_Luv2LBGR:
|
||||
case CV_Luv2LRGB: case CV_Luv2RGB:
|
||||
case CV_RGB2HLS: case CV_RGB2HLS_FULL:
|
||||
case CV_RGB2HSV: case CV_RGB2HSV_FULL:
|
||||
case CV_RGB2Lab: case CV_RGB2Luv:
|
||||
case CV_RGB2XYZ: case CV_RGB2YCrCb:
|
||||
case CV_RGB2YUV: case CV_XYZ2BGR:
|
||||
case CV_XYZ2RGB: case CV_YCrCb2BGR:
|
||||
case CV_YCrCb2RGB: case CV_YUV2BGR:
|
||||
case CV_YUV2RGB:
|
||||
return ChPair(3,3);
|
||||
case CV_BGR2BGRA: case CV_BGR2RGBA:
|
||||
case CX_HLS2BGRA: case CX_HLS2BGRA_FULL:
|
||||
case CX_HLS2RGBA: case CX_HLS2RGBA_FULL:
|
||||
case CX_HSV2BGRA: case CX_HSV2BGRA_FULL:
|
||||
case CX_HSV2RGBA: case CX_HSV2RGBA_FULL:
|
||||
case CX_Lab2BGRA: case CX_Lab2LBGRA:
|
||||
case CX_Lab2LRGBA: case CX_Lab2RGBA:
|
||||
case CX_Luv2BGRA: case CX_Luv2LBGRA:
|
||||
case CX_Luv2LRGBA: case CX_Luv2RGBA:
|
||||
case CX_XYZ2BGRA: case CX_XYZ2RGBA:
|
||||
case CX_YCrCb2BGRA: case CX_YCrCb2RGBA:
|
||||
case CX_YUV2BGRA: case CX_YUV2RGBA:
|
||||
return ChPair(3,4);
|
||||
case CV_BGRA2GRAY: case CV_RGBA2GRAY:
|
||||
return ChPair(4,1);
|
||||
case CV_BGRA2BGR555: case CV_BGRA2BGR565:
|
||||
case CV_RGBA2BGR555: case CV_RGBA2BGR565:
|
||||
return ChPair(4,2);
|
||||
case CV_BGRA2BGR: case CX_BGRA2HLS:
|
||||
case CX_BGRA2HLS_FULL: case CX_BGRA2HSV:
|
||||
case CX_BGRA2HSV_FULL: case CX_BGRA2Lab:
|
||||
case CX_BGRA2Luv: case CX_BGRA2XYZ:
|
||||
case CX_BGRA2YCrCb: case CX_BGRA2YUV:
|
||||
case CX_LBGRA2Lab: case CX_LBGRA2Luv:
|
||||
case CX_LRGBA2Lab: case CX_LRGBA2Luv:
|
||||
case CV_RGBA2BGR: case CX_RGBA2HLS:
|
||||
case CX_RGBA2HLS_FULL: case CX_RGBA2HSV:
|
||||
case CX_RGBA2HSV_FULL: case CX_RGBA2Lab:
|
||||
case CX_RGBA2Luv: case CX_RGBA2XYZ:
|
||||
case CX_RGBA2YCrCb: case CX_RGBA2YUV:
|
||||
return ChPair(4,3);
|
||||
case CV_BGRA2RGBA:
|
||||
return ChPair(4,4);
|
||||
default:
|
||||
ADD_FAILURE() << "Unknown conversion type";
|
||||
break;
|
||||
};
|
||||
return ChPair(0,0);
|
||||
}
|
||||
|
||||
typedef std::tr1::tuple<Size, CvtMode> Size_CvtMode_t;
|
||||
@ -222,18 +229,18 @@ PERF_TEST_P(Size_CvtMode, cvtColor8u,
|
||||
)
|
||||
)
|
||||
{
|
||||
Size sz = get<0>(GetParam());
|
||||
int mode = get<1>(GetParam());
|
||||
ChPair ch = getConversionInfo(mode);
|
||||
mode %= CV_COLORCVT_MAX;
|
||||
|
||||
Mat src(sz, CV_8UC(ch.scn));
|
||||
Mat dst(sz, CV_8UC(ch.dcn));
|
||||
|
||||
declare.in(src, WARMUP_RNG).out(dst);
|
||||
|
||||
Size sz = get<0>(GetParam());
|
||||
int mode = get<1>(GetParam());
|
||||
ChPair ch = getConversionInfo(mode);
|
||||
mode %= CV_COLORCVT_MAX;
|
||||
|
||||
Mat src(sz, CV_8UC(ch.scn));
|
||||
Mat dst(sz, CV_8UC(ch.dcn));
|
||||
|
||||
declare.in(src, WARMUP_RNG).out(dst);
|
||||
|
||||
TEST_CYCLE() cvtColor(src, dst, mode, ch.dcn);
|
||||
|
||||
|
||||
SANITY_CHECK(dst, 1);
|
||||
}
|
||||
|
||||
@ -248,15 +255,15 @@ PERF_TEST_P(Size_CvtMode2, cvtColorYUV420,
|
||||
)
|
||||
{
|
||||
Size sz = get<0>(GetParam());
|
||||
int mode = get<1>(GetParam());
|
||||
ChPair ch = getConversionInfo(mode);
|
||||
int mode = get<1>(GetParam());
|
||||
ChPair ch = getConversionInfo(mode);
|
||||
|
||||
Mat src(sz.height + sz.height / 2, sz.width, CV_8UC(ch.scn));
|
||||
Mat dst(sz, CV_8UC(ch.dcn));
|
||||
|
||||
declare.in(src, WARMUP_RNG).out(dst);
|
||||
|
||||
|
||||
TEST_CYCLE() cvtColor(src, dst, mode, ch.dcn);
|
||||
|
||||
|
||||
SANITY_CHECK(dst, 1);
|
||||
}
|
||||
|
@ -2829,22 +2829,18 @@ struct YUV420p2RGB888Invoker
|
||||
Mat* dst;
|
||||
const uchar* my1, *mu, *mv;
|
||||
int width, stride;
|
||||
int ustepIdx, vstepIdx;
|
||||
|
||||
YUV420p2RGB888Invoker(Mat* _dst, int _stride, const uchar* _y1, const uchar* _u, const uchar* _v)
|
||||
: dst(_dst), my1(_y1), mu(_u), mv(_v), width(_dst->cols), stride(_stride) {}
|
||||
YUV420p2RGB888Invoker(Mat* _dst, int _stride, const uchar* _y1, const uchar* _u, const uchar* _v, int _ustepIdx, int _vstepIdx)
|
||||
: dst(_dst), my1(_y1), mu(_u), mv(_v), width(_dst->cols), stride(_stride), ustepIdx(_ustepIdx), vstepIdx(_vstepIdx) {}
|
||||
|
||||
void operator()(const BlockedRange& range) const
|
||||
{
|
||||
const int rangeBegin = range.begin() * 2;
|
||||
const int rangeEnd = range.end() * 2;
|
||||
|
||||
//R = 1.164(Y - 16) + 1.596(V - 128)
|
||||
//G = 1.164(Y - 16) - 0.813(V - 128) - 0.391(U - 128)
|
||||
//B = 1.164(Y - 16) + 2.018(U - 128)
|
||||
|
||||
//R = (1220542(Y - 16) + 1673527(V - 128) + (1 << 19)) >> 20
|
||||
//G = (1220542(Y - 16) - 852492(V - 128) - 409993(U - 128) + (1 << 19)) >> 20
|
||||
//B = (1220542(Y - 16) + 2116026(U - 128) + (1 << 19)) >> 20
|
||||
|
||||
size_t uvsteps[2] = {width/2, stride - width/2};
|
||||
int usIdx = ustepIdx, vsIdx = vstepIdx;
|
||||
|
||||
const int cY = 1220542;
|
||||
const int cUB = 2116026;
|
||||
@ -2854,10 +2850,16 @@ struct YUV420p2RGB888Invoker
|
||||
const int YUV420_SHIFT = 20;
|
||||
|
||||
const uchar* y1 = my1 + rangeBegin * stride;
|
||||
const uchar* u1 = mu + (range.begin() / 2) * stride + (range.begin() % 2) * width/2;
|
||||
const uchar* v1 = mv + (range.begin() / 2) * stride + (range.begin() % 2) * width/2;
|
||||
const uchar* u1 = mu + (range.begin() / 2) * stride;
|
||||
const uchar* v1 = mv + (range.begin() / 2) * stride;
|
||||
|
||||
if(range.begin() % 2 == 1)
|
||||
{
|
||||
u1 += uvsteps[(usIdx++) & 1];
|
||||
v1 += uvsteps[(vsIdx++) & 1];
|
||||
}
|
||||
|
||||
for (int j = rangeBegin; j < rangeEnd; j += 2, y1 += stride * 2, u1 += width / 2, v1 += width / 2)
|
||||
for (int j = rangeBegin; j < rangeEnd; j += 2, y1 += stride * 2, u1 += uvsteps[(usIdx++) & 1], v1 += uvsteps[(vsIdx++) & 1])
|
||||
{
|
||||
uchar* row1 = dst->ptr<uchar>(j);
|
||||
uchar* row2 = dst->ptr<uchar>(j + 1);
|
||||
@ -2892,12 +2894,6 @@ struct YUV420p2RGB888Invoker
|
||||
row2[4] = saturate_cast<uchar>((y11 + guv) >> YUV420_SHIFT);
|
||||
row2[3+bIdx] = saturate_cast<uchar>((y11 + buv) >> YUV420_SHIFT);
|
||||
}
|
||||
|
||||
if(j % 4 == 2)
|
||||
{
|
||||
u1 += stride - width;
|
||||
v1 += stride - width;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -2908,35 +2904,37 @@ struct YUV420p2RGBA8888Invoker
|
||||
Mat* dst;
|
||||
const uchar* my1, *mu, *mv;
|
||||
int width, stride;
|
||||
int ustepIdx, vstepIdx;
|
||||
|
||||
YUV420p2RGBA8888Invoker(Mat* _dst, int _stride, const uchar* _y1, const uchar* _u, const uchar* _v)
|
||||
: dst(_dst), my1(_y1), mu(_u), mv(_v), width(_dst->cols), stride(_stride) {}
|
||||
YUV420p2RGBA8888Invoker(Mat* _dst, int _stride, const uchar* _y1, const uchar* _u, const uchar* _v, int _ustepIdx, int _vstepIdx)
|
||||
: dst(_dst), my1(_y1), mu(_u), mv(_v), width(_dst->cols), stride(_stride), ustepIdx(_ustepIdx), vstepIdx(_vstepIdx) {}
|
||||
|
||||
void operator()(const BlockedRange& range) const
|
||||
{
|
||||
int rangeBegin = range.begin() * 2;
|
||||
int rangeEnd = range.end() * 2;
|
||||
|
||||
//R = 1.164(Y - 16) + 1.596(V - 128)
|
||||
//G = 1.164(Y - 16) - 0.813(V - 128) - 0.391(U - 128)
|
||||
//B = 1.164(Y - 16) + 2.018(U - 128)
|
||||
|
||||
//R = (1220542(Y - 16) + 1673527(V - 128) + (1 << 19)) >> 20
|
||||
//G = (1220542(Y - 16) - 852492(V - 128) - 409993(U - 128) + (1 << 19)) >> 20
|
||||
//B = (1220542(Y - 16) + 2116026(U - 128) + (1 << 19)) >> 20
|
||||
|
||||
const int cY = 1220542;
|
||||
const int cUB = 2116026;
|
||||
const int cUG = -409993;
|
||||
const int cVG = -852492;
|
||||
const int cVR = 1673527;
|
||||
const int YUV420_SHIFT = 20;
|
||||
|
||||
size_t uvsteps[2] = {width/2, stride - width/2};
|
||||
int usIdx = ustepIdx, vsIdx = vstepIdx;
|
||||
|
||||
const uchar* y1 = my1 + rangeBegin * stride;
|
||||
const uchar* u1 = mu + (range.begin() / 2) * stride + (range.begin() % 2) * width/2;
|
||||
const uchar* v1 = mv + (range.begin() / 2) * stride + (range.begin() % 2) * width/2;
|
||||
const uchar* u1 = mu + (range.begin() / 2) * stride;
|
||||
const uchar* v1 = mv + (range.begin() / 2) * stride;
|
||||
|
||||
if(range.begin() % 2 == 1)
|
||||
{
|
||||
u1 += uvsteps[(usIdx++) & 1];
|
||||
v1 += uvsteps[(vsIdx++) & 1];
|
||||
}
|
||||
|
||||
for (int j = rangeBegin; j < rangeEnd; j += 2, y1 += stride * 2, u1 += width / 2, v1 += width / 2)
|
||||
for (int j = rangeBegin; j < rangeEnd; j += 2, y1 += stride * 2, u1 += uvsteps[(usIdx++) & 1], v1 += uvsteps[(vsIdx++) & 1])
|
||||
{
|
||||
uchar* row1 = dst->ptr<uchar>(j);
|
||||
uchar* row2 = dst->ptr<uchar>(j + 1);
|
||||
@ -2975,12 +2973,6 @@ struct YUV420p2RGBA8888Invoker
|
||||
row2[4+bIdx] = saturate_cast<uchar>((y11 + buv) >> YUV420_SHIFT);
|
||||
row2[7] = uchar(0xff);
|
||||
}
|
||||
|
||||
if(j % 4 == 2)
|
||||
{
|
||||
u1 += stride - width;
|
||||
v1 += stride - width;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -3012,9 +3004,9 @@ inline void cvtYUV420sp2RGBA(Mat& _dst, int _stride, const uchar* _y1, const uch
|
||||
}
|
||||
|
||||
template<int bIdx>
|
||||
inline void cvtYUV420p2RGB(Mat& _dst, int _stride, const uchar* _y1, const uchar* _u, const uchar* _v)
|
||||
inline void cvtYUV420p2RGB(Mat& _dst, int _stride, const uchar* _y1, const uchar* _u, const uchar* _v, int ustepIdx, int vstepIdx)
|
||||
{
|
||||
YUV420p2RGB888Invoker<bIdx> converter(&_dst, _stride, _y1, _u, _v);
|
||||
YUV420p2RGB888Invoker<bIdx> converter(&_dst, _stride, _y1, _u, _v, ustepIdx, vstepIdx);
|
||||
#ifdef HAVE_TBB
|
||||
if (_dst.total() >= MIN_SIZE_FOR_PARALLEL_YUV420_CONVERSION)
|
||||
parallel_for(BlockedRange(0, _dst.rows/2), converter);
|
||||
@ -3024,9 +3016,9 @@ inline void cvtYUV420p2RGB(Mat& _dst, int _stride, const uchar* _y1, const uchar
|
||||
}
|
||||
|
||||
template<int bIdx>
|
||||
inline void cvtYUV420p2RGBA(Mat& _dst, int _stride, const uchar* _y1, const uchar* _u, const uchar* _v)
|
||||
inline void cvtYUV420p2RGBA(Mat& _dst, int _stride, const uchar* _y1, const uchar* _u, const uchar* _v, int ustepIdx, int vstepIdx)
|
||||
{
|
||||
YUV420p2RGBA8888Invoker<bIdx> converter(&_dst, _stride, _y1, _u, _v);
|
||||
YUV420p2RGBA8888Invoker<bIdx> converter(&_dst, _stride, _y1, _u, _v, ustepIdx, vstepIdx);
|
||||
#ifdef HAVE_TBB
|
||||
if (_dst.total() >= MIN_SIZE_FOR_PARALLEL_YUV420_CONVERSION)
|
||||
parallel_for(BlockedRange(0, _dst.rows/2), converter);
|
||||
@ -3461,15 +3453,19 @@ void cv::cvtColor( InputArray _src, OutputArray _dst, int code, int dcn )
|
||||
int srcstep = (int)src.step;
|
||||
const uchar* y = src.ptr();
|
||||
const uchar* u = y + srcstep * dstSz.height;
|
||||
const uchar* v = u + (srcstep * dstSz.height / 4);
|
||||
if(uidx == 1) std::swap(u ,v);
|
||||
const uchar* v = y + srcstep * (dstSz.height + dstSz.height/4) + (dstSz.width/2) * ((dstSz.height % 4)/2);
|
||||
|
||||
int ustepIdx = 0;
|
||||
int vstepIdx = dstSz.height % 4 == 2 ? 1 : 0;
|
||||
|
||||
if(uidx == 1) { std::swap(u ,v), std::swap(ustepIdx, vstepIdx); };
|
||||
|
||||
switch(dcn*10 + bidx)
|
||||
{
|
||||
case 30: cvtYUV420p2RGB<0>(dst, srcstep, y, u, v); break;
|
||||
case 32: cvtYUV420p2RGB<2>(dst, srcstep, y, u, v); break;
|
||||
case 40: cvtYUV420p2RGBA<0>(dst, srcstep, y, u, v); break;
|
||||
case 42: cvtYUV420p2RGBA<2>(dst, srcstep, y, u, v); break;
|
||||
case 30: cvtYUV420p2RGB<0>(dst, srcstep, y, u, v, ustepIdx, vstepIdx); break;
|
||||
case 32: cvtYUV420p2RGB<2>(dst, srcstep, y, u, v, ustepIdx, vstepIdx); break;
|
||||
case 40: cvtYUV420p2RGBA<0>(dst, srcstep, y, u, v, ustepIdx, vstepIdx); break;
|
||||
case 42: cvtYUV420p2RGBA<2>(dst, srcstep, y, u, v, ustepIdx, vstepIdx); break;
|
||||
default: CV_Error( CV_StsBadFlag, "Unknown/unsupported color conversion code" ); break;
|
||||
};
|
||||
}
|
||||
|
487
modules/imgproc/test/test_cvtyuv.cpp
Normal file
487
modules/imgproc/test/test_cvtyuv.cpp
Normal file
@ -0,0 +1,487 @@
|
||||
#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 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 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 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 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];
|
||||
}
|
||||
};
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
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)));
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
typedef ::testing::TestWithParam<YUVCVTS> Imgproc_ColorYUV;
|
||||
|
||||
TEST_P(Imgproc_ColorYUV, accuracy)
|
||||
{
|
||||
int code = GetParam();
|
||||
RNG& random = theRNG();
|
||||
|
||||
YUVreader* yuvReader = YUVreader::getReader(code);
|
||||
RGBwriter* rgbWriter = RGBwriter::getWriter(code);
|
||||
GRAYwriter* grayWriter = GRAYwriter::getWriter(code);
|
||||
|
||||
int dcn = (rgbWriter == 0) ? grayWriter->channels() : rgbWriter->channels();
|
||||
|
||||
for(int iter = 0; iter < 30; ++iter)
|
||||
{
|
||||
Size sz(random.uniform(1, 641), random.uniform(1, 481));
|
||||
|
||||
if(yuvReader->requiresEvenWidth()) sz.width += sz.width % 2;
|
||||
if(yuvReader->requiresEvenHeight()) sz.height += sz.height % 2;
|
||||
|
||||
Size ysz = yuvReader->size(sz);
|
||||
Mat src = Mat(ysz.height, ysz.width * yuvReader->channels(), CV_8UC1).reshape(yuvReader->channels());
|
||||
|
||||
Mat dst = Mat(sz.height, sz.width * dcn, CV_8UC1).reshape(dcn);
|
||||
Mat gold(sz, CV_8UC(dcn));
|
||||
|
||||
random.fill(src, RNG::UNIFORM, 0, 256);
|
||||
|
||||
if(rgbWriter)
|
||||
referenceYUV2RGB<YUV2RGB_Converter>(src, gold, yuvReader, rgbWriter);
|
||||
else
|
||||
referenceYUV2GRAY<YUV2GRAY_Converter>(src, gold, yuvReader, grayWriter);
|
||||
|
||||
cv::cvtColor(src, dst, code, -1);
|
||||
|
||||
EXPECT_EQ(0, countOfDifferencies(gold, dst));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_P(Imgproc_ColorYUV, roi_accuracy)
|
||||
{
|
||||
int code = GetParam();
|
||||
RNG& random = theRNG();
|
||||
|
||||
YUVreader* yuvReader = YUVreader::getReader(code);
|
||||
RGBwriter* rgbWriter = RGBwriter::getWriter(code);
|
||||
GRAYwriter* grayWriter = GRAYwriter::getWriter(code);
|
||||
|
||||
int dcn = (rgbWriter == 0) ? grayWriter->channels() : rgbWriter->channels();
|
||||
|
||||
for(int iter = 0; iter < 30; ++iter)
|
||||
{
|
||||
Size sz(random.uniform(1, 641), random.uniform(1, 481));
|
||||
|
||||
if(yuvReader->requiresEvenWidth()) sz.width += sz.width % 2;
|
||||
if(yuvReader->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 ysz = yuvReader->size(sz);
|
||||
|
||||
Mat src_full(ysz.height + roi_offset_top + roi_offset_bottom, ysz.width + roi_offset_left + roi_offset_right, CV_8UC(yuvReader->channels()));
|
||||
Mat dst_full(sz.height + roi_offset_left + roi_offset_right, sz.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 + ysz.height), Range(roi_offset_left, roi_offset_left + ysz.width));
|
||||
Mat dst = dst_full(Range(roi_offset_left, roi_offset_left + sz.height), Range(roi_offset_top, roi_offset_top + sz.width));
|
||||
Mat gold = gold_full(Range(roi_offset_left, roi_offset_left + sz.height), Range(roi_offset_top, roi_offset_top + sz.width));
|
||||
|
||||
if(rgbWriter)
|
||||
referenceYUV2RGB<YUV2RGB_Converter>(src, gold, yuvReader, rgbWriter);
|
||||
else
|
||||
referenceYUV2GRAY<YUV2GRAY_Converter>(src, gold, yuvReader, grayWriter);
|
||||
|
||||
cv::cvtColor(src, dst, code, -1);
|
||||
|
||||
EXPECT_EQ(0, countOfDifferencies(gold_full, dst_full));
|
||||
}
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(cvt420, Imgproc_ColorYUV,
|
||||
::testing::Values(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_YUV2GRAY_420));
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(DISABLED_cvt888, Imgproc_ColorYUV,
|
||||
::testing::Values(CV_YUV2BGR, CV_YUV2RGB));
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(DISABLED_cvt422, Imgproc_ColorYUV,
|
||||
::testing::Values(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_UYVY, CV_YUV2GRAY_YUY2));
|
Loading…
Reference in New Issue
Block a user