android 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的正确性,测试代码如下:

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  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

0
### 回答1: libyuv.so是一个用于图像处理的开源,特别适用于Android平台。它提供了许多用于颜色空间转换、缩放、旋转和镜像等常见图像操作的函数。 首先,libyuv.so可以用来进行颜色空间转换。它支持诸如I420、NV12、NV21、UYVY等常见的颜色格式之间的相互转换。这在很多图像处理应用中非常有用,比如将相机采集到的图像数据转换为OpenGL ES所需的纹理格式。 其次,libyuv.so还提供了缩放和旋转图像的功能。通过使用这些函数,我们可以根据需要调整图像的大小和方向。这对于在Android应用中处理实时视频流或图像预览非常有用,比如实现缩放和旋转摄像头的功能。 此外,libyuv.so还提供了镜像图像的功能。通过使用这个,我们可以轻松地在水平和垂直方向上对图像进行镜像翻转。这在一些镜像或翻转效果的应用中非常有用,比如实现照片编辑软件中的镜像滤镜效果。 总之,libyuv.so是一个强大的图像处理,它提供了许多常用的图像操作的函数,可以方便地在Android平台上进行图像处理。无论是颜色空间转换、缩放、旋转还是镜像,libyuv.so都能帮助我们实现这些功能,而且使用起来非常便捷。 ### 回答2: libyuv.so是一个用于处理图像和视频的开源,特别适用于Android平台。它提供了一系列的函数和工具,用于进行图像和视频的格式转换、旋转、缩放和裁剪等操作。 libyuv.so的功能非常强大,可以处理各种不同编码格式的图像和视频。它支持YUV、RGB和ARGB等不同的颜色格式,并且可以进行各种不同格式之间的转换。这使得它在处理图像和视频时非常灵活,可以适应不同的需求和场景。 除了格式转换,libyuv.so还提供了一些其他功能,如图像和视频的旋转、缩放和裁剪等操作。这些功能可以帮助开发者在处理图像和视频时更加方便和高效。例如,开发者可以使用libyuv.so将图像旋转90度或者180度,实现图像的镜像效果,或者进行图像的缩放和裁剪等操作。 另外,libyuv.so还提供了一些用于图像和视频处理的工具函数,如计算PSNR(峰值信噪比)、计算图像差异、计算图像相似度等。这些工具函数可以帮助开发者评估图像和视频质量,进行相关的算法研究和优化。 总的来说,libyuv.so是一个功能强大的开源,适用于Android平台的图像和视频处理。它提供了多种功能和工具,方便开发者进行图像和视频处理相关的操作,同时也帮助提高了开发效率和质量。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值