diff --git a/modules/imgproc/include/opencv2/imgproc.hpp b/modules/imgproc/include/opencv2/imgproc.hpp index 647ea1862b..951f59bd91 100644 --- a/modules/imgproc/include/opencv2/imgproc.hpp +++ b/modules/imgproc/include/opencv2/imgproc.hpp @@ -842,7 +842,41 @@ enum ColorConversionCodes { COLOR_BayerRG2RGBA = COLOR_BayerBG2BGRA, //!< equivalent to BGGR Bayer pattern COLOR_BayerGR2RGBA = COLOR_BayerGB2BGRA, //!< equivalent to GBRG Bayer pattern - COLOR_COLORCVT_MAX = 143 + //! RGB to YUV 4:2:2 family + + COLOR_RGB2YUV_UYVY = 143, + COLOR_BGR2YUV_UYVY = 144, + COLOR_RGB2YUV_Y422 = COLOR_RGB2YUV_UYVY, + COLOR_BGR2YUV_Y422 = COLOR_BGR2YUV_UYVY, + COLOR_RGB2YUV_UYNV = COLOR_RGB2YUV_UYVY, + COLOR_BGR2YUV_UYNV = COLOR_BGR2YUV_UYVY, + + COLOR_RGBA2YUV_UYVY = 145, + COLOR_BGRA2YUV_UYVY = 146, + COLOR_RGBA2YUV_Y422 = COLOR_RGBA2YUV_UYVY, + COLOR_BGRA2YUV_Y422 = COLOR_BGRA2YUV_UYVY, + COLOR_RGBA2YUV_UYNV = COLOR_RGBA2YUV_UYVY, + COLOR_BGRA2YUV_UYNV = COLOR_BGRA2YUV_UYVY, + + COLOR_RGB2YUV_YUY2 = 147, + COLOR_BGR2YUV_YUY2 = 148, + COLOR_RGB2YUV_YVYU = 149, + COLOR_BGR2YUV_YVYU = 150, + COLOR_RGB2YUV_YUYV = COLOR_RGB2YUV_YUY2, + COLOR_BGR2YUV_YUYV = COLOR_BGR2YUV_YUY2, + COLOR_RGB2YUV_YUNV = COLOR_RGB2YUV_YUY2, + COLOR_BGR2YUV_YUNV = COLOR_BGR2YUV_YUY2, + + COLOR_RGBA2YUV_YUY2 = 151, + COLOR_BGRA2YUV_YUY2 = 152, + COLOR_RGBA2YUV_YVYU = 153, + COLOR_BGRA2YUV_YVYU = 154, + COLOR_RGBA2YUV_YUYV = COLOR_RGBA2YUV_YUY2, + COLOR_BGRA2YUV_YUYV = COLOR_BGRA2YUV_YUY2, + COLOR_RGBA2YUV_YUNV = COLOR_RGBA2YUV_YUY2, + COLOR_BGRA2YUV_YUNV = COLOR_BGRA2YUV_YUY2, + + COLOR_COLORCVT_MAX = 155 }; //! @addtogroup imgproc_shape diff --git a/modules/imgproc/include/opencv2/imgproc/hal/hal.hpp b/modules/imgproc/include/opencv2/imgproc/hal/hal.hpp index f129012ba6..48851ece07 100644 --- a/modules/imgproc/include/opencv2/imgproc/hal/hal.hpp +++ b/modules/imgproc/include/opencv2/imgproc/hal/hal.hpp @@ -224,6 +224,11 @@ CV_EXPORTS void cvtOnePlaneYUVtoBGR(const uchar * src_data, size_t src_step, int width, int height, int dcn, bool swapBlue, int uIdx, int ycn); +CV_EXPORTS void cvtOnePlaneBGRtoYUV(const uchar * src_data, size_t src_step, + uchar * dst_data, size_t dst_step, + int width, int height, + int scn, bool swapBlue, int uIdx, int ycn); + CV_EXPORTS void cvtRGBAtoMultipliedRGBA(const uchar * src_data, size_t src_step, uchar * dst_data, size_t dst_step, int width, int height); diff --git a/modules/imgproc/perf/opencl/perf_color.cpp b/modules/imgproc/perf/opencl/perf_color.cpp index 9525e1f275..dce588879b 100644 --- a/modules/imgproc/perf/opencl/perf_color.cpp +++ b/modules/imgproc/perf/opencl/perf_color.cpp @@ -58,7 +58,7 @@ CV_ENUM(ConversionTypes, COLOR_RGB2GRAY, COLOR_RGB2BGR, COLOR_RGB2YUV, COLOR_YUV COLOR_YCrCb2RGB, COLOR_RGB2XYZ, COLOR_XYZ2RGB, COLOR_RGB2HSV, COLOR_HSV2RGB, COLOR_RGB2HLS, COLOR_HLS2RGB, COLOR_BGR5652BGR, COLOR_BGR2BGR565, COLOR_RGBA2mRGBA, COLOR_mRGBA2RGBA, COLOR_RGB2Lab, COLOR_Lab2BGR, COLOR_RGB2Luv, COLOR_Luv2LBGR, COLOR_YUV2RGB_NV12, COLOR_YUV2RGB_IYUV, - COLOR_YUV2GRAY_420, COLOR_RGB2YUV_IYUV, COLOR_YUV2RGB_YUY2, COLOR_YUV2GRAY_YUY2) + COLOR_YUV2GRAY_420, COLOR_RGB2YUV_IYUV, COLOR_YUV2RGB_YUY2, COLOR_RGB2YUV_YUY2, COLOR_YUV2GRAY_YUY2) typedef tuple > CvtColorParams; typedef TestBaseWithParam CvtColorFixture; @@ -91,6 +91,7 @@ OCL_PERF_TEST_P(CvtColorFixture, CvtColor, testing::Combine( make_tuple(ConversionTypes(COLOR_YUV2GRAY_420), 1, 1), make_tuple(ConversionTypes(COLOR_RGB2YUV_IYUV), 3, 1), make_tuple(ConversionTypes(COLOR_YUV2RGB_YUY2), 2, 3), + make_tuple(ConversionTypes(COLOR_RGB2YUV_YUY2), 3, 2), make_tuple(ConversionTypes(COLOR_YUV2GRAY_YUY2), 2, 1) ))) { diff --git a/modules/imgproc/perf/perf_cvt_color.cpp b/modules/imgproc/perf/perf_cvt_color.cpp index ab169ecfca..5915b507ce 100644 --- a/modules/imgproc/perf/perf_cvt_color.cpp +++ b/modules/imgproc/perf/perf_cvt_color.cpp @@ -178,7 +178,9 @@ CV_ENUM(CvtModeBayer, CV_ENUM(CvtMode2, COLOR_YUV2BGR_NV12, COLOR_YUV2BGRA_NV12, COLOR_YUV2RGB_NV12, COLOR_YUV2RGBA_NV12, COLOR_YUV2BGR_NV21, COLOR_YUV2BGRA_NV21, COLOR_YUV2RGB_NV21, COLOR_YUV2RGBA_NV21, COLOR_YUV2BGR_YV12, COLOR_YUV2BGRA_YV12, COLOR_YUV2RGB_YV12, COLOR_YUV2RGBA_YV12, COLOR_YUV2BGR_IYUV, COLOR_YUV2BGRA_IYUV, COLOR_YUV2RGB_IYUV, COLOR_YUV2RGBA_IYUV, COLOR_YUV2GRAY_420, COLOR_YUV2RGB_UYVY, COLOR_YUV2BGR_UYVY, COLOR_YUV2RGBA_UYVY, COLOR_YUV2BGRA_UYVY, COLOR_YUV2RGB_YUY2, COLOR_YUV2BGR_YUY2, COLOR_YUV2RGB_YVYU, - COLOR_YUV2BGR_YVYU, COLOR_YUV2RGBA_YUY2, COLOR_YUV2BGRA_YUY2, COLOR_YUV2RGBA_YVYU, COLOR_YUV2BGRA_YVYU) + COLOR_YUV2BGR_YVYU, COLOR_YUV2RGBA_YUY2, COLOR_YUV2BGRA_YUY2, COLOR_YUV2RGBA_YVYU, COLOR_YUV2BGRA_YVYU, + COLOR_RGB2YUV_UYVY, COLOR_BGR2YUV_UYVY, COLOR_RGBA2YUV_UYVY, COLOR_BGRA2YUV_UYVY, COLOR_RGB2YUV_YUY2, COLOR_BGR2YUV_YUY2, COLOR_RGB2YUV_YVYU, + COLOR_BGR2YUV_YVYU, COLOR_RGBA2YUV_YUY2, COLOR_BGRA2YUV_YUY2, COLOR_RGBA2YUV_YVYU, COLOR_BGRA2YUV_YVYU) CV_ENUM(CvtMode3, COLOR_RGB2YUV_IYUV, COLOR_BGR2YUV_IYUV, COLOR_RGBA2YUV_IYUV, COLOR_BGRA2YUV_IYUV, COLOR_RGB2YUV_YV12, COLOR_BGR2YUV_YV12, COLOR_RGBA2YUV_YV12, COLOR_BGRA2YUV_YV12) @@ -225,12 +227,20 @@ static ChPair getConversionInfo(int cvtMode) case COLOR_YUV2RGB_YUY2: case COLOR_YUV2BGR_YUY2: case COLOR_YUV2RGB_YVYU: case COLOR_YUV2BGR_YVYU: return ChPair(2,3); + case COLOR_RGB2YUV_UYVY: case COLOR_BGR2YUV_UYVY: + case COLOR_RGB2YUV_YUY2: case COLOR_BGR2YUV_YUY2: + case COLOR_RGB2YUV_YVYU: case COLOR_BGR2YUV_YVYU: + return ChPair(3,2); case COLOR_BGR5552BGRA: case COLOR_BGR5552RGBA: case COLOR_BGR5652BGRA: case COLOR_BGR5652RGBA: case COLOR_YUV2RGBA_UYVY: case COLOR_YUV2BGRA_UYVY: case COLOR_YUV2RGBA_YUY2: case COLOR_YUV2BGRA_YUY2: case COLOR_YUV2RGBA_YVYU: case COLOR_YUV2BGRA_YVYU: return ChPair(2,4); + case COLOR_RGBA2YUV_UYVY: case COLOR_BGRA2YUV_UYVY: + case COLOR_RGBA2YUV_YUY2: case COLOR_BGRA2YUV_YUY2: + case COLOR_RGBA2YUV_YVYU: case COLOR_BGRA2YUV_YVYU: + return ChPair(4,2); case COLOR_BGR2GRAY: case COLOR_RGB2GRAY: case COLOR_RGB2YUV_IYUV: case COLOR_RGB2YUV_YV12: case COLOR_BGR2YUV_IYUV: case COLOR_BGR2YUV_YV12: diff --git a/modules/imgproc/src/color.cpp b/modules/imgproc/src/color.cpp index cc4dd13c92..4eaa051e24 100644 --- a/modules/imgproc/src/color.cpp +++ b/modules/imgproc/src/color.cpp @@ -90,6 +90,20 @@ static bool ocl_cvtColor( InputArray _src, OutputArray _dst, int code, int dcn ) return oclCvtColorOnePlaneYUV2BGR(_src, _dst, dcn, bidx, uidx, yidx); } + case COLOR_RGB2YUV_UYVY: case COLOR_BGR2YUV_UYVY: case COLOR_RGBA2YUV_UYVY: case COLOR_BGRA2YUV_UYVY: + case COLOR_RGB2YUV_YUY2: case COLOR_BGR2YUV_YUY2: case COLOR_RGB2YUV_YVYU: case COLOR_BGR2YUV_YVYU: + case COLOR_RGBA2YUV_YUY2: case COLOR_BGRA2YUV_YUY2: case COLOR_RGBA2YUV_YVYU: case COLOR_BGRA2YUV_YVYU: + { + int yidx = (code==COLOR_RGB2YUV_UYVY || code==COLOR_RGBA2YUV_UYVY || + code==COLOR_BGR2YUV_UYVY || code==COLOR_BGRA2YUV_UYVY) ? 1 : 0; + int uidx = (code==COLOR_RGB2YUV_YVYU || code==COLOR_RGBA2YUV_YVYU || + code==COLOR_BGR2YUV_YVYU || code==COLOR_BGRA2YUV_YVYU) ? 2 : 0; + uidx = 1 - yidx + uidx; + + bool res = oclCvtColorOnePlaneBGR2YUV(_src, _dst, dcn, bidx, uidx, yidx); + + return res; + } case COLOR_BGR2YCrCb: case COLOR_RGB2YCrCb: return oclCvtColorBGR2YCrCb(_src, _dst, bidx); @@ -339,6 +353,19 @@ void cvtColor( InputArray _src, OutputArray _dst, int code, int dcn ) break; } + case COLOR_RGB2YUV_UYVY: case COLOR_BGR2YUV_UYVY: case COLOR_RGBA2YUV_UYVY: case COLOR_BGRA2YUV_UYVY: + case COLOR_RGB2YUV_YUY2: case COLOR_BGR2YUV_YUY2: case COLOR_RGB2YUV_YVYU: case COLOR_BGR2YUV_YVYU: + case COLOR_RGBA2YUV_YUY2: case COLOR_BGRA2YUV_YUY2: case COLOR_RGBA2YUV_YVYU: case COLOR_BGRA2YUV_YVYU: + //http://www.fourcc.org/yuv.php#UYVY + //http://www.fourcc.org/yuv.php#YUY2 + //http://www.fourcc.org/yuv.php#YVYU + { + int ycn = (code==COLOR_RGB2YUV_UYVY || code==COLOR_BGR2YUV_UYVY || + code==COLOR_RGBA2YUV_UYVY || code==COLOR_BGRA2YUV_UYVY) ? 1 : 0; + cvtColorOnePlaneBGR2YUV(_src, _dst, swapBlue(code), uIndex(code), ycn); + break; + } + case COLOR_YUV2GRAY_UYVY: case COLOR_YUV2GRAY_YUY2: cvtColorYUV2Gray_ch(_src, _dst, code == COLOR_YUV2GRAY_UYVY ? 1 : 0); diff --git a/modules/imgproc/src/color.hpp b/modules/imgproc/src/color.hpp index abbd65ec06..7751d823b1 100644 --- a/modules/imgproc/src/color.hpp +++ b/modules/imgproc/src/color.hpp @@ -71,6 +71,8 @@ inline bool swapBlue(int code) case COLOR_YUV2BGR_UYVY: case COLOR_YUV2BGRA_UYVY: case COLOR_YUV2BGR_YUY2: case COLOR_YUV2BGRA_YUY2: case COLOR_YUV2BGR_YVYU: case COLOR_YUV2BGRA_YVYU: case COLOR_BGR2YUV_IYUV: case COLOR_BGRA2YUV_IYUV: case COLOR_BGR2YUV_YV12: case COLOR_BGRA2YUV_YV12: + case COLOR_BGR2YUV_UYVY: case COLOR_BGRA2YUV_UYVY: case COLOR_BGR2YUV_YUY2: + case COLOR_BGRA2YUV_YUY2: case COLOR_BGR2YUV_YVYU: case COLOR_BGRA2YUV_YVYU: return false; default: return true; @@ -124,6 +126,13 @@ inline int dstChannels(int code) return 3; + case COLOR_RGB2YUV_UYVY: case COLOR_BGR2YUV_UYVY: case COLOR_RGB2YUV_YVYU: case COLOR_BGR2YUV_YVYU: + case COLOR_RGB2YUV_YUY2: case COLOR_BGR2YUV_YUY2: + case COLOR_RGBA2YUV_UYVY: case COLOR_BGRA2YUV_UYVY: case COLOR_RGBA2YUV_YVYU: case COLOR_BGRA2YUV_YVYU: + case COLOR_RGBA2YUV_YUY2: case COLOR_BGRA2YUV_YUY2: + + return 2; + default: return 0; } @@ -159,6 +168,7 @@ inline int uIndex(int code) return 2; case COLOR_YUV2RGB_YVYU: case COLOR_YUV2BGR_YVYU: case COLOR_YUV2RGBA_YVYU: case COLOR_YUV2BGRA_YVYU: + case COLOR_RGB2YUV_YVYU: case COLOR_BGR2YUV_YVYU: case COLOR_RGBA2YUV_YVYU: case COLOR_BGRA2YUV_YVYU: case COLOR_RGB2YUV_IYUV: case COLOR_BGR2YUV_IYUV: case COLOR_RGBA2YUV_IYUV: case COLOR_BGRA2YUV_IYUV: case COLOR_YUV2BGR_NV21: case COLOR_YUV2RGB_NV21: case COLOR_YUV2BGRA_NV21: case COLOR_YUV2RGBA_NV21: case COLOR_YUV2BGR_YV12: case COLOR_YUV2RGB_YV12: case COLOR_YUV2BGRA_YV12: case COLOR_YUV2RGBA_YV12: @@ -169,6 +179,8 @@ inline int uIndex(int code) case COLOR_YUV2BGR_IYUV: case COLOR_YUV2RGB_IYUV: case COLOR_YUV2BGRA_IYUV: case COLOR_YUV2RGBA_IYUV: case COLOR_YUV2RGB_UYVY: case COLOR_YUV2BGR_UYVY: case COLOR_YUV2RGBA_UYVY: case COLOR_YUV2BGRA_UYVY: case COLOR_YUV2RGB_YUY2: case COLOR_YUV2BGR_YUY2: case COLOR_YUV2RGBA_YUY2: case COLOR_YUV2BGRA_YUY2: + case COLOR_RGB2YUV_UYVY: case COLOR_BGR2YUV_UYVY: case COLOR_RGBA2YUV_UYVY: case COLOR_BGRA2YUV_UYVY: + case COLOR_RGB2YUV_YUY2: case COLOR_BGR2YUV_YUY2: case COLOR_RGBA2YUV_YUY2: case COLOR_BGRA2YUV_YUY2: return 0; @@ -529,6 +541,7 @@ bool oclCvtColorBGR2YUV( InputArray _src, OutputArray _dst, int bidx ); bool oclCvtColorYUV2BGR( InputArray _src, OutputArray _dst, int dcn, int bidx ); bool oclCvtColorOnePlaneYUV2BGR( InputArray _src, OutputArray _dst, int dcn, int bidx, int uidx, int yidx ); +bool oclCvtColorOnePlaneBGR2YUV( InputArray _src, OutputArray _dst, int dcn, int bidx, int uidx, int yidx ); bool oclCvtColorTwoPlaneYUV2BGR( InputArray _src, OutputArray _dst, int dcn, int bidx, int uidx ); bool oclCvtColorThreePlaneYUV2BGR( InputArray _src, OutputArray _dst, int dcn, int bidx, int uidx ); bool oclCvtColorBGR2ThreePlaneYUV( InputArray _src, OutputArray _dst, int bidx, int uidx ); @@ -547,6 +560,7 @@ void cvtColorBGR2YUV( InputArray _src, OutputArray _dst, bool swapb, bool crcb); void cvtColorYUV2BGR( InputArray _src, OutputArray _dst, int dcn, bool swapb, bool crcb); void cvtColorOnePlaneYUV2BGR( InputArray _src, OutputArray _dst, int dcn, bool swapb, int uidx, int ycn); +void cvtColorOnePlaneBGR2YUV( InputArray _src, OutputArray _dst, bool swapb, int uidx, int ycn); void cvtColorTwoPlaneYUV2BGR( InputArray _src, OutputArray _dst, int dcn, bool swapb, int uidx ); void cvtColorTwoPlaneYUV2BGRpair( InputArray _ysrc, InputArray _uvsrc, OutputArray _dst, int dcn, bool swapb, int uidx ); void cvtColorThreePlaneYUV2BGR( InputArray _src, OutputArray _dst, int dcn, bool swapb, int uidx ); diff --git a/modules/imgproc/src/color.simd_helpers.hpp b/modules/imgproc/src/color.simd_helpers.hpp index 6642ff69c4..06b9ba3d06 100644 --- a/modules/imgproc/src/color.simd_helpers.hpp +++ b/modules/imgproc/src/color.simd_helpers.hpp @@ -76,7 +76,7 @@ struct Set enum SizePolicy { - TO_YUV, FROM_YUV, FROM_UYVY, NONE + TO_YUV, FROM_YUV, FROM_UYVY, TO_UYVY, NONE }; template< typename VScn, typename VDcn, typename VDepth, SizePolicy sizePolicy = NONE > @@ -109,6 +109,7 @@ struct CvtHelper dstSz = Size(sz.width, sz.height * 2 / 3); break; case FROM_UYVY: + case TO_UYVY: CV_Assert( sz.width % 2 == 0); dstSz = sz; break; diff --git a/modules/imgproc/src/color_yuv.dispatch.cpp b/modules/imgproc/src/color_yuv.dispatch.cpp index 559005e07f..8720908100 100644 --- a/modules/imgproc/src/color_yuv.dispatch.cpp +++ b/modules/imgproc/src/color_yuv.dispatch.cpp @@ -206,6 +206,19 @@ void cvtOnePlaneYUVtoBGR(const uchar * src_data, size_t src_step, CV_CPU_DISPATCH_MODES_ALL); } +void cvtOnePlaneBGRtoYUV(const uchar * src_data, size_t src_step, + uchar * dst_data, size_t dst_step, + int width, int height, + int scn, bool swapBlue, int uIdx, int ycn) +{ + CV_INSTRUMENT_REGION(); + + CALL_HAL(cvtOnePlaneBGRtoYUV, cv_hal_cvtOnePlaneBGRtoYUV, src_data, src_step, dst_data, dst_step, width, height, scn, swapBlue, uIdx, ycn); + + CV_CPU_DISPATCH(cvtOnePlaneBGRtoYUV, (src_data, src_step, dst_data, dst_step, width, height, scn, swapBlue, uIdx, ycn), + CV_CPU_DISPATCH_MODES_ALL); +} + } // namespace hal // @@ -281,6 +294,20 @@ bool oclCvtColorOnePlaneYUV2BGR( InputArray _src, OutputArray _dst, int dcn, int return h.run(); } +bool oclCvtColorOnePlaneBGR2YUV( InputArray _src, OutputArray _dst, int dcn, int bidx, int uidx, int yidx ) +{ + OclHelper< Set<3, 4>, Set<2>, Set > h(_src, _dst, dcn); + + if(!h.createKernel("RGB2YUV_422", ocl::imgproc::color_yuv_oclsrc, + format("-D dcn=%d -D bidx=%d -D uidx=%d -D yidx=%d", dcn, bidx, uidx, yidx + ))) + { + return false; + } + + return h.run(); +} + bool oclCvtColorYUV2Gray_420( InputArray _src, OutputArray _dst ) { OclHelper< Set<1>, Set<1>, Set, FROM_YUV> h(_src, _dst, 1); @@ -360,6 +387,14 @@ void cvtColorOnePlaneYUV2BGR( InputArray _src, OutputArray _dst, int dcn, bool s dcn, swapb, uidx, ycn); } +void cvtColorOnePlaneBGR2YUV( InputArray _src, OutputArray _dst, bool swapb, int uidx, int ycn) +{ + CvtHelper< Set<3, 4>, Set<2>, Set, TO_UYVY > h(_src, _dst, 2); + + hal::cvtOnePlaneBGRtoYUV(h.src.data, h.src.step, h.dst.data, h.dst.step, h.src.cols, h.src.rows, + h.scn, swapb, uidx, ycn); +} + void cvtColorYUV2Gray_ch( InputArray _src, OutputArray _dst, int coi ) { CV_Assert( _src.channels() == 2 && _src.depth() == CV_8U ); diff --git a/modules/imgproc/src/color_yuv.simd.hpp b/modules/imgproc/src/color_yuv.simd.hpp index 580329f660..03f1b653e5 100644 --- a/modules/imgproc/src/color_yuv.simd.hpp +++ b/modules/imgproc/src/color_yuv.simd.hpp @@ -37,6 +37,10 @@ void cvtOnePlaneYUVtoBGR(const uchar * src_data, size_t src_step, uchar * dst_data, size_t dst_step, int width, int height, int dcn, bool swapBlue, int uIdx, int ycn); +void cvtOnePlaneBGRtoYUV(const uchar * src_data, size_t src_step, + uchar * dst_data, size_t dst_step, + int width, int height, + int scn, bool swapBlue, int uIdx, int ycn); #ifndef CV_CPU_OPTIMIZATION_DECLARATIONS_ONLY @@ -1852,6 +1856,114 @@ inline void cvtYUV422toRGB(uchar * dst_data, size_t dst_step, const uchar * src_ converter(Range(0, height)); } + +///////////////////////////////////// RGB -> YUV422 ///////////////////////////////////// + +static const int RGB2YUV422_SHIFT = 14; + +// Coefficients based on ITU.BT-601, ISBN 1-878707-09-4 (https://fourcc.org/fccyvrgb.php) +// The conversion coefficients for RGB to YUV422 are based on the ones for RGB to YUV. +// For both Y components, the coefficients are applied as given in the link to each input RGB pixel +// separately. For U and V, they are reduced by half to account for two RGB pixels contributing +// to the same U and V values. In other words, the U and V contributions from the two RGB pixels +// are averaged. The integer versions are obtained by multiplying the float versions by 16384 +// and rounding to the nearest integer. + +int c_RGB2YUV422Coeffs_i[10] = {1024, 8192, 4211, 8258, 1606, + -1212, -2384, 3596, -3015, -582}; + +static inline void RGB2Y(const uchar r, const uchar g, const uchar b, uchar& y) +{ + int y_ = r * c_RGB2YUV422Coeffs_i[2] + g * c_RGB2YUV422Coeffs_i[3] + + b * c_RGB2YUV422Coeffs_i[4] + c_RGB2YUV422Coeffs_i[0]*256; + y = saturate_cast(((1 << (RGB2YUV422_SHIFT-1)) + y_) >> RGB2YUV422_SHIFT); +} + +static inline void RGB2UV(const uchar r1, const uchar g1, const uchar b1, + const uchar r2, const uchar g2, const uchar b2, + uchar& u, uchar& v) +{ + int sr = r1 + r2, sg = g1 + g2, sb = b1 + b2; + + int u_ = sr * c_RGB2YUV422Coeffs_i[5] + sg * c_RGB2YUV422Coeffs_i[6] + + sb * c_RGB2YUV422Coeffs_i[7] + c_RGB2YUV422Coeffs_i[1]*256; + u = saturate_cast(((1 << (RGB2YUV422_SHIFT-1)) + u_) >> RGB2YUV422_SHIFT); + + int v_ = sr * c_RGB2YUV422Coeffs_i[7] + sg * c_RGB2YUV422Coeffs_i[8] + + sb * c_RGB2YUV422Coeffs_i[9] + c_RGB2YUV422Coeffs_i[1]*256; + v = saturate_cast(((1 << (RGB2YUV422_SHIFT-1)) + v_) >> RGB2YUV422_SHIFT); +} + +template +static inline void cvtRGB82Yuv422(const uchar r1, const uchar g1, const uchar b1, + const uchar r2, const uchar g2, const uchar b2, + uchar* row) +{ + uchar &u = row[uidx], &v = row[vidx], &y1 = row[yidx], &y2 = row[yidx+2]; + + RGB2Y(r1, g1, b1, y1); + RGB2Y(r2, g2, b2, y2); + + RGB2UV(r1, g1, b1, r2, g2, b2, u, v); +} + +// bIdx is 0 or 2; [uIdx, yIdx] is [0, 0], [0, 1], [1, 0]; scn is 3 or 4 +template +struct RGB8toYUV422Invoker : ParallelLoopBody +{ + uchar * dst_data; + size_t dst_step; + const uchar * src_data; + size_t src_step; + int width; + + RGB8toYUV422Invoker(uchar * _dst_data, size_t _dst_step, + const uchar * _src_data, size_t _src_step, + int _width) + : dst_data(_dst_data), dst_step(_dst_step), src_data(_src_data), src_step(_src_step), width(_width) {} + + void operator()(const Range& range) const CV_OVERRIDE + { + int rangeBegin = range.start; + int rangeEnd = range.end; + + // [yIdx, uIdx] | [uidx, vidx]: + // 0, 0 | 1, 3 + // 0, 1 | 3, 1 + // 1, 0 | 0, 2 + const int uidx = 1 - yIdx + uIdx * 2; + const int vidx = (2 + uidx) % 4; + const int ridx = (2-bIdx); + const uchar* rgb_src = src_data + rangeBegin * (src_step); + const uchar* rgb_src2 = rgb_src+scn; + + for (int j = rangeBegin; j < rangeEnd; j++, rgb_src += src_step, rgb_src2 = rgb_src+scn) + { + uchar* row = dst_data + (dst_step) * j; + int i = 0; + for (; i < scn * width; i += (scn << 1), row += 4) + { + const uchar r1 = rgb_src[i+ridx], g1 = rgb_src[i+1], b1 = rgb_src[i+bIdx]; + const uchar r2 = rgb_src2[i+ridx], g2 = rgb_src2[i+1], b2 = rgb_src2[i+bIdx]; + + cvtRGB82Yuv422(r1, g1, b1, r2, g2, b2, row); + } + } + } +}; + +template +inline void cvtRGBtoYUV422(uchar * dst_data, size_t dst_step, const uchar * src_data, size_t src_step, + int width, int height) +{ + RGB8toYUV422Invoker converter(dst_data, dst_step, src_data, src_step, width); + if (width * height >= MIN_SIZE_FOR_PARALLEL_YUV422_CONVERSION) + parallel_for_(Range(0, height), converter); + else + converter(Range(0, height)); +} + + } // namespace anon @@ -2033,6 +2145,35 @@ void cvtOnePlaneYUVtoBGR(const uchar * src_data, size_t src_step, cvtPtr(dst_data, dst_step, src_data, src_step, width, height); } +void cvtOnePlaneBGRtoYUV(const uchar * src_data, size_t src_step, + uchar * dst_data, size_t dst_step, + int width, int height, + int scn, bool swapBlue, int uIdx, int ycn) +{ + CV_INSTRUMENT_REGION(); + + cvt_1plane_yuv_ptr_t cvtPtr; + int blueIdx = swapBlue ? 2 : 0; + switch(scn*1000 + blueIdx*100 + uIdx*10 + ycn) + { + case 3000: cvtPtr = cvtRGBtoYUV422<0,0,0,3>; break; + case 3001: cvtPtr = cvtRGBtoYUV422<0,0,1,3>; break; + case 3010: cvtPtr = cvtRGBtoYUV422<0,1,0,3>; break; + case 3200: cvtPtr = cvtRGBtoYUV422<2,0,0,3>; break; + case 3201: cvtPtr = cvtRGBtoYUV422<2,0,1,3>; break; + case 3210: cvtPtr = cvtRGBtoYUV422<2,1,0,3>; break; + case 4000: cvtPtr = cvtRGBtoYUV422<0,0,0,4>; break; + case 4001: cvtPtr = cvtRGBtoYUV422<0,0,1,4>; break; + case 4010: cvtPtr = cvtRGBtoYUV422<0,1,0,4>; break; + case 4200: cvtPtr = cvtRGBtoYUV422<2,0,0,4>; break; + case 4201: cvtPtr = cvtRGBtoYUV422<2,0,1,4>; break; + case 4210: cvtPtr = cvtRGBtoYUV422<2,1,0,4>; break; + default: CV_Error( CV_StsBadFlag, "Unknown/unsupported color conversion code" ); break; + }; + + cvtPtr(dst_data, dst_step, src_data, src_step, width, height); +} + #endif CV_CPU_OPTIMIZATION_NAMESPACE_END }} // namespace diff --git a/modules/imgproc/src/hal_replacement.hpp b/modules/imgproc/src/hal_replacement.hpp index f285f4c1b0..c066f3d6f3 100644 --- a/modules/imgproc/src/hal_replacement.hpp +++ b/modules/imgproc/src/hal_replacement.hpp @@ -639,6 +639,19 @@ inline int hal_ni_cvtBGRtoThreePlaneYUV(const uchar * src_data, size_t src_step, */ inline int hal_ni_cvtOnePlaneYUVtoBGR(const uchar * src_data, size_t src_step, uchar * dst_data, size_t dst_step, int width, int height, int dcn, bool swapBlue, int uIdx, int ycn) { return CV_HAL_ERROR_NOT_IMPLEMENTED; } +/** + @brief hal_cvtOnePlaneBGRtoYUV + @param src_data,src_step source image data and step + @param dst_data,dst_step destination image data and step + @param width,height image size + @param scn source image channels (3 or 4) + @param swapBlue if set to true B and R destination channels will be swapped (write RGB) + @param uIdx U-channel index (0 or 1) + @param ycn Y-channel index (0 or 1) + Convert from BGR, RGB, BGRA or RGBA to UYVY, YUY2 or YVYU. + Only for CV_8U. + */ +inline int hal_ni_cvtOnePlaneBGRtoYUV(const uchar * src_data, size_t src_step, uchar * dst_data, size_t dst_step, int width, int height, int scn, bool swapBlue, int uIdx, int ycn) { return CV_HAL_ERROR_NOT_IMPLEMENTED; } /** @brief hal_cvtRGBAtoMultipliedRGBA @@ -688,6 +701,7 @@ inline int hal_ni_cvtMultipliedRGBAtoRGBA(const uchar * src_data, size_t src_ste #define cv_hal_cvtThreePlaneYUVtoBGR hal_ni_cvtThreePlaneYUVtoBGR #define cv_hal_cvtBGRtoThreePlaneYUV hal_ni_cvtBGRtoThreePlaneYUV #define cv_hal_cvtOnePlaneYUVtoBGR hal_ni_cvtOnePlaneYUVtoBGR +#define cv_hal_cvtOnePlaneBGRtoYUV hal_ni_cvtOnePlaneBGRtoYUV #define cv_hal_cvtRGBAtoMultipliedRGBA hal_ni_cvtRGBAtoMultipliedRGBA #define cv_hal_cvtMultipliedRGBAtoRGBA hal_ni_cvtMultipliedRGBAtoRGBA //! @endcond diff --git a/modules/imgproc/src/opencl/color_yuv.cl b/modules/imgproc/src/opencl/color_yuv.cl index bf75a1c5b8..c536f87a0b 100644 --- a/modules/imgproc/src/opencl/color_yuv.cl +++ b/modules/imgproc/src/opencl/color_yuv.cl @@ -568,6 +568,76 @@ __kernel void YUV2RGB_422(__global const uchar* srcptr, int src_step, int src_of } } +// Coefficients based on ITU.BT-601, ISBN 1-878707-09-4 (https://fourcc.org/fccyvrgb.php) +// The conversion coefficients for RGB to YUV422 are based on the ones for RGB to YUV. +// For both Y components, the coefficients are applied as given in the link to each input RGB pixel +// separately. For U and V, they are reduced by half to account for two RGB pixels contributing +// to the same U and V values. In other words, the U and V contributions from the two RGB pixels +// are averaged. The integer versions are obtained by multiplying the float versions by 16384 +// and rounding to the nearest integer. + +__constant float c_RGB2YUV422Coeffs_f[10] = {0.0625, 0.5, 0.257, 0.504, 0.098, -0.074 , -0.1455, 0.2195, -0.184 , -0.0355}; +__constant int c_RGB2YUV422Coeffs_i[10] = {1024 * HALF_MAX_NUM * 2, 8192 * HALF_MAX_NUM * 2, 4211, 8258, 1606, -1212, -2384, 3596, -3015, -582}; + +__kernel void RGB2YUV_422(__global const uchar* srcptr, int src_step, int src_offset, + __global uchar* dstptr, int dst_step, int dst_offset, + int rows, int cols) +{ + int x = get_global_id(0); + int y = get_global_id(1) * PIX_PER_WI_Y; + + if (x < cols/2) + { + int src_index = mad24(y, src_step, mad24(x << 1, scnbytes, src_offset)); + int dst_index = mad24(y, dst_step, mad24(x << 1, dcnbytes, dst_offset)); + + #pragma unroll + for (int cy = 0; cy < PIX_PER_WI_Y; ++cy) + { + if (y < rows) + { + __global const DATA_TYPE* src = (__global const DATA_TYPE*)(srcptr + src_index); + __global DATA_TYPE* dst = (__global DATA_TYPE*)(dstptr + dst_index); + DATA_TYPE_3 src_pix1 = vload3(0, src); + DATA_TYPE b1 = src_pix1.B_COMP, g1 = src_pix1.G_COMP, r1 = src_pix1.R_COMP; + DATA_TYPE_3 src_pix2 = vload3(0, src+scn); + DATA_TYPE b2 = src_pix2.B_COMP, g2 = src_pix2.G_COMP, r2 = src_pix2.R_COMP; + + +#ifdef DEPTH_5 + __constant float * coeffs = c_RGB2YUV422Coeffs_f; + #define MAC_fn fma + #define res_dtype DATA_TYPE + #define mul_fn(x,y) (x*y) + #define output_scale_fn(x) x +#else + __constant int * coeffs = c_RGB2YUV422Coeffs_i; + #define MAC_fn mad24 + #define res_dtype int + #define mul_fn mul24 + #define output_scale_fn(x) SAT_CAST(CV_DESCALE(x, yuv_shift)) +#endif + + const res_dtype Y1 = MAC_fn(coeffs[2], r1, coeffs[0] + MAC_fn(coeffs[3], g1, mul_fn(coeffs[4], b1))); + const res_dtype Y2 = MAC_fn(coeffs[2], r2, coeffs[0] + MAC_fn(coeffs[3], g2, mul_fn(coeffs[4], b2))); + + const res_dtype sr = r1+r2, sg = g1+g2, sb = b1+b2; + const res_dtype U = MAC_fn(coeffs[5], sr, coeffs[1] + MAC_fn(coeffs[6], sg, mul_fn(coeffs[7], sb))); + const res_dtype V = MAC_fn(coeffs[7], sr, coeffs[1] + MAC_fn(coeffs[8], sg, mul_fn(coeffs[9], sb))); + + dst[uidx] = output_scale_fn(U); + dst[(2 + uidx) % 4] = output_scale_fn(V); + dst[yidx] = output_scale_fn(Y1); + dst[yidx+2] = output_scale_fn(Y2); + + ++y; + dst_index += dst_step; + src_index += src_step; + } + } + } +} + ///////////////////////////////////// RGB <-> YCrCb ////////////////////////////////////// __constant float c_RGB2YCrCbCoeffs_f[5] = {R2YF, G2YF, B2YF, YCRF, YCBF}; diff --git a/modules/imgproc/test/ocl/test_color.cpp b/modules/imgproc/test/ocl/test_color.cpp index bdbc6a90d0..55401ba73c 100644 --- a/modules/imgproc/test/ocl/test_color.cpp +++ b/modules/imgproc/test/ocl/test_color.cpp @@ -458,6 +458,43 @@ OCL_TEST_P(CvtColor_YUV2RGB_422, YUV2BGR_YVYU) { performTest(2, 3, CVTCODE(YUV2B OCL_TEST_P(CvtColor_YUV2RGB_422, YUV2RGBA_YVYU) { performTest(2, 4, CVTCODE(YUV2RGBA_YVYU)); } OCL_TEST_P(CvtColor_YUV2RGB_422, YUV2BGRA_YVYU) { performTest(2, 4, CVTCODE(YUV2BGRA_YVYU)); } +// RGBA -> YUV422 + +struct CvtColor_RGB2YUV_422 : + public CvtColor +{ + void generateTestData(int channelsIn, int channelsOut) + { + const int srcType = CV_MAKE_TYPE(depth, channelsIn); + const int dstType = CV_MAKE_TYPE(depth, channelsOut); + + Size roiSize = randomSize(1, MAX_VALUE); + roiSize.width *= 2; + roiSize.height *= 2; + + Border srcBorder = randomBorder(0, use_roi ? MAX_VALUE : 0); + randomSubMat(src, src_roi, roiSize, srcBorder, srcType, 2, 100); + + Border dstBorder = randomBorder(0, use_roi ? MAX_VALUE : 0); + randomSubMat(dst, dst_roi, roiSize, dstBorder, dstType, 6, 16); + + UMAT_UPLOAD_INPUT_PARAMETER(src); + UMAT_UPLOAD_OUTPUT_PARAMETER(dst); + } +}; + +OCL_TEST_P(CvtColor_RGB2YUV_422, RGB2YUV_UYVY) { performTest(3, 2, CVTCODE(RGB2YUV_UYVY)); } +OCL_TEST_P(CvtColor_RGB2YUV_422, BGR2YUV_UYVY) { performTest(3, 2, CVTCODE(BGR2YUV_UYVY)); } +OCL_TEST_P(CvtColor_RGB2YUV_422, RGBA2YUV_UYVY) { performTest(4, 2, CVTCODE(RGBA2YUV_UYVY)); } +OCL_TEST_P(CvtColor_RGB2YUV_422, BGRA2YUV_UYVY) { performTest(4, 2, CVTCODE(BGRA2YUV_UYVY)); } +OCL_TEST_P(CvtColor_RGB2YUV_422, RGB2YUV_YUY2) { performTest(3, 2, CVTCODE(RGB2YUV_YUY2)); } +OCL_TEST_P(CvtColor_RGB2YUV_422, BGR2YUV_YUY2) { performTest(3, 2, CVTCODE(BGR2YUV_YUY2)); } +OCL_TEST_P(CvtColor_RGB2YUV_422, RGBA2YUV_YUY2) { performTest(4, 2, CVTCODE(RGBA2YUV_YUY2)); } +OCL_TEST_P(CvtColor_RGB2YUV_422, BGRA2YUV_YUY2) { performTest(4, 2, CVTCODE(BGRA2YUV_YUY2)); } +OCL_TEST_P(CvtColor_RGB2YUV_422, RGB2YUV_YVYU) { performTest(3, 2, CVTCODE(RGB2YUV_YVYU)); } +OCL_TEST_P(CvtColor_RGB2YUV_422, BGR2YUV_YVYU) { performTest(3, 2, CVTCODE(BGR2YUV_YVYU)); } +OCL_TEST_P(CvtColor_RGB2YUV_422, RGBA2YUV_YVYU) { performTest(4, 2, CVTCODE(RGBA2YUV_YVYU)); } +OCL_TEST_P(CvtColor_RGB2YUV_422, BGRA2YUV_YVYU) { performTest(4, 2, CVTCODE(BGRA2YUV_YVYU)); } OCL_INSTANTIATE_TEST_CASE_P(ImgProc, CvtColor8u, testing::Combine(testing::Values(MatDepth(CV_8U)), Bool())); @@ -485,6 +522,11 @@ OCL_INSTANTIATE_TEST_CASE_P(ImgProc, CvtColor_YUV2RGB_422, testing::Values(MatDepth(CV_8U)), Bool())); +OCL_INSTANTIATE_TEST_CASE_P(ImgProc, CvtColor_RGB2YUV_422, + testing::Combine( + testing::Values(MatDepth(CV_8U)), + Bool())); + } } // namespace opencv_test::ocl #endif diff --git a/modules/imgproc/test/test_cvtyuv.cpp b/modules/imgproc/test/test_cvtyuv.cpp index cb49baab0a..7114ef035d 100644 --- a/modules/imgproc/test/test_cvtyuv.cpp +++ b/modules/imgproc/test/test_cvtyuv.cpp @@ -159,6 +159,42 @@ class I420Writer: public YUV420pWriter } }; +class YUV422Writer: public YUVwriter +{ + int channels() { return 2; } + Size size(Size imgSize) { return Size(imgSize.width, imgSize.height); } +}; + +class UYVYWriter: public YUV422Writer +{ + virtual void write(Mat& yuv, int row, int col, const YUV& val) + { + yuv.ptr(row)[col][1] = val[0]; + yuv.ptr(row)[(col/2)*2][0] = val[1]; + yuv.ptr(row)[(col/2)*2 + 1][0] = val[2]; + } +}; + +class YUY2Writer: public YUV422Writer +{ + virtual void write(Mat& yuv, int row, int col, const YUV& val) + { + yuv.ptr(row)[col][0] = val[0]; + yuv.ptr(row)[(col/2)*2][1] = val[1]; + yuv.ptr(row)[(col/2)*2 + 1][1] = val[2]; + } +}; + +class YVYUWriter: public YUV422Writer +{ + virtual void write(Mat& yuv, int row, int col, const YUV& val) + { + yuv.ptr(row)[col][0] = val[0]; + yuv.ptr(row)[(col/2)*2 + 1][1] = val[1]; + yuv.ptr(row)[(col/2)*2][1] = val[2]; + } +}; + class YUV420Reader: public YUVreader { int channels() { return 1; } @@ -357,6 +393,36 @@ public: } }; +class RGB2YUV422_Converter +{ +public: + YUV convert(RGB rgb1, RGB rgb2, int idx) + { + int r1 = rgb1[0]; + int g1 = rgb1[1]; + int b1 = rgb1[2]; + + int r2 = rgb2[0]; + int g2 = rgb2[1]; + int b2 = rgb2[2]; + + // Coefficients below based on ITU.BT-601, ISBN 1-878707-09-4 (https://fourcc.org/fccyvrgb.php) + // The conversion coefficients for RGB to YUV422 are based on the ones for RGB to YUV. + // For both Y components, the coefficients are applied as given in the link to each input RGB pixel + // separately. For U and V, they are reduced by half to account for two RGB pixels contributing + // to the same U and V values. In other words, the U and V contributions from the two RGB pixels + // are averaged. The integer versions are obtained by multiplying the float versions by 16384 + // and rounding to the nearest integer. + + uchar y1 = saturate_cast((int)( 0.257f*r1 + 0.504f*g1 + 0.098f*b1 + 16)); + uchar y2 = saturate_cast((int)( 0.257f*r2 + 0.504f*g2 + 0.098f*b2 + 16)); + uchar u = saturate_cast((int)(-0.074f*(r1+r2) - 0.1455f*(g1+g2) + 0.2195f*(b1+b2) + 128)); + uchar v = saturate_cast((int)( 0.2195f*(r1+r2) - 0.184f*(g1+g2) - 0.0355f*(b1+b2) + 128)); + + return YUV((idx==0)?y1:y2, u, v); + } +}; + YUVreader* YUVreader::getReader(int code) { switch(code) @@ -421,15 +487,27 @@ RGBreader* RGBreader::getReader(int code) { case COLOR_RGB2YUV_YV12: case COLOR_RGB2YUV_I420: + case COLOR_RGB2YUV_UYVY: + case COLOR_RGB2YUV_YUY2: + case COLOR_RGB2YUV_YVYU: return new RGB888Reader(); case COLOR_BGR2YUV_YV12: case COLOR_BGR2YUV_I420: + case COLOR_BGR2YUV_UYVY: + case COLOR_BGR2YUV_YUY2: + case COLOR_BGR2YUV_YVYU: return new BGR888Reader(); case COLOR_RGBA2YUV_I420: case COLOR_RGBA2YUV_YV12: + case COLOR_RGBA2YUV_UYVY: + case COLOR_RGBA2YUV_YUY2: + case COLOR_RGBA2YUV_YVYU: return new RGBA8888Reader(); case COLOR_BGRA2YUV_YV12: case COLOR_BGRA2YUV_I420: + case COLOR_BGRA2YUV_UYVY: + case COLOR_BGRA2YUV_YUY2: + case COLOR_BGRA2YUV_YVYU: return new BGRA8888Reader(); default: return 0; @@ -505,6 +583,21 @@ YUVwriter* YUVwriter::getWriter(int code) case COLOR_RGBA2YUV_YV12: case COLOR_BGRA2YUV_YV12: return new YV12Writer(); + case COLOR_RGB2YUV_UYVY: + case COLOR_BGR2YUV_UYVY: + case COLOR_RGBA2YUV_UYVY: + case COLOR_BGRA2YUV_UYVY: + return new UYVYWriter(); + case COLOR_RGB2YUV_YUY2: + case COLOR_BGR2YUV_YUY2: + case COLOR_RGBA2YUV_YUY2: + case COLOR_BGRA2YUV_YUY2: + return new YUY2Writer(); + case COLOR_RGB2YUV_YVYU: + case COLOR_BGR2YUV_YVYU: + case COLOR_RGBA2YUV_YVYU: + case COLOR_BGRA2YUV_YVYU: + return new YVYUWriter(); case COLOR_RGB2YUV_I420: case COLOR_BGR2YUV_I420: case COLOR_RGBA2YUV_I420: @@ -545,6 +638,21 @@ void referenceRGB2YUV(const Mat& rgb, Mat& yuv, RGBreader* rgbReader, YUVwriter* yuvWriter->write(yuv, row, col, cvt.convert(rgbReader->read(rgb, row, col))); } +template +void referenceRGB2YUV422(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+=2) + { + yuvWriter->write(yuv, row, col, cvt.convert(rgbReader->read(rgb, row, col), rgbReader->read(rgb, row, col+1), 0)); + yuvWriter->write(yuv, row, col+1, cvt.convert(rgbReader->read(rgb, row, col), rgbReader->read(rgb, row, col+1), 1)); + } + } +} + struct ConversionYUV { explicit ConversionYUV( const int code ) @@ -611,6 +719,28 @@ struct ConversionYUV GRAYwriter* grayWriter_; }; +bool is_rgb2yuv422(int code) +{ + switch (code) + { + case COLOR_RGB2YUV_UYVY: + case COLOR_BGR2YUV_UYVY: + case COLOR_RGBA2YUV_UYVY: + case COLOR_BGRA2YUV_UYVY: + case COLOR_RGB2YUV_YUY2: + case COLOR_BGR2YUV_YUY2: + case COLOR_RGBA2YUV_YUY2: + case COLOR_BGRA2YUV_YUY2: + case COLOR_RGB2YUV_YVYU: + case COLOR_BGR2YUV_YVYU: + case COLOR_RGBA2YUV_YVYU: + case COLOR_BGRA2YUV_YVYU: + return true; + default: + return false; + } +} + CV_ENUM(YUVCVTS, COLOR_YUV2RGB_NV12, COLOR_YUV2BGR_NV12, COLOR_YUV2RGB_NV21, COLOR_YUV2BGR_NV21, COLOR_YUV2RGBA_NV12, COLOR_YUV2BGRA_NV12, COLOR_YUV2RGBA_NV21, COLOR_YUV2BGRA_NV21, COLOR_YUV2RGB_YV12, COLOR_YUV2BGR_YV12, COLOR_YUV2RGB_IYUV, COLOR_YUV2BGR_IYUV, @@ -620,13 +750,18 @@ CV_ENUM(YUVCVTS, COLOR_YUV2RGB_NV12, COLOR_YUV2BGR_NV12, COLOR_YUV2RGB_NV21, COL COLOR_YUV2RGBA_YUY2, COLOR_YUV2BGRA_YUY2, COLOR_YUV2RGBA_YVYU, COLOR_YUV2BGRA_YVYU, COLOR_YUV2GRAY_420, COLOR_YUV2GRAY_UYVY, COLOR_YUV2GRAY_YUY2, COLOR_YUV2BGR, COLOR_YUV2RGB, COLOR_RGB2YUV_YV12, COLOR_BGR2YUV_YV12, COLOR_RGBA2YUV_YV12, - COLOR_BGRA2YUV_YV12, COLOR_RGB2YUV_I420, COLOR_BGR2YUV_I420, COLOR_RGBA2YUV_I420, COLOR_BGRA2YUV_I420) + COLOR_BGRA2YUV_YV12, COLOR_RGB2YUV_I420, COLOR_BGR2YUV_I420, COLOR_RGBA2YUV_I420, COLOR_BGRA2YUV_I420, + COLOR_RGB2YUV_UYVY, COLOR_BGR2YUV_UYVY, COLOR_RGBA2YUV_UYVY, COLOR_BGRA2YUV_UYVY, + COLOR_RGB2YUV_YUY2, COLOR_BGR2YUV_YUY2, COLOR_RGB2YUV_YVYU, COLOR_BGR2YUV_YVYU, + COLOR_RGBA2YUV_YUY2, COLOR_BGRA2YUV_YUY2, COLOR_RGBA2YUV_YVYU, COLOR_BGRA2YUV_YVYU) typedef ::testing::TestWithParam Imgproc_ColorYUV; TEST_P(Imgproc_ColorYUV, accuracy) { int code = GetParam(); + bool yuv422 = is_rgb2yuv422(code); + RNG& random = theRNG(); ConversionYUV cvt(code); @@ -654,7 +789,12 @@ TEST_P(Imgproc_ColorYUV, accuracy) else if(cvt.grayWriter_) referenceYUV2GRAY(src, gold, cvt.yuvReader_, cvt.grayWriter_); else if(cvt.yuvWriter_) - referenceRGB2YUV (src, gold, cvt.rgbReader_, cvt.yuvWriter_); + { + if(!yuv422) + referenceRGB2YUV (src, gold, cvt.rgbReader_, cvt.yuvWriter_); + else + referenceRGB2YUV422 (src, gold, cvt.rgbReader_, cvt.yuvWriter_); + } cv::cvtColor(src, dst, code, -1); @@ -665,6 +805,8 @@ TEST_P(Imgproc_ColorYUV, accuracy) TEST_P(Imgproc_ColorYUV, roi_accuracy) { int code = GetParam(); + bool yuv422 = is_rgb2yuv422(code); + RNG& random = theRNG(); ConversionYUV cvt(code); @@ -701,7 +843,12 @@ TEST_P(Imgproc_ColorYUV, roi_accuracy) else if(cvt.grayWriter_) referenceYUV2GRAY(src, gold, cvt.yuvReader_, cvt.grayWriter_); else if(cvt.yuvWriter_) - referenceRGB2YUV (src, gold, cvt.rgbReader_, cvt.yuvWriter_); + { + if(!yuv422) + referenceRGB2YUV (src, gold, cvt.rgbReader_, cvt.yuvWriter_); + else + referenceRGB2YUV422 (src, gold, cvt.rgbReader_, cvt.yuvWriter_); + } cv::cvtColor(src, dst, code, -1); @@ -722,7 +869,11 @@ INSTANTIATE_TEST_CASE_P(cvt422, Imgproc_ColorYUV, ::testing::Values((int)COLOR_YUV2RGB_UYVY, (int)COLOR_YUV2BGR_UYVY, (int)COLOR_YUV2RGBA_UYVY, (int)COLOR_YUV2BGRA_UYVY, (int)COLOR_YUV2RGB_YUY2, (int)COLOR_YUV2BGR_YUY2, (int)COLOR_YUV2RGB_YVYU, (int)COLOR_YUV2BGR_YVYU, (int)COLOR_YUV2RGBA_YUY2, (int)COLOR_YUV2BGRA_YUY2, (int)COLOR_YUV2RGBA_YVYU, (int)COLOR_YUV2BGRA_YVYU, - (int)COLOR_YUV2GRAY_UYVY, (int)COLOR_YUV2GRAY_YUY2)); + (int)COLOR_YUV2GRAY_UYVY, (int)COLOR_YUV2GRAY_YUY2, + (int)COLOR_RGB2YUV_UYVY, (int)COLOR_BGR2YUV_UYVY, (int)COLOR_RGBA2YUV_UYVY, (int)COLOR_BGRA2YUV_UYVY, + (int)COLOR_RGB2YUV_YUY2, (int)COLOR_BGR2YUV_YUY2, (int)COLOR_RGB2YUV_YVYU, (int)COLOR_BGR2YUV_YVYU, + (int)COLOR_RGBA2YUV_YUY2, (int)COLOR_BGRA2YUV_YUY2, (int)COLOR_RGBA2YUV_YVYU, (int)COLOR_BGRA2YUV_YVYU, + (int)COLOR_RGB2YUV_YUY2)); }