From cdda5ec491466c79f410d85bea6daa5a326c55e2 Mon Sep 17 00:00:00 2001 From: Andrey Kamaev Date: Sat, 4 Jun 2011 18:15:52 +0000 Subject: [PATCH] YUV420i to RGB conversion is added to cvtColor --- .../imgproc/include/opencv2/imgproc/types_c.h | 3 + modules/imgproc/src/color.cpp | 160 +++++++++++++++++- modules/imgproc/src/thresh.cpp | 1 - modules/video/src/lkpyramid.cpp | 3 +- 4 files changed, 160 insertions(+), 7 deletions(-) diff --git a/modules/imgproc/include/opencv2/imgproc/types_c.h b/modules/imgproc/include/opencv2/imgproc/types_c.h index ed6e49231..7c3b5a37e 100644 --- a/modules/imgproc/include/opencv2/imgproc/types_c.h +++ b/modules/imgproc/include/opencv2/imgproc/types_c.h @@ -225,6 +225,9 @@ enum CV_BayerGB2GRAY = 87, CV_BayerRG2GRAY = 88, CV_BayerGR2GRAY = 89, + + CV_YUV420i2RGB = 90, + CV_YUV420i2BGR = 91, CV_COLORCVT_MAX =100 }; diff --git a/modules/imgproc/src/color.cpp b/modules/imgproc/src/color.cpp index bf65a319f..ea139530b 100644 --- a/modules/imgproc/src/color.cpp +++ b/modules/imgproc/src/color.cpp @@ -2648,10 +2648,130 @@ static void Bayer2RGB_VNG_8u( const Mat& srcmat, Mat& dstmat, int code ) } } -} +///////////////////////////////////// YUV420i -> RGB ///////////////////////////////////// + +template +struct YUV420i2BGR888Invoker +{ + Mat& dst; + const uchar* my1, *muv; + int width; + + YUV420i2BGR888Invoker(Mat& _dst, int _width, const uchar* _y1, const uchar* _uv) + : dst(_dst), my1(_y1), muv(_uv), width(_width) {} + + void operator()(const BlockedRange& range) const + { + //B = 1.164(Y - 16) + 2.018(U - 128) + //G = 1.164(Y - 16) - 0.813(V - 128) - 0.391(U - 128) + //R = 1.164(Y - 16) + 1.596(V - 128) + + const uchar* y1 = my1 + range.begin() * width, *uv = muv + range.begin() * width / 2; + + for (int j = range.begin(); j < range.end(); j+=2, y1+=width*2, uv+=width) + { + uchar* row1 = dst.ptr(j); + uchar* row2 = dst.ptr(j+1); + const uchar* y2 = y1 + width; + + for(int i = 0; i < width; i+=2,row1+=6,row2+=6) + { + int cr = uv[i] - 128; + int cb = uv[i+1] - 128; + + int ruv = 409 * cr + 128; + int guv = 128 - 100 * cb - 208 * cr; + int buv = 516 * cb + 128; + + int y00 = (y1[i] - 16) * 298; + row1[0+R] = saturate_cast((y00 + buv) >> 8); + row1[1] = saturate_cast((y00 + guv) >> 8); + row1[2-R] = saturate_cast((y00 + ruv) >> 8); + + int y01 = (y1[i+1] - 16) * 298; + row1[3+R] = saturate_cast((y01 + buv) >> 8); + row1[4] = saturate_cast((y01 + guv) >> 8); + row1[5-R] = saturate_cast((y01 + ruv) >> 8); + + int y10 = (y2[i] - 16) * 298; + row2[0+R] = saturate_cast((y10 + buv) >> 8); + row2[1] = saturate_cast((y10 + guv) >> 8); + row2[2-R] = saturate_cast((y10 + ruv) >> 8); + + int y11 = (y2[i+1] - 16) * 298; + row2[3+R] = saturate_cast((y11 + buv) >> 8); + row2[4] = saturate_cast((y11 + guv) >> 8); + row2[5-R] = saturate_cast((y11 + ruv) >> 8); + } + } + } +}; + +template +struct YUV420i2BGRA8888Invoker +{ + Mat& dst; + const uchar* my1, *muv; + int width; + + YUV420i2BGRA8888Invoker(Mat& _dst, int _width, const uchar* _y1, const uchar* _uv) + : dst(_dst), my1(_y1), muv(_uv), width(_width) {} + + void operator()(const BlockedRange& range) const + { + //B = 1.164(Y - 16) + 2.018(U - 128) + //G = 1.164(Y - 16) - 0.813(V - 128) - 0.391(U - 128) + //R = 1.164(Y - 16) + 1.596(V - 128) + + const uchar* y1 = my1 + range.begin() * width, *uv = muv + range.begin() * width / 2; + + for (int j = range.begin(); j < range.end(); j+=2, y1+=width*2, uv+=width) + { + uchar* row1 = dst.ptr(j); + uchar* row2 = dst.ptr(j+1); + const uchar* y2 = y1 + width; + + for(int i = 0; i < width; i+=2,row1+=8,row2+=8) + { + int cr = uv[i] - 128; + int cb = uv[i+1] - 128; + + int ruv = 409 * cr + 128; + int guv = 128 - 100 * cb - 208 * cr; + int buv = 516 * cb + 128; + + int y00 = (y1[i] - 16) * 298; + row1[0+R] = saturate_cast((y00 + buv) >> 8); + row1[1] = saturate_cast((y00 + guv) >> 8); + row1[2-R] = saturate_cast((y00 + ruv) >> 8); + row1[3] = (uchar)0xff; + + int y01 = (y1[i+1] - 16) * 298; + row1[4+R] = saturate_cast((y01 + buv) >> 8); + row1[5] = saturate_cast((y01 + guv) >> 8); + row1[6-R] = saturate_cast((y01 + ruv) >> 8); + row1[7] = (uchar)0xff; + + int y10 = (y2[i] - 16) * 298; + row2[0+R] = saturate_cast((y10 + buv) >> 8); + row2[1] = saturate_cast((y10 + guv) >> 8); + row2[2-R] = saturate_cast((y10 + ruv) >> 8); + row2[3] = (uchar)0xff; + + int y11 = (y2[i+1] - 16) * 298; + row2[4+R] = saturate_cast((y11 + buv) >> 8); + row2[5] = saturate_cast((y11 + guv) >> 8); + row2[6-R] = saturate_cast((y11 + ruv) >> 8); + row2[7] = (uchar)0xff; + } + } + } +}; + +}//namespace cv ////////////////////////////////////////////////////////////////////////////////////////// -// The main function // +// The main function // ////////////////////////////////////////////////////////////////////////////////////////// void cv::cvtColor( const InputArray& _src, OutputArray _dst, int code, int dcn ) @@ -2992,6 +3112,40 @@ void cv::cvtColor( const InputArray& _src, OutputArray _dst, int code, int dcn ) Bayer2RGB_VNG_8u(src, dst, code); } break; + case CV_YUV420i2BGR: case CV_YUV420i2RGB: + { + if(dcn <= 0) dcn = 3; + CV_Assert( dcn == 3 || dcn == 4 ); + CV_Assert( sz.width % 2 == 0 && sz.height % 3 == 0 && depth == CV_8U && src.isContinuous() ); + + Size dstSz(sz.width, sz.height * 2 / 3); + _dst.create( dstSz, CV_MAKETYPE(depth, dcn)); + dst = _dst.getMat(); + + const uchar* y = src.ptr(); + const uchar* uv = y + dstSz.area(); + +#ifdef HAVE_TEGRA_OPTIMIZATION + if (!tegra::YUV420i2BGR(y, uv, dst, CV_YUV420i2RGB == code)) +#endif + { + if (CV_YUV420i2RGB == code) + { + if (dcn == 3) + parallel_for(BlockedRange(0, dstSz.height, 2), YUV420i2BGR888Invoker<2>(dst, dstSz.width, y, uv)); + else + parallel_for(BlockedRange(0, dstSz.height, 2), YUV420i2BGRA8888Invoker<2>(dst, dstSz.width, y, uv)); + } + else + { + if (dcn == 3) + parallel_for(BlockedRange(0, dstSz.height, 2), YUV420i2BGR888Invoker<0>(dst, dstSz.width, y, uv)); + else + parallel_for(BlockedRange(0, dstSz.height, 2), YUV420i2BGRA8888Invoker<0>(dst, dstSz.width, y, uv)); + } + } + } + break; default: CV_Error( CV_StsBadFlag, "Unknown/unsupported color conversion code" ); } @@ -3009,5 +3163,3 @@ cvCvtColor( const CvArr* srcarr, CvArr* dstarr, int code ) /* End of file. */ - - diff --git a/modules/imgproc/src/thresh.cpp b/modules/imgproc/src/thresh.cpp index 05297cd40..201b62ede 100644 --- a/modules/imgproc/src/thresh.cpp +++ b/modules/imgproc/src/thresh.cpp @@ -60,7 +60,6 @@ thresh_8u( const Mat& _src, Mat& _dst, uchar thresh, uchar maxval, int type ) } #ifdef HAVE_TEGRA_OPTIMIZATION -#warning TEGRA OPTIMIZED THRESHOLD IS USED switch( type ) { case THRESH_BINARY: diff --git a/modules/video/src/lkpyramid.cpp b/modules/video/src/lkpyramid.cpp index 5ab9cd508..7303e9328 100644 --- a/modules/video/src/lkpyramid.cpp +++ b/modules/video/src/lkpyramid.cpp @@ -51,9 +51,8 @@ void cv::calcOpticalFlowPyrLK( const InputArray& _prevImg, const InputArray& _ne int flags ) { #ifdef HAVE_TEGRA_OPTIMIZATION -#warning "TEGRA OPTIMIZED calcOpticalFlowPyrLK IS USED" if (tegra::calcOpticalFlowPyrLK(_prevImg, _nextImg, _prevPts, _nextPts, _status, _err, winSize, maxLevel, criteria, derivLambda, flags)) - return; + return; #endif Mat prevImg = _prevImg.getMat(), nextImg = _nextImg.getMat(), prevPtsMat = _prevPts.getMat(); derivLambda = std::min(std::max(derivLambda, 0.), 1.);