• 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 x64project,不须要额外的配置;

    3.        打开Project.slnproject,又一次编译,就可以生成yuv.lib静态库。

    4.    新加入一个test_libyuv控制台project。用于測试yuv.lib的正确性。測试代码例如以下:

    #include <iostream>
    #include <assert.h>
    #include "libyuv.h"
    #include <cmath>
    #include <opencv2/opencv.hpp>
    
    void test_BGRAToI420(const cv::Mat& matSrc, int width, int height, int size_frame, cv::Mat& matDst);
    void test_BGRAToNV21(const cv::Mat& matSrc, int width, int height, int size_frame, cv::Mat& matDst);
    void test_BGRAToNV12(const cv::Mat& matSrc, int width, int height, int size_frame, cv::Mat& matDst);
    
    int main(int argc, char* argv[])
    {
    	cv::Mat matSrc = cv::imread("cat.jpg");
    	if (!matSrc.data) {
    		std::cout << "read src image error" << std::endl;
    		return -1;
    	}
    
    	//cv::resize(matSrc, matSrc, cv::Size(500, 111));
    
    	int width = matSrc.cols;
    	int height = matSrc.rows;
    	int size_frame = width * height;
    
    	cv::Mat matI420, matNV21, matNV12;
    
    	test_BGRAToI420(matSrc, width, height, size_frame, matI420);
    	test_BGRAToNV21(matSrc, width, height, size_frame, matNV21);
    	test_BGRAToNV12(matSrc, width, height, size_frame, matNV12);
    
    	assert((matI420.depth() == matNV21.depth()) && (matI420.depth() == matNV12.depth()));
    	assert((matI420.channels() == matNV21.channels()) && (matI420.channels() == matNV12.channels()));
    
    	for (int i = 0; i < height; i++) {
    		const unsigned char* pI420 = matI420.ptr(i);
    		const unsigned char* pNV21 = matNV21.ptr(i);
    		const unsigned char* pNV12 = matNV12.ptr(i);
    
    		for (int j = 0, m = 0; j < width; j++, m+=4) {
    			if ((pI420[m] != pNV21[m]) || (pI420[m] != pNV12[m]) ||
    				(pI420[m + 1] != pNV21[m + 1]) || (pI420[m + 1] != pNV12[m + 1]) ||
    				(pI420[m + 2] != pNV21[m + 2]) || (pI420[m + 2] != pNV12[m + 2]) ||
    				(pI420[m + 3] != pNV21[m + 3]) || (pI420[m + 3] != pNV12[m + 3])) {
    				std::cout << "convert error" << std::endl;
    			}
    		}
    	}
    
    	std::cout << "ok" << std::endl;
    	return 0;
    }
    
    void test_BGRAToI420(const cv::Mat& matSrc, int width, int height, int size_frame, cv::Mat& matDst)
    {
    	// BGRA <--> I420(YUV420P)
    	cv::Mat matBGRA, matI420, matARGB;
    	cv::cvtColor(matSrc, matBGRA, cv::COLOR_BGR2BGRA);
    	matARGB = cv::Mat(height, width, CV_8UC4, cv::Scalar::all(0));
    	libyuv::BGRAToARGB(matBGRA.data, width * 4, matARGB.data, width * 4, width, height);
    
    	uchar* pI420 = new uchar[width * height + (width + 1) / 2 * (height + 1) / 2 * 2];
    	memset(pI420, 0, sizeof(uchar) * (width * height + (width + 1) / 2 * (height + 1) / 2 * 2));
    	uchar* dst_y = pI420;
    	int dst_y_stride = width;
    	uchar* dst_u = pI420 + size_frame;
    	int dst_u_stride = (width + 1) / 2;
    	uchar* dst_v = pI420 + size_frame + dst_u_stride * (height + 1) / 2;
    	int dst_v_stride = (width + 1) / 2;
    
    	libyuv::BGRAToI420(matARGB.data, width * 4, dst_y, dst_y_stride, dst_u, dst_u_stride, dst_v, dst_v_stride, width, height);
    	matI420 = cv::Mat(height, width, CV_8UC4, cv::Scalar::all(0));
    	libyuv::I420ToBGRA(dst_y, dst_y_stride, dst_u, dst_u_stride, dst_v, dst_v_stride, matI420.data, width * 4, width, height);
    	cv::Mat matBGRA_ = cv::Mat(height, width, CV_8UC4, cv::Scalar::all(0));
    	libyuv::ARGBToBGRA(matI420.data, width * 4, matBGRA_.data, width * 4, width, height);
    	cv::imwrite("I420_bgra.jpg", matBGRA_);
    	matBGRA_.copyTo(matDst);
    
    	int count_diff = 0;
    	int max_diff = 0;
    	int threshold = 20;//
    	for (int i = 0; i < height; i++) {
    		uchar* pSrc = matBGRA.ptr(i);
    		uchar* pDst = matBGRA_.ptr(i);
    		for (int j = 0, m = 0; j < width; j++, m += 4) {
    			int tmp = std::max(abs(pSrc[m] - pDst[m]), abs(pSrc[m + 1] - pDst[m + 1]));
    			tmp = std::max(tmp, abs(pSrc[m + 2] - pDst[m + 2]));
    			if (tmp > max_diff)
    				max_diff = tmp;
    
    			if (abs(pSrc[m] - pDst[m]) > threshold ||
    				abs(pSrc[m + 1] - pDst[m + 1]) > threshold ||
    				abs(pSrc[m + 2] - pDst[m + 2]) > threshold) {
    				count_diff++;
    				//std::cout << i << "    " << j << std::endl;
    			}
    
    		}
    	}
    
    	std::cout << "convert I420 to BGRA diff max: " << max_diff << std::endl;
    	if (count_diff > width + height) {//
    		std::cout << "convert I420 to BGRA error." << std::endl;
    		std::cout << "diff num: " << count_diff << std::endl;
    	}
    
    	delete[] pI420;
    }
    
    void test_BGRAToNV12(const cv::Mat& matSrc, int width, int height, int size_frame, cv::Mat& matDst)
    {
    	// BGRA <--> NV12
    	cv::Mat matBGRA, matNV12;
    	cv::cvtColor(matSrc, matBGRA, cv::COLOR_BGR2BGRA);
    
    	uchar* pNV12 = new uchar[width * height + ((width + 1) / 2) * ((height + 1) / 2) * 2];
    	memset(pNV12, 0, sizeof(uchar) * (width * height + ((width + 1) / 2) * ((height + 1) / 2) * 2));
    	uchar* dst_y = pNV12;
    	int dst_y_stride = width;
    	uchar* dst_vu = pNV12 + size_frame;
    	int dst_vu_stride = (width + 1) / 2 * 2;
    
    	libyuv::ARGBToNV12(matBGRA.data, width * 4, dst_y, dst_y_stride, dst_vu, dst_vu_stride, width, height);
    	matNV12 = cv::Mat(height, width, CV_8UC4, cv::Scalar::all(0));
    	libyuv::NV12ToARGB(dst_y, dst_y_stride, dst_vu, dst_vu_stride, matNV12.data, width * 4, width, height);
    	cv::imwrite("NV12_bgra.jpg", matNV12);
    	matNV12.copyTo(matDst);
    
    	int count_diff = 0;
    	int max_diff = 0;
    	int threshold = 20;//
    	for (int i = 0; i < height; i++) {
    		uchar* pSrc = matBGRA.ptr(i);
    		uchar* pDst = matNV12.ptr(i);
    		for (int j = 0, m = 0; j < width; j++, m += 4) {
    			int tmp = std::max(abs(pSrc[m] - pDst[m]), abs(pSrc[m + 1] - pDst[m + 1]));
    			tmp = std::max(tmp, abs(pSrc[m + 2] - pDst[m + 2]));
    			if (tmp > max_diff)
    				max_diff = tmp;
    
    			if (abs(pSrc[m] - pDst[m]) > threshold ||
    				abs(pSrc[m + 1] - pDst[m + 1]) > threshold ||
    				abs(pSrc[m + 2] - pDst[m + 2]) > threshold) {
    				count_diff++;
    				//std::cout << i << "    " << j << std::endl;
    			}
    		}
    	}
    
    	std::cout << "convert NV12 to BGRA diff max: " << max_diff << std::endl;
    	if (count_diff > width + height) {//
    		std::cout << "convert NV12 to BGRA error." << std::endl;
    		std::cout << "diff num: " << count_diff << std::endl;
    	}
    
    	delete[] pNV12;
    }
    
    void test_BGRAToNV21(const cv::Mat& matSrc, int width, int height, int size_frame, cv::Mat& matDst)
    {
    	// BGRA <--> NV21
    	cv::Mat matBGRA, matNV21;
    	cv::cvtColor(matSrc, matBGRA, cv::COLOR_BGR2BGRA);
    
    	uchar* pNV21 = new uchar[width * height + ((width + 1) / 2) * ((height + 1) / 2) * 2];
    	memset(pNV21, 0, sizeof(uchar) * (width * height + ((width + 1) / 2) * ((height + 1) / 2) * 2));
    	uchar* dst_y = pNV21;
    	int dst_y_stride = width;
    	uchar* dst_vu = pNV21 + size_frame;
    	int dst_vu_stride = (width + 1) / 2 * 2;
    
    	libyuv::ARGBToNV21(matBGRA.data, width * 4, dst_y, dst_y_stride, dst_vu, dst_vu_stride, width, height);
    	matNV21 = cv::Mat(height, width, CV_8UC4, cv::Scalar::all(0));
    	libyuv::NV21ToARGB(dst_y, dst_y_stride, dst_vu, dst_vu_stride, matNV21.data, width * 4, width, height);
    	cv::imwrite("NV21_bgra.jpg", matNV21);
    	matNV21.copyTo(matDst);
    
    	int count_diff = 0;
    	int max_diff = 0;
    	int threshold = 20;//
    	for (int i = 0; i < height; i++) {
    		uchar* pSrc = matBGRA.ptr(i);
    		uchar* pDst = matNV21.ptr(i);
    		for (int j = 0, m = 0; j < width; j++, m += 4) {
    			int tmp = std::max(abs(pSrc[m] - pDst[m]), abs(pSrc[m + 1] - pDst[m + 1]));
    			tmp = std::max(tmp, abs(pSrc[m + 2] - pDst[m + 2]));
    			if (tmp > max_diff)
    				max_diff = tmp;
    
    			if (abs(pSrc[m] - pDst[m]) > threshold ||
    				abs(pSrc[m + 1] - pDst[m + 1]) > threshold ||
    				abs(pSrc[m + 2] - pDst[m + 2]) > threshold) {
    				count_diff++;
    				//std::cout << i << "    " << j << std::endl;
    			}
    		}
    	}
    
    	std::cout << "convert NV21 to BGRA diff max: " << max_diff << std::endl;
    	if (count_diff > width + height) {//
    		std::cout << "convert NV21 to BGRA error." << std::endl;
    		std::cout << "diff num: " << count_diff << std::endl;
    	}
    
    	delete[] pNV21;
    }

    GitHubhttps://github.com/fengbingchun/Libyuv_Test

  • 相关阅读:
    day 48
    40 协程 多路复用
    JQuery
    JS DOMBOM
    psotgres、timescaledb
    crontab命令
    Go语言结构体和方法
    Go语言锁的使用
    Go语言map数据结构
    ZOJ 3777 Problem Arrangement
  • 原文地址:https://www.cnblogs.com/yfceshi/p/7092525.html
Copyright © 2020-2023  润新知