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;
}

GitHubhttps://github.com/fengbingchun/Libyuv_Test

### 回答1: 要下载libyuv的Windows版本,可以按照以下步骤进行操作: 1. 打开浏览器,访问libyuv的官方网站。在搜索引擎中输入“libyuv”即可找到相关网站。 2. 在官方网站上,寻找“Downloads”或类似的选项。这个选项通常位于网站的主导航栏中。 3. 在“Downloads”页面上,查找适用于Windows操作系统的版本。通常会提供不同的版本,例如32位和64位。 4. 点击适用于Windows的下载链接,开始下载libyuv的安装程序。 5. 一旦下载完成,双击安装程序开始安装libyuv。 6. 在安装过程中,根据提示选择安装的位置和其他选项。可以选择默认设置或自定义设置。 7. 继续点击“安装”按钮,等待安装程序完成的安装过程。 8. 安装完成后,可以在指定的安装位置找到libyuv的文件。 9. 确认安装成功后,即可开始在Windows系统中使用libyuv。 请注意,以上步骤仅为一般示范,具体操作可能因不同版本的libyuv和官方网站的更新而有所不同。因此,在下载和安装libyuv时,建议查找并参考官方网站的具体说明和指导。 ### 回答2: 要下载libyuv的Windows版本,可以按照以下步骤进行操作。 首先,在你的浏览器中打开libyuv的官方网站,网址为https://chromium.googlesource.com/libyuv/libyuv/。在该网站上,你可以找到该的最新版本和其他相关信息。 然后,浏览官方网站上的页面,找到与Windows版本相关的下载链接。一般来说,官方网站会提供多种不同版本的供下载,你需要选择与Windows平台兼容的版本。 点击相应的下载链接后,你将被重定向到下载页面。有些网站可能会要求你提供一些必要的信息或者注册账号,这些步骤可根据具体情况进行。 接着,选择适合你的Windows操作系统版本的进行下载。一般来说,官方网站会提供多个不同版本的,包括32位和64位版本。 等待下载完成后,你可以将下载好的文件保存到受支持的目录中,例如你的项目文件夹或者系统目录。 最后,在你的编程环境中配置libyuv,确保你可以在你的Windows项目中正确调用该的函数和功能。 总结来说,下载libyuv的Windows版本,你需要访问官方网站,找到与Windows平台兼容的文件,进行下载和配置。 ### 回答3: 要下载libyuv的Windows版本,可以按照以下步骤进行操作: 1. 打开libyuv的官方网站。可以使用搜索引擎搜索"libyuv官方网站",从搜索结果中选择官方网站链接。 2. 在官方网站上找到下载页面。通常,在网站的导航栏或主页上都会提供一个"下载"或"Download"选项。点击该选项进入下载页面。 3. 在下载页面上寻找Windows版本的文件。一般来说,不同的平台会有相应的下载链接,如Windows、Linux、Mac等。找到Windows版本的文件下载链接。 4. 点击Windows版本的下载链接,开始下载文件。通常,文件会以压缩文件的形式提供,如.zip或.tar.gz等。 5. 下载完成后,解压缩文件。使用解压缩工具(如WinRAR、7-Zip等)打开下载的压缩文件,并将其中的文件解压到你想要存放的目录中。 现在,你已经成功下载了libyuv的Windows版本。你可以根据自己的需要将其集成到你的项目中,并使用其中的函数和工具来进行图像处理和视频编解码等操作。记得在使用文件时,仔细阅读官方提供的文档和示例,以便正确地使用和调用中的功能。
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值