libyuv库的使用

libyuv是Google开源的实现各种YUV与RGB之间相互转换、旋转、缩放的库。它是跨平台的,可在Windows、Linux、Mac、Android等操作系统,x86、x64、arm架构上进行编译运行,支持SSE、AVX、NEON等SIMD指令加速。

下面说一下libyuv在Windows7VS2013 x64上的编译步骤及使用:

1.        从https://code.google.com/p/libyuv/source/checkout或者https://github.com/lemenkov/libyuv下载libyuv源码;我是通过svn直接从google下载的,版本号是1433,更新日期2015年6月13日;

2.        通过cmake gui生成vs2013 x64工程,不需要额外的配置;

3.        打开Project.sln工程,重新编译,即可生成yuv.lib静态库;

4.    新添加一个test_libyuv控制台工程,用于测试yuv.lib的正确性,测试代码如下:

  1. #include <iostream>  
  2. #include <assert.h>  
  3. #include "libyuv.h"  
  4. #include <cmath>  
  5. #include <opencv2/opencv.hpp>  
  6.   
  7. void test_BGRAToI420(const cv::Mat& matSrc, int width, int height, int size_frame, cv::Mat& matDst);  
  8. void test_BGRAToNV21(const cv::Mat& matSrc, int width, int height, int size_frame, cv::Mat& matDst);  
  9. void test_BGRAToNV12(const cv::Mat& matSrc, int width, int height, int size_frame, cv::Mat& matDst);  
  10.   
  11. int main(int argc, char* argv[])  
  12. {  
  13.     cv::Mat matSrc = cv::imread("cat.jpg");  
  14.     if (!matSrc.data) {  
  15.         std::cout << "read src image error" << std::endl;  
  16.         return -1;  
  17.     }  
  18.   
  19.     //cv::resize(matSrc, matSrc, cv::Size(500, 111));  
  20.   
  21.     int width = matSrc.cols;  
  22.     int height = matSrc.rows;  
  23.     int size_frame = width * height;  
  24.   
  25.     cv::Mat matI420, matNV21, matNV12;  
  26.   
  27.     test_BGRAToI420(matSrc, width, height, size_frame, matI420);  
  28.     test_BGRAToNV21(matSrc, width, height, size_frame, matNV21);  
  29.     test_BGRAToNV12(matSrc, width, height, size_frame, matNV12);  
  30.   
  31.     assert((matI420.depth() == matNV21.depth()) && (matI420.depth() == matNV12.depth()));  
  32.     assert((matI420.channels() == matNV21.channels()) && (matI420.channels() == matNV12.channels()));  
  33.   
  34.     for (int i = 0; i < height; i++) {  
  35.         const unsigned char* pI420 = matI420.ptr(i);  
  36.         const unsigned char* pNV21 = matNV21.ptr(i);  
  37.         const unsigned char* pNV12 = matNV12.ptr(i);  
  38.   
  39.         for (int j = 0, m = 0; j < width; j++, m+=4) {  
  40.             if ((pI420[m] != pNV21[m]) || (pI420[m] != pNV12[m]) ||  
  41.                 (pI420[m + 1] != pNV21[m + 1]) || (pI420[m + 1] != pNV12[m + 1]) ||  
  42.                 (pI420[m + 2] != pNV21[m + 2]) || (pI420[m + 2] != pNV12[m + 2]) ||  
  43.                 (pI420[m + 3] != pNV21[m + 3]) || (pI420[m + 3] != pNV12[m + 3])) {  
  44.                 std::cout << "convert error" << std::endl;  
  45.             }  
  46.         }  
  47.     }  
  48.   
  49.     std::cout << "ok" << std::endl;  
  50.     return 0;  
  51. }  
  52.   
  53. void test_BGRAToI420(const cv::Mat& matSrc, int width, int height, int size_frame, cv::Mat& matDst)  
  54. {  
  55.     // BGRA <--> I420(YUV420P)  
  56.     cv::Mat matBGRA, matI420, matARGB;  
  57.     cv::cvtColor(matSrc, matBGRA, cv::COLOR_BGR2BGRA);  
  58.     matARGB = cv::Mat(height, width, CV_8UC4, cv::Scalar::all(0));  
  59.     libyuv::BGRAToARGB(matBGRA.data, width * 4, matARGB.data, width * 4, width, height);  
  60.   
  61.     uchar* pI420 = new uchar[width * height + (width + 1) / 2 * (height + 1) / 2 * 2];  
  62.     memset(pI420, 0, sizeof(uchar) * (width * height + (width + 1) / 2 * (height + 1) / 2 * 2));  
  63.     uchar* dst_y = pI420;  
  64.     int dst_y_stride = width;  
  65.     uchar* dst_u = pI420 + size_frame;  
  66.     int dst_u_stride = (width + 1) / 2;  
  67.     uchar* dst_v = pI420 + size_frame + dst_u_stride * (height + 1) / 2;  
  68.     int dst_v_stride = (width + 1) / 2;  
  69.   
  70.     libyuv::BGRAToI420(matARGB.data, width * 4, dst_y, dst_y_stride, dst_u, dst_u_stride, dst_v, dst_v_stride, width, height);  
  71.     matI420 = cv::Mat(height, width, CV_8UC4, cv::Scalar::all(0));  
  72.     libyuv::I420ToBGRA(dst_y, dst_y_stride, dst_u, dst_u_stride, dst_v, dst_v_stride, matI420.data, width * 4, width, height);  
  73.     cv::Mat matBGRA_ = cv::Mat(height, width, CV_8UC4, cv::Scalar::all(0));  
  74.     libyuv::ARGBToBGRA(matI420.data, width * 4, matBGRA_.data, width * 4, width, height);  
  75.     cv::imwrite("I420_bgra.jpg", matBGRA_);  
  76.     matBGRA_.copyTo(matDst);  
  77.   
  78.     int count_diff = 0;  
  79.     int max_diff = 0;  
  80.     int threshold = 20;//  
  81.     for (int i = 0; i < height; i++) {  
  82.         uchar* pSrc = matBGRA.ptr(i);  
  83.         uchar* pDst = matBGRA_.ptr(i);  
  84.         for (int j = 0, m = 0; j < width; j++, m += 4) {  
  85.             int tmp = std::max(abs(pSrc[m] - pDst[m]), abs(pSrc[m + 1] - pDst[m + 1]));  
  86.             tmp = std::max(tmp, abs(pSrc[m + 2] - pDst[m + 2]));  
  87.             if (tmp > max_diff)  
  88.                 max_diff = tmp;  
  89.   
  90.             if (abs(pSrc[m] - pDst[m]) > threshold ||  
  91.                 abs(pSrc[m + 1] - pDst[m + 1]) > threshold ||  
  92.                 abs(pSrc[m + 2] - pDst[m + 2]) > threshold) {  
  93.                 count_diff++;  
  94.                 //std::cout << i << "    " << j << std::endl;  
  95.             }  
  96.   
  97.         }  
  98.     }  
  99.   
  100.     std::cout << "convert I420 to BGRA diff max: " << max_diff << std::endl;  
  101.     if (count_diff > width + height) {//  
  102.         std::cout << "convert I420 to BGRA error." << std::endl;  
  103.         std::cout << "diff num: " << count_diff << std::endl;  
  104.     }  
  105.   
  106.     delete[] pI420;  
  107. }  
  108.   
  109. void test_BGRAToNV12(const cv::Mat& matSrc, int width, int height, int size_frame, cv::Mat& matDst)  
  110. {  
  111.     // BGRA <--> NV12  
  112.     cv::Mat matBGRA, matNV12;  
  113.     cv::cvtColor(matSrc, matBGRA, cv::COLOR_BGR2BGRA);  
  114.   
  115.     uchar* pNV12 = new uchar[width * height + ((width + 1) / 2) * ((height + 1) / 2) * 2];  
  116.     memset(pNV12, 0, sizeof(uchar) * (width * height + ((width + 1) / 2) * ((height + 1) / 2) * 2));  
  117.     uchar* dst_y = pNV12;  
  118.     int dst_y_stride = width;  
  119.     uchar* dst_vu = pNV12 + size_frame;  
  120.     int dst_vu_stride = (width + 1) / 2 * 2;  
  121.   
  122.     libyuv::ARGBToNV12(matBGRA.data, width * 4, dst_y, dst_y_stride, dst_vu, dst_vu_stride, width, height);  
  123.     matNV12 = cv::Mat(height, width, CV_8UC4, cv::Scalar::all(0));  
  124.     libyuv::NV12ToARGB(dst_y, dst_y_stride, dst_vu, dst_vu_stride, matNV12.data, width * 4, width, height);  
  125.     cv::imwrite("NV12_bgra.jpg", matNV12);  
  126.     matNV12.copyTo(matDst);  
  127.   
  128.     int count_diff = 0;  
  129.     int max_diff = 0;  
  130.     int threshold = 20;//  
  131.     for (int i = 0; i < height; i++) {  
  132.         uchar* pSrc = matBGRA.ptr(i);  
  133.         uchar* pDst = matNV12.ptr(i);  
  134.         for (int j = 0, m = 0; j < width; j++, m += 4) {  
  135.             int tmp = std::max(abs(pSrc[m] - pDst[m]), abs(pSrc[m + 1] - pDst[m + 1]));  
  136.             tmp = std::max(tmp, abs(pSrc[m + 2] - pDst[m + 2]));  
  137.             if (tmp > max_diff)  
  138.                 max_diff = tmp;  
  139.   
  140.             if (abs(pSrc[m] - pDst[m]) > threshold ||  
  141.                 abs(pSrc[m + 1] - pDst[m + 1]) > threshold ||  
  142.                 abs(pSrc[m + 2] - pDst[m + 2]) > threshold) {  
  143.                 count_diff++;  
  144.                 //std::cout << i << "    " << j << std::endl;  
  145.             }  
  146.         }  
  147.     }  
  148.   
  149.     std::cout << "convert NV12 to BGRA diff max: " << max_diff << std::endl;  
  150.     if (count_diff > width + height) {//  
  151.         std::cout << "convert NV12 to BGRA error." << std::endl;  
  152.         std::cout << "diff num: " << count_diff << std::endl;  
  153.     }  
  154.   
  155.     delete[] pNV12;  
  156. }  
  157.   
  158. void test_BGRAToNV21(const cv::Mat& matSrc, int width, int height, int size_frame, cv::Mat& matDst)  
  159. {  
  160.     // BGRA <--> NV21  
  161.     cv::Mat matBGRA, matNV21;  
  162.     cv::cvtColor(matSrc, matBGRA, cv::COLOR_BGR2BGRA);  
  163.   
  164.     uchar* pNV21 = new uchar[width * height + ((width + 1) / 2) * ((height + 1) / 2) * 2];  
  165.     memset(pNV21, 0, sizeof(uchar) * (width * height + ((width + 1) / 2) * ((height + 1) / 2) * 2));  
  166.     uchar* dst_y = pNV21;  
  167.     int dst_y_stride = width;  
  168.     uchar* dst_vu = pNV21 + size_frame;  
  169.     int dst_vu_stride = (width + 1) / 2 * 2;  
  170.   
  171.     libyuv::ARGBToNV21(matBGRA.data, width * 4, dst_y, dst_y_stride, dst_vu, dst_vu_stride, width, height);  
  172.     matNV21 = cv::Mat(height, width, CV_8UC4, cv::Scalar::all(0));  
  173.     libyuv::NV21ToARGB(dst_y, dst_y_stride, dst_vu, dst_vu_stride, matNV21.data, width * 4, width, height);  
  174.     cv::imwrite("NV21_bgra.jpg", matNV21);  
  175.     matNV21.copyTo(matDst);  
  176.   
  177.     int count_diff = 0;  
  178.     int max_diff = 0;  
  179.     int threshold = 20;//  
  180.     for (int i = 0; i < height; i++) {  
  181.         uchar* pSrc = matBGRA.ptr(i);  
  182.         uchar* pDst = matNV21.ptr(i);  
  183.         for (int j = 0, m = 0; j < width; j++, m += 4) {  
  184.             int tmp = std::max(abs(pSrc[m] - pDst[m]), abs(pSrc[m + 1] - pDst[m + 1]));  
  185.             tmp = std::max(tmp, abs(pSrc[m + 2] - pDst[m + 2]));  
  186.             if (tmp > max_diff)  
  187.                 max_diff = tmp;  
  188.   
  189.             if (abs(pSrc[m] - pDst[m]) > threshold ||  
  190.                 abs(pSrc[m + 1] - pDst[m + 1]) > threshold ||  
  191.                 abs(pSrc[m + 2] - pDst[m + 2]) > threshold) {  
  192.                 count_diff++;  
  193.                 //std::cout << i << "    " << j << std::endl;  
  194.             }  
  195.         }  
  196.     }  
  197.   
  198.     std::cout << "convert NV21 to BGRA diff max: " << max_diff << std::endl;  
  199.     if (count_diff > width + height) {//  
  200.         std::cout << "convert NV21 to BGRA error." << std::endl;  
  201.         std::cout << "diff num: " << count_diff << std::endl;  
  202.     }  
  203.   
  204.     delete[] pNV21;  
  205. }  

GitHubhttps://github.com/fengbingchun/Libyuv_Test

猜你喜欢

转载自blog.csdn.net/edmond999/article/details/79623243