Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <opencv2/opencv.hpp>
- #include <cstdint>
- // ============================================================================
- namespace hal {
- // ============================================================================
- using namespace cv;
- // ----------------------------------------------------------------------------
- const int ITUR_BT_601_CY = 1220542;
- const int ITUR_BT_601_CUB = 2116026;
- const int ITUR_BT_601_CUG = -409993;
- const int ITUR_BT_601_CVG = -852492;
- const int ITUR_BT_601_CVR = 1673527;
- const int ITUR_BT_601_SHIFT = 20;
- // Coefficients for RGB to YUV420p conversion
- const int ITUR_BT_601_CRY = 269484;
- const int ITUR_BT_601_CGY = 528482;
- const int ITUR_BT_601_CBY = 102760;
- const int ITUR_BT_601_CRU = -155188;
- const int ITUR_BT_601_CGU = -305135;
- const int ITUR_BT_601_CBU = 460324;
- const int ITUR_BT_601_CGV = -385875;
- const int ITUR_BT_601_CBV = -74448;
- // ----------------------------------------------------------------------------
- template<int bIdx, int uIdx, int yIdx, int cn>
- struct RGB888toYUV422Invoker : ParallelLoopBody
- {
- uchar * dst_data;
- size_t dst_step;
- const uchar * src_data;
- size_t src_step;
- int width;
- RGB888toYUV422Invoker(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
- {
- const int uidx = 1 - yIdx + uIdx * 2;
- const int vidx = (2 + uidx) % 4;
- for (int j = range.start; j < range.end; j++) {
- const uchar* row = src_data + src_step * j;
- const uchar* brow = row + bIdx;
- const uchar* grow = row + 1;
- const uchar* rrow = row + (2 - bIdx);
- uchar* yuv_row = dst_data + dst_step * j;
- for (int i = 0, k = 0; i < (width * cn); i += (2 * cn), k += 4) {
- int b0(brow[i]), g0(grow[i]), r0(rrow[i]);
- int b1(brow[cn + i]), g1(grow[cn + i]), r1(rrow[cn + i]);
- const int shifted16 = (16 << ITUR_BT_601_SHIFT);
- const int halfShift = (1 << (ITUR_BT_601_SHIFT - 1));
- int y0 = ITUR_BT_601_CRY * r0 + ITUR_BT_601_CGY * g0 + ITUR_BT_601_CBY * b0 + halfShift + shifted16;
- int y1 = ITUR_BT_601_CRY * r1 + ITUR_BT_601_CGY * g1 + ITUR_BT_601_CBY * b1 + halfShift + shifted16;
- yuv_row[k + yIdx] = saturate_cast<uchar>(y0 >> ITUR_BT_601_SHIFT);
- yuv_row[k + yIdx + 2] = saturate_cast<uchar>(y1 >> ITUR_BT_601_SHIFT);
- const int shifted128 = (128 << ITUR_BT_601_SHIFT);
- int u0 = ITUR_BT_601_CRU * r0 + ITUR_BT_601_CGU * g0 + ITUR_BT_601_CBU * b0 + halfShift + shifted128;
- int v0 = ITUR_BT_601_CBU * r0 + ITUR_BT_601_CGV * g0 + ITUR_BT_601_CBV * b0 + halfShift + shifted128;
- yuv_row[k + uidx] = saturate_cast<uchar>(u0 >> ITUR_BT_601_SHIFT);
- yuv_row[k + vidx] = saturate_cast<uchar>(v0 >> ITUR_BT_601_SHIFT);
- }
- }
- }
- };
- // ----------------------------------------------------------------------------
- #define MIN_SIZE_FOR_PARALLEL_YUV422_CONVERSION (320*240)
- // ----------------------------------------------------------------------------
- template<int bIdx, int uIdx, int yIdx, int cn>
- inline void cvtRGBtoYUV422(uchar * dst_data, size_t dst_step, const uchar * src_data, size_t src_step,
- int width, int height)
- {
- RGB888toYUV422Invoker<bIdx, uIdx, yIdx, cn> 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));
- }
- // ----------------------------------------------------------------------------
- void cvtBGRtoOnePlaneYUV(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();
- // TODO: add hal replacement method
- int blueIdx = swapBlue ? 2 : 0;
- switch (scn * 1000 + blueIdx * 100 + uIdx * 10 + ycn) {
- case 3000: cvtRGBtoYUV422<0, 0, 0, 3>(dst_data, dst_step, src_data, src_step, width, height); break;
- case 3001: cvtRGBtoYUV422<0, 0, 1, 3>(dst_data, dst_step, src_data, src_step, width, height); break;
- case 3010: cvtRGBtoYUV422<0, 1, 0, 3>(dst_data, dst_step, src_data, src_step, width, height); break;
- case 3200: cvtRGBtoYUV422<2, 0, 0, 3>(dst_data, dst_step, src_data, src_step, width, height); break;
- case 3201: cvtRGBtoYUV422<2, 0, 1, 3>(dst_data, dst_step, src_data, src_step, width, height); break;
- case 3210: cvtRGBtoYUV422<2, 1, 0, 3>(dst_data, dst_step, src_data, src_step, width, height); break;
- case 4000: cvtRGBtoYUV422<0, 0, 0, 4>(dst_data, dst_step, src_data, src_step, width, height); break;
- case 4001: cvtRGBtoYUV422<0, 0, 1, 4>(dst_data, dst_step, src_data, src_step, width, height); break;
- case 4010: cvtRGBtoYUV422<0, 1, 0, 4>(dst_data, dst_step, src_data, src_step, width, height); break;
- case 4200: cvtRGBtoYUV422<2, 0, 0, 4>(dst_data, dst_step, src_data, src_step, width, height); break;
- case 4201: cvtRGBtoYUV422<2, 0, 1, 4>(dst_data, dst_step, src_data, src_step, width, height); break;
- case 4210: cvtRGBtoYUV422<2, 1, 0, 4>(dst_data, dst_step, src_data, src_step, width, height); break;
- default: CV_Error(CV_StsBadFlag, "Unknown/unsupported color conversion code"); break;
- };
- }
- // ============================================================================
- } // namespace hal
- // ============================================================================
- enum
- {
- //! YUV 4:2:2 family to RGB
- COLOR_RGB2YUV_UYVY = 127,
- COLOR_BGR2YUV_UYVY = 128,
- //COLOR_RGB2YUV_VYUY = 129,
- //COLOR_BGR2YUV_VYUY = 130,
- 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 = 131,
- COLOR_BGRA2YUV_UYVY = 132,
- //COLOR_RGBA2YUV_VYUY = 133,
- //COLOR_BGRA2YUV_VYUY = 134,
- 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 = 135,
- COLOR_BGR2YUV_YUY2 = 136,
- COLOR_RGB2YUV_YVYU = 137,
- COLOR_BGR2YUV_YVYU = 138,
- 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 = 139,
- COLOR_BGRA2YUV_YUY2 = 140,
- COLOR_RGBA2YUV_YVYU = 141,
- COLOR_BGRA2YUV_YVYU = 142,
- COLOR_RGBA2YUV_YUYV = COLOR_RGBA2YUV_YUY2,
- COLOR_BGRA2YUV_YUYV = COLOR_BGRA2YUV_YUY2,
- COLOR_RGBA2YUV_YUNV = COLOR_RGBA2YUV_YUY2,
- COLOR_BGRA2YUV_YUNV = COLOR_BGRA2YUV_YUY2
- };
- // ============================================================================
- namespace {
- // ============================================================================
- inline bool swapBlue(int code)
- {
- switch (code) {
- case COLOR_BGR2YUV_UYVY:
- case COLOR_BGRA2YUV_UYVY:
- case COLOR_BGR2YUV_YUY2:
- case COLOR_BGR2YUV_YVYU:
- case COLOR_BGRA2YUV_YUY2:
- case COLOR_BGRA2YUV_YVYU:
- return false;
- default:
- return true;
- }
- }
- // ============================================================================
- } // anonymous namespace
- // ============================================================================
- void my_cvtColor(cv::InputArray _src, cv::OutputArray _dst, int code, int dcn = 0)
- {
- int stype = _src.type();
- int scn = CV_MAT_CN(stype), depth = CV_MAT_DEPTH(stype), uidx, ycn;
- cv::Mat src, dst;
- if (_src.getObj() == _dst.getObj()) // inplace processing (#6653)
- _src.copyTo(src);
- else
- src = _src.getMat();
- cv::Size sz = src.size();
- CV_Assert(depth == CV_8U || depth == CV_16U || depth == CV_32F);
- 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_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
- if (dcn <= 0) dcn = 2;
- ycn = (code == COLOR_RGB2YUV_UYVY || code == COLOR_BGR2YUV_UYVY || code == COLOR_RGBA2YUV_UYVY || code == COLOR_BGRA2YUV_UYVY) ? 1 : 0;
- uidx = (code == COLOR_RGB2YUV_YVYU || code == COLOR_BGR2YUV_YVYU || code == COLOR_RGBA2YUV_YVYU || code == COLOR_BGRA2YUV_YVYU) ? 1 : 0;
- CV_Assert(dcn == 2 && depth == CV_8U);
- CV_Assert(scn == 3 || scn == 4);
- CV_Assert(sz.width % 2 == 0);
- _dst.create(sz, CV_8UC(dcn));
- dst = _dst.getMat();
- hal::cvtBGRtoOnePlaneYUV(src.data, src.step, dst.data, dst.step, src.cols, src.rows,
- scn, swapBlue(code), uidx, ycn);
- break;
- default:
- cv::cvtColor(_src, _dst, code, dcn);
- };
- }
- // ============================================================================
- cv::Mat3b make_test_image()
- {
- cv::Mat3b image(65536, 256);
- cv::Mat3b::iterator it(image.begin());
- for (uint32_t b(0); b < 256; ++b) {
- for (uint32_t g(0); g < 256; ++g) {
- for (uint32_t r(0); r < 256; ++r) {
- *(it++) = cv::Vec3b(b, g, r);
- }
- }
- }
- return image;
- }
- // ----------------------------------------------------------------------------
- int main()
- {
- cv::Mat3b image(make_test_image());
- cv::Mat2b image_yuv;
- my_cvtColor(image, image_yuv, COLOR_BGR2YUV_Y422);
- cv::Mat3b image_bgr;
- cv::cvtColor(image_yuv, image_bgr, cv::COLOR_YUV2BGR_Y422);
- cv::Mat delta_y422;
- cv::absdiff(image, image_bgr, delta_y422);
- double minval, maxval;
- cv::minMaxLoc(delta_y422, &minval, &maxval);
- cv::Mat mean, std;
- cv::meanStdDev(delta_y422, mean, std);
- std::cout << minval << "\n" << maxval << "\n" << mean << "\n" << std << "\n";
- return 0;
- }
- // ============================================================================
Add Comment
Please, Sign In to add comment