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

#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;
}
时间: 2024-10-08 12:02:39

libyuv库的使用的相关文章

颜色空间YUV简单介绍

YUV概念:YUV是被欧洲电视系统所採用的一种颜色编码方法(属于PAL,Phase Alternation Line),是PAL和SECAM模拟彩色电视制式採用的颜色空间. 当中的Y.U.V几个字母不是英文单词的组合词,Y代表亮度,事实上Y就是图像的灰度值:UV代表色差,U和V是构成彩色的两个分量.在现代彩色电视系统中.通常採用三管彩色摄影机或彩色CCD摄影机进行取像,然后把取得的彩色图像信号经分色.分别放大校正后得到RGB,再经过矩阵变换电路得到亮度信号Y和两个色差信号B--Y(即U).R--

FreeSwitch SIP(1):linux下编译安装v1.4

本文,原文连接: http://blog.csdn.net/freewebsys/article/details/46546205 ,转载请注明出处! 1,关于FreeSwitch FreeSWITCH 是一个电话的软交换解决方案,包括一个软电话和软交换机用以提供语音和聊天的产品驱动.FreeSWITCH 可以用作交换机引擎.PBX.多媒体网关以及多媒体服务器等. FreeSWITCH 支持多种通讯技术标准,包括 SIP, H.323, IAX2 以及 GoogleTalk ,可以方便的与其他开

使用NDK编译 libyuv &lt;转&gt;

官方源码:http://code.google.com/p/libyuv/简介: libyuv is an open source project that includes YUV scaling and conversion functionality. Scale YUV to prepare content for compression, with point, bilinear or box filter. Convert to YUV from webcam formats. Co

FreeSWITCH第三方库(视频)的简单介绍(二)

FreeSWITCH使用了大量的第三方库,本文档主要介绍视频相关库的信息: 音频相关库的信息介绍参考:http://www.cnblogs.com/yoyotl/p/5486753.html 其他相关库的信息介绍参考:http://www.cnblogs.com/yoyotl/p/5489315.html ① openh264 OpenH264 是思科公司以BSD协议开放的一个开源的 H.264 编码器和解码器. Cisco 将以 BSD 协议开放其 H264 解码器实现,并提供针对主流操作系统

libyuv编译(各平台)【转】

转自:http://blog.csdn.net/wszawsz33/article/details/51669719 版权声明:本文为博主原创文章,未经博主允许不得转载. 目录(?)[-] Getting Started Pre-requisites Getting the Code Android Building the Library and Unittests Windows Building with clangcl OSX iOS Android Building with GN B

Facebook Paper使用的第三方库

第三方库名 简介 链接 ACE code editor https://github.com/ajaxorg/ace Appirater 用户评分组件 https://github.com/arashpayan/appirater Reachability 网络连通测试 https://github.com/tonymillion/Reachability AQGridView iPhone/iPad网格视图 https://github.com/AlanQuatermain/AQGridVie

67个拯救web开发者的工具、库和资源!

划重点 在本文中,我不会去谈 React.Angular.Vue 等等这些大的前端框架,也不会谈 Atom.VS code.Sublime 等等这些已经很出名的代码编辑器,我只是想简单的分享一套我认为有助于提升开发者工作流的工具集. 这套工具集中的大部分你可能见过,也可能没见过,如果有哪个让你眼前一亮,那么我的分享就很值了. 这个列表包含许多种类的资源,所以这里我将它们分组整理. Javascript 库 Particles.js-一个用来在 web 中创建炫酷的浮动粒子的库 Three.js-

sqlserver 全库查询 带架构

网上现有的全库查询,无法识别自定义架构的数据库结构: declare @str nvarchar(10) declare @tablename varchar(50) declare @colname varchar(50) declare @counts int declare @sql nvarchar(2000)--以上定义变量 declare cur1 cursor for select a.name tablename,B.name colname from sys.objects a

iOS库--.a与.framework

一.什么是库? 库是共享程序代码的方式,一般分为静态库和动态库. 二.静态库与动态库的区别? 静态库:链接时完整地拷贝至可执行文件中,被多次使用就有多份冗余拷贝. 动态库:链接时不复制,程序运行时由系统动态加载到内存,供程序调用,系统只加载一次,多个程序共用,节省内存. 三.iOS里静态库形式? .a和.framework 四.iOS里动态库形式? .dylib和.framework 五.framework为什么既是静态库又是动态库? 系统的.framework是动态库,我们自己建立的.fram