dan-masek

Hacking BGR to YUV 422...

Apr 22nd, 2018
386
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 10.45 KB | None | 0 0
  1. #include <opencv2/opencv.hpp>
  2.  
  3. #include <cstdint>
  4. // ============================================================================
  5. namespace hal {
  6. // ============================================================================
  7. using namespace cv;
  8. // ----------------------------------------------------------------------------
  9. const int ITUR_BT_601_CY = 1220542;
  10. const int ITUR_BT_601_CUB = 2116026;
  11. const int ITUR_BT_601_CUG = -409993;
  12. const int ITUR_BT_601_CVG = -852492;
  13. const int ITUR_BT_601_CVR = 1673527;
  14. const int ITUR_BT_601_SHIFT = 20;
  15.  
  16. // Coefficients for RGB to YUV420p conversion
  17. const int ITUR_BT_601_CRY = 269484;
  18. const int ITUR_BT_601_CGY = 528482;
  19. const int ITUR_BT_601_CBY = 102760;
  20. const int ITUR_BT_601_CRU = -155188;
  21. const int ITUR_BT_601_CGU = -305135;
  22. const int ITUR_BT_601_CBU = 460324;
  23. const int ITUR_BT_601_CGV = -385875;
  24. const int ITUR_BT_601_CBV = -74448;
  25. // ----------------------------------------------------------------------------
  26. template<int bIdx, int uIdx, int yIdx, int cn>
  27. struct RGB888toYUV422Invoker : ParallelLoopBody
  28. {
  29.     uchar * dst_data;
  30.     size_t dst_step;
  31.     const uchar * src_data;
  32.     size_t src_step;
  33.     int width;
  34.  
  35.     RGB888toYUV422Invoker(uchar * _dst_data, size_t _dst_step,
  36.         const uchar * _src_data, size_t _src_step,
  37.         int _width)
  38.         : dst_data(_dst_data), dst_step(_dst_step), src_data(_src_data), src_step(_src_step), width(_width)
  39.     {
  40.     }
  41.  
  42.     void operator()(const Range& range) const
  43.     {
  44.         const int uidx = 1 - yIdx + uIdx * 2;
  45.         const int vidx = (2 + uidx) % 4;
  46.  
  47.         for (int j = range.start; j < range.end; j++) {
  48.             const uchar* row = src_data + src_step * j;
  49.             const uchar* brow = row + bIdx;
  50.             const uchar* grow = row + 1;
  51.             const uchar* rrow = row + (2 - bIdx);
  52.  
  53.             uchar* yuv_row = dst_data + dst_step * j;
  54.  
  55.             for (int i = 0, k = 0; i < (width * cn); i += (2 * cn), k += 4) {
  56.                 int b0(brow[i]), g0(grow[i]), r0(rrow[i]);
  57.                 int b1(brow[cn + i]), g1(grow[cn + i]), r1(rrow[cn + i]);
  58.  
  59.                 const int shifted16 = (16 << ITUR_BT_601_SHIFT);
  60.                 const int halfShift = (1 << (ITUR_BT_601_SHIFT - 1));
  61.                 int y0 = ITUR_BT_601_CRY * r0 + ITUR_BT_601_CGY * g0 + ITUR_BT_601_CBY * b0 + halfShift + shifted16;
  62.                 int y1 = ITUR_BT_601_CRY * r1 + ITUR_BT_601_CGY * g1 + ITUR_BT_601_CBY * b1 + halfShift + shifted16;
  63.                 yuv_row[k + yIdx] = saturate_cast<uchar>(y0 >> ITUR_BT_601_SHIFT);
  64.                 yuv_row[k + yIdx + 2] = saturate_cast<uchar>(y1 >> ITUR_BT_601_SHIFT);
  65.  
  66.  
  67.                 const int shifted128 = (128 << ITUR_BT_601_SHIFT);
  68.                 int u0 = ITUR_BT_601_CRU * r0 + ITUR_BT_601_CGU * g0 + ITUR_BT_601_CBU * b0 + halfShift + shifted128;
  69.                 int v0 = ITUR_BT_601_CBU * r0 + ITUR_BT_601_CGV * g0 + ITUR_BT_601_CBV * b0 + halfShift + shifted128;
  70.                 yuv_row[k + uidx] = saturate_cast<uchar>(u0 >> ITUR_BT_601_SHIFT);
  71.                 yuv_row[k + vidx] = saturate_cast<uchar>(v0 >> ITUR_BT_601_SHIFT);
  72.             }
  73.         }
  74.     }
  75. };
  76. // ----------------------------------------------------------------------------
  77. #define MIN_SIZE_FOR_PARALLEL_YUV422_CONVERSION (320*240)
  78. // ----------------------------------------------------------------------------
  79. template<int bIdx, int uIdx, int yIdx, int cn>
  80. inline void cvtRGBtoYUV422(uchar * dst_data, size_t dst_step, const uchar * src_data, size_t src_step,
  81.     int width, int height)
  82. {
  83.     RGB888toYUV422Invoker<bIdx, uIdx, yIdx, cn> converter(dst_data, dst_step, src_data, src_step, width);
  84.     if (width * height >= MIN_SIZE_FOR_PARALLEL_YUV422_CONVERSION)
  85.         parallel_for_(Range(0, height), converter);
  86.     else
  87.         converter(Range(0, height));
  88. }
  89. // ----------------------------------------------------------------------------
  90. void cvtBGRtoOnePlaneYUV(const uchar * src_data, size_t src_step,
  91.     uchar * dst_data, size_t dst_step,
  92.     int width, int height,
  93.     int scn, bool swapBlue, int uIdx, int ycn)
  94. {
  95.     // CV_INSTRUMENT_REGION();
  96.  
  97.     // TODO: add hal replacement method
  98.     int blueIdx = swapBlue ? 2 : 0;
  99.     switch (scn * 1000 + blueIdx * 100 + uIdx * 10 + ycn) {
  100.     case 3000: cvtRGBtoYUV422<0, 0, 0, 3>(dst_data, dst_step, src_data, src_step, width, height); break;
  101.     case 3001: cvtRGBtoYUV422<0, 0, 1, 3>(dst_data, dst_step, src_data, src_step, width, height); break;
  102.     case 3010: cvtRGBtoYUV422<0, 1, 0, 3>(dst_data, dst_step, src_data, src_step, width, height); break;
  103.     case 3200: cvtRGBtoYUV422<2, 0, 0, 3>(dst_data, dst_step, src_data, src_step, width, height); break;
  104.     case 3201: cvtRGBtoYUV422<2, 0, 1, 3>(dst_data, dst_step, src_data, src_step, width, height); break;
  105.     case 3210: cvtRGBtoYUV422<2, 1, 0, 3>(dst_data, dst_step, src_data, src_step, width, height); break;
  106.     case 4000: cvtRGBtoYUV422<0, 0, 0, 4>(dst_data, dst_step, src_data, src_step, width, height); break;
  107.     case 4001: cvtRGBtoYUV422<0, 0, 1, 4>(dst_data, dst_step, src_data, src_step, width, height); break;
  108.     case 4010: cvtRGBtoYUV422<0, 1, 0, 4>(dst_data, dst_step, src_data, src_step, width, height); break;
  109.     case 4200: cvtRGBtoYUV422<2, 0, 0, 4>(dst_data, dst_step, src_data, src_step, width, height); break;
  110.     case 4201: cvtRGBtoYUV422<2, 0, 1, 4>(dst_data, dst_step, src_data, src_step, width, height); break;
  111.     case 4210: cvtRGBtoYUV422<2, 1, 0, 4>(dst_data, dst_step, src_data, src_step, width, height); break;
  112.     default: CV_Error(CV_StsBadFlag, "Unknown/unsupported color conversion code"); break;
  113.     };
  114. }
  115. // ============================================================================
  116. } // namespace hal
  117. // ============================================================================
  118. enum
  119. {
  120.     //! YUV 4:2:2 family to RGB
  121.     COLOR_RGB2YUV_UYVY = 127,
  122.     COLOR_BGR2YUV_UYVY = 128,
  123.     //COLOR_RGB2YUV_VYUY = 129,
  124.     //COLOR_BGR2YUV_VYUY = 130,
  125.     COLOR_RGB2YUV_Y422 = COLOR_RGB2YUV_UYVY,
  126.     COLOR_BGR2YUV_Y422 = COLOR_BGR2YUV_UYVY,
  127.     COLOR_RGB2YUV_UYNV = COLOR_RGB2YUV_UYVY,
  128.     COLOR_BGR2YUV_UYNV = COLOR_BGR2YUV_UYVY,
  129.  
  130.     COLOR_RGBA2YUV_UYVY = 131,
  131.     COLOR_BGRA2YUV_UYVY = 132,
  132.     //COLOR_RGBA2YUV_VYUY = 133,
  133.     //COLOR_BGRA2YUV_VYUY = 134,
  134.     COLOR_RGBA2YUV_Y422 = COLOR_RGBA2YUV_UYVY,
  135.     COLOR_BGRA2YUV_Y422 = COLOR_BGRA2YUV_UYVY,
  136.     COLOR_RGBA2YUV_UYNV = COLOR_RGBA2YUV_UYVY,
  137.     COLOR_BGRA2YUV_UYNV = COLOR_BGRA2YUV_UYVY,
  138.  
  139.     COLOR_RGB2YUV_YUY2 = 135,
  140.     COLOR_BGR2YUV_YUY2 = 136,
  141.     COLOR_RGB2YUV_YVYU = 137,
  142.     COLOR_BGR2YUV_YVYU = 138,
  143.     COLOR_RGB2YUV_YUYV = COLOR_RGB2YUV_YUY2,
  144.     COLOR_BGR2YUV_YUYV = COLOR_BGR2YUV_YUY2,
  145.     COLOR_RGB2YUV_YUNV = COLOR_RGB2YUV_YUY2,
  146.     COLOR_BGR2YUV_YUNV = COLOR_BGR2YUV_YUY2,
  147.  
  148.     COLOR_RGBA2YUV_YUY2 = 139,
  149.     COLOR_BGRA2YUV_YUY2 = 140,
  150.     COLOR_RGBA2YUV_YVYU = 141,
  151.     COLOR_BGRA2YUV_YVYU = 142,
  152.     COLOR_RGBA2YUV_YUYV = COLOR_RGBA2YUV_YUY2,
  153.     COLOR_BGRA2YUV_YUYV = COLOR_BGRA2YUV_YUY2,
  154.     COLOR_RGBA2YUV_YUNV = COLOR_RGBA2YUV_YUY2,
  155.     COLOR_BGRA2YUV_YUNV = COLOR_BGRA2YUV_YUY2
  156.  
  157. };
  158. // ============================================================================
  159. namespace {
  160. // ============================================================================
  161. inline bool swapBlue(int code)
  162. {
  163.     switch (code) {
  164.     case COLOR_BGR2YUV_UYVY:
  165.     case COLOR_BGRA2YUV_UYVY:
  166.     case COLOR_BGR2YUV_YUY2:
  167.     case COLOR_BGR2YUV_YVYU:
  168.     case COLOR_BGRA2YUV_YUY2:
  169.     case COLOR_BGRA2YUV_YVYU:
  170.         return false;
  171.     default:
  172.         return true;
  173.     }
  174. }
  175. // ============================================================================
  176. } // anonymous namespace
  177. // ============================================================================
  178. void my_cvtColor(cv::InputArray _src, cv::OutputArray _dst, int code, int dcn = 0)
  179. {
  180.     int stype = _src.type();
  181.     int scn = CV_MAT_CN(stype), depth = CV_MAT_DEPTH(stype), uidx, ycn;
  182.  
  183.     cv::Mat src, dst;
  184.     if (_src.getObj() == _dst.getObj()) // inplace processing (#6653)
  185.         _src.copyTo(src);
  186.     else
  187.         src = _src.getMat();
  188.     cv::Size sz = src.size();
  189.     CV_Assert(depth == CV_8U || depth == CV_16U || depth == CV_32F);
  190.  
  191.     switch (code) {
  192.     case COLOR_RGB2YUV_UYVY: case COLOR_BGR2YUV_UYVY: case COLOR_RGBA2YUV_UYVY: case COLOR_BGRA2YUV_UYVY:
  193.     case COLOR_RGB2YUV_YUY2: case COLOR_BGR2YUV_YUY2: case COLOR_RGB2YUV_YVYU: case COLOR_BGR2YUV_YVYU:
  194.     case COLOR_RGBA2YUV_YUY2: case COLOR_BGRA2YUV_YUY2: case COLOR_RGBA2YUV_YVYU: case COLOR_BGRA2YUV_YVYU:
  195.         //http://www.fourcc.org/yuv.php#UYVY
  196.         //http://www.fourcc.org/yuv.php#YUY2
  197.         //http://www.fourcc.org/yuv.php#YVYU
  198.         if (dcn <= 0) dcn = 2;
  199.         ycn = (code == COLOR_RGB2YUV_UYVY || code == COLOR_BGR2YUV_UYVY || code == COLOR_RGBA2YUV_UYVY || code == COLOR_BGRA2YUV_UYVY) ? 1 : 0;
  200.         uidx = (code == COLOR_RGB2YUV_YVYU || code == COLOR_BGR2YUV_YVYU || code == COLOR_RGBA2YUV_YVYU || code == COLOR_BGRA2YUV_YVYU) ? 1 : 0;
  201.         CV_Assert(dcn == 2 && depth == CV_8U);
  202.         CV_Assert(scn == 3 || scn == 4);
  203.         CV_Assert(sz.width % 2 == 0);
  204.         _dst.create(sz, CV_8UC(dcn));
  205.         dst = _dst.getMat();
  206.         hal::cvtBGRtoOnePlaneYUV(src.data, src.step, dst.data, dst.step, src.cols, src.rows,
  207.             scn, swapBlue(code), uidx, ycn);
  208.         break;
  209.     default:
  210.         cv::cvtColor(_src, _dst, code, dcn);
  211.     };
  212. }
  213. // ============================================================================
  214. cv::Mat3b make_test_image()
  215. {
  216.     cv::Mat3b image(65536, 256);
  217.     cv::Mat3b::iterator it(image.begin());
  218.     for (uint32_t b(0); b < 256; ++b) {
  219.         for (uint32_t g(0); g < 256; ++g) {
  220.             for (uint32_t r(0); r < 256; ++r) {
  221.                 *(it++) = cv::Vec3b(b, g, r);
  222.             }
  223.         }
  224.     }
  225.     return image;
  226. }
  227. // ----------------------------------------------------------------------------
  228. int main()
  229. {
  230.     cv::Mat3b image(make_test_image());
  231.  
  232.  
  233.     cv::Mat2b image_yuv;
  234.     my_cvtColor(image, image_yuv, COLOR_BGR2YUV_Y422);
  235.  
  236.     cv::Mat3b image_bgr;
  237.     cv::cvtColor(image_yuv, image_bgr, cv::COLOR_YUV2BGR_Y422);
  238.  
  239.     cv::Mat delta_y422;
  240.     cv::absdiff(image, image_bgr, delta_y422);
  241.  
  242.     double minval, maxval;
  243.     cv::minMaxLoc(delta_y422, &minval, &maxval);
  244.     cv::Mat mean, std;
  245.     cv::meanStdDev(delta_y422, mean, std);
  246.     std::cout << minval << "\n" << maxval << "\n" << mean << "\n" << std << "\n";
  247.  
  248.     return 0;
  249. }
  250. // ============================================================================
Add Comment
Please, Sign In to add comment