用NEON intrinsic实现RGB转YUV420SP(NV12)

这篇博客详细介绍了如何使用NEON intrinsic将RGB数据转换为YUV420SP(NV12)格式,包括RGB与YUV的排列方式、转换公式、NEON版本的代码实现及性能测试。文章通过位移运算优化了计算效率,并提供了常规版本与NEON版本的代码对比,展现了NEON intrinsic在图像处理中的优势。
摘要由CSDN通过智能技术生成

如题,现在要把RGB的格式转成YUV格式。


1. 数据的排列方式

  先来看看两种数据在内存里是按什么方式排列的


1.1 RGB的排列

在这里插入图片描述
  如图所示,1组RGB表示1个像素的颜色,每个像素依次排列。图中有8组RGB数据,即8个像素点。


1.2 YUV的排列

在这里插入图片描述

  如图所示,这里是 YUV420SP(NV12) 的排列方式,YUV的比例为Y:U:V=4:1:1。Y代表像素点的明亮度(灰阶),图中有48个Y,即48个像素点。UV代表像素点的色度,1个U和1个V组合到一起能表示一种颜色,在YUV420格式里,1组UV决定了4个像素点的颜色,其对应关系如图所示。U和V加起来的数据量是Y的一半。
  YUV的图片还有许多种格式,请参考其它资料。

  实际上它在内存里面是按照 Y 1 Y 2 Y 3 Y 4 Y 5 Y 6 Y 7 Y 8 U 1 V 1 U 2 V 2 Y_1Y_2Y_3Y_4Y_5Y_6Y_7Y_8U_1V_1U_2V_2 Y1Y2Y3Y4Y5Y6Y7Y8U1V1U2V2的顺序排列的,如下图所示。存储的时候数据是连续排列的,解析的时候加上宽和高的信息才成为了一张矩形图片。写代码计算地址偏移的时候要注意行和列的关系。
在这里插入图片描述


2. RGB转YUV


2.1 RGB转YUV的公式

不知道哪里来的公式,但据说是总所周知的。

     Y =  (0.257*R) + (0.504*G) + (0.098*B) + 16

Cb = U = -(0.148*R) - (0.291*G) + (0.439*B) + 128

Cr = V =  (0.439*R) - (0.368*G) - (0.071*B) + 128

这个公式里面有很多小数,运算起来效率不高,整数的运算会快一点。于是就有了下面的代码:

    Y = ( ( 66*R + 129*G +  25*B) >> 8) + 16;
    
    U = ( (-38*R -  74*G + 112*B) >> 8) + 128;
    
    V = ( (112*R -  94*G -  18*B) >> 8) + 128;

什么原理呢?以Y为例,本来Y是:
Y = (0.257*R) + (0.504*G) + (0.098*B) + 16

乘以256,再除以256:
Y = ( 256*0.257*R + 256*0.504*G + 256*0.098*B )/256 + 16
Y = ( 65.792*R + 129.024*G + 25.088*B )/256 + 16

舍掉小数部分(因为已经放大256倍了,再丢掉一点小数影响不大,速度要紧)。于是:
Y = ( 65*R + 129*G + 25*B )/256 + 16

众所周知,除法可以用位移来计算,而且速度更快。这里 256 = 2 8 256=2^8 256=28 ,数据在计算机中以二进制的形式存储,因此除以256即向右移8位。于是:
Y = ( ( 65*R + 129*G + 25*B ) >> 8 ) + 16

U和V同理。


2.2 代码

这里参考https://www.jianshu.com/p/e498326a55b1?utm_campaign的代码:


2.2.1 常规版本:
typedef unsigned char byte;
void RGBtoNV12(byte* pNV12, byte* pRGB, int width, int height)
{
   
    int frameSize = width * height;
    int yIndex = 0;
    int uvIndex = frameSize;

    int R, G, B, Y, U, V;
    int index = 0;
    for (int j = 0; j < height; j++)
    {
   
        for (int i 
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值