24位的RGB图片数据转化成YUV422数据

本文详细介绍了如何将24位RGB图像数据转换为YUV422格式,涉及到C++和C语言实现的算法及数据结构操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

24位的RGB图片数据转化成YUV422数据,之前截图的,可以再优化下RGB2YUV函数,不再用浮点数据做运算能节省CPU

        y =  (299 * r + 587 * g + 117 * b) / 1000

        u =  (-1687* r + 3313* g + 5000 * b ) / 10000 + 128

         v =  (5000* r -  4187 * g  - 813 * b) / 10000 + 128

void RGB2YUV(unsigned char r, unsigned char g, unsigned char b,unsigned char &y, unsigned char &u, unsigned char &v)
{
    y = 0.299 * r + 0.587 * g + 0.114 * b;
    u = -0.1687 * r -  0.3313 * g + 0.5 * b + 128;
    v = 0.5 * r - 0.4187 * g -0.0813 * b + 128;
}


void RGB24TOYUV422(unsigned char *pRgb, int w, int h, unsigned char *pYuv)
{
    w = w / 2 * 2;
    
    for(int height = 0; height < h; height ++)
    {
        unsigned char *ptrRGB = pRgb + height * w * 3;
        unsigned char *ptrYUV = pYuv + height * w * 2;

        for(int width = 0; width < w ; width += 2)
        {
            unsigned char y1, u1, v1, y2, u2, v2, r1, g1, b1, r2, g2, b2;
            r1 = *ptrRGB;
            ptrRGB++;
            g1 = *ptrRGB;
            ptrRGB++;
            b1 = *ptrRGB;
            ptrRGB++;

            r2 = *ptrRGB;
            ptrRGB++;
            g2 = *ptrRGB;
            ptrRGB++;
            b2 = *ptrRGB;
            ptrRGB++;

            RGB2YUV(r1, g1, b1, y1, u1, v1);
            RGB2YUV(r2, g2, b2, y2, u2, v2);

            //u、v分量取平均值
            unsigned char u = (u1 + u2) / 2;
            unsigned char v = (v1 + v2) / 2;
            *ptrYUV = y1;
            ptrYUV++;
            *ptrYUV= u;
            ptrYUV++;
            *ptrYUV= y2;
            ptrYUV++;            
            *ptrYUV= v;
            ptrYUV++;
        }
    }
}

RGB图像换为YUV420格式是图像处理中常见的需求,特别是在视频编码和图像压缩领域。在Python中,可以通过手动实现换公式或使用OpenCV等库完成这一任务。 ### 手动实现RGBYUV420的换 为了进行RGBYUV420的换,需要遵循以下步骤: 1. **读取RGB图像**:可以使用Pillow库来加载图像并提取RGB数据。 2. **定义YUV换公式**:根据BT601标准(适用于SDTV),RGBYUV换公式如下: $$ \begin{aligned} Y &= 0.257 \cdot R + 0.504 \cdot G + 0.098 \cdot B + 16 \\ U &= -0.148 \cdot R - 0.291 \cdot G + 0.439 \cdot B + 128 \\ V &= 0.439 \cdot R - 0.368 \cdot G - 0.071 \cdot B + 128 \end{aligned} $$ 3. **下采样U和V分量**:由于YUV420格式的特性,U和V分量只需要每个2x2像素块存储一个值。 4. **保存为YUV420格式**:将Y、U、V数据拼接成YUV420格式,并以二进制形式保存[^2]。 以下是完整的Python代码示例: ```python import numpy as np from PIL import Image def rgb_to_yuv420(width, height, rgb_data): # 将RGB数据换为numpy数组 rgb = np.frombuffer(rgb_data, dtype=np.uint8).reshape((height, width, 3)) # 初始化YUV数组 y = np.zeros((height, width), dtype=np.uint8) u = np.zeros((height // 2, width // 2), dtype=np.uint8) v = np.zeros((height // 2, width // 2), dtype=np.uint8) # RGBYUV for i in range(height): for j in range(width): r = rgb[i, j, 0] g = rgb[i, j, 1] b = rgb[i, j, 2] y_val = int(0.257 * r + 0.504 * g + 0.098 * b + 16) u_val = int(-0.148 * r - 0.291 * g + 0.439 * b + 128) v_val = int(0.439 * r - 0.368 * g - 0.071 * b + 128) y[i, j] = np.clip(y_val, 0, 255) # 下采样U和V分量 for i in range(0, height, 2): for j in range(0, width, 2): avg_u = (int(rgb[i, j, 0]) + int(rgb[i, j+1, 0]) + int(rgb[i+1, j, 0]) + int(rgb[i+1, j+1, 0])) // 4 avg_v = (int(rgb[i, j, 1]) + int(rgb[i, j+1, 1]) + int(rgb[i+1, j, 1]) + int(rgb[i+1, j+1, 1])) // 4 u_val = int(-0.148 * avg_u - 0.291 * avg_v + 0.439 * ((avg_u + avg_v) // 2) + 128) v_val = int(0.439 * avg_u - 0.368 * avg_v - 0.071 * ((avg_u + avg_v) // 2) + 128) u[i//2, j//2] = np.clip(u_val, 0, 255) v[i//2, j//2] = np.clip(v_val, 0, 255) # 拼接YUV420数据 y_data = y.tobytes() u_data = u.tobytes() v_data = v.tobytes() return y_data + u_data + v_data # 示例:读取RGB图像并换为YUV420 image_path = "example_rgb.jpg" output_path = "output.yuv" # 读取RGB图像 img = Image.open(image_path) width, height = img.size rgb_data = img.convert("RGB").tobytes() # 调用换函数 yuv_data = rgb_to_yuv420(width, height, rgb_data) # 保存为YUV420文件 with open(output_path, "wb") as f: f.write(yuv_data) ``` ### 使用OpenCV实现RGBYUV420的换 OpenCV提供了直接的色彩空间换功能,简化了RGBYUV420的换过程。以下是基于OpenCV的实现: ```python import cv2 import numpy as np # 读取RGB图像 image_path = "example_rgb.jpg" rgb_image = cv2.imread(image_path) # 换为YUV颜色空间 yuv_image = cv2.cvtColor(rgb_image, cv2.COLOR_BGR2YUV) # 提取Y、U、V分量 y, u, v = cv2.split(yuv_image) # 对U和V分量进行下采样(YUV420格式) u_downsampled = cv2.resize(u, (u.shape[1] // 2, u.shape[0] // 2), interpolation=cv2.INTER_LINEAR) v_downsampled = cv2.resize(v, (v.shape[1] // 2, v.shape[0] // 2), interpolation=cv2.INTER_LINEAR) # 保存为YUV420文件 yuv420_data = y.tobytes() + u_downsampled.tobytes() + v_downsampled.tobytes() output_path = "output_opencv.yuv" with open(output_path, "wb") as f: f.write(yuv420_data) ``` ### 总结 - 手动实现方式适合需要完全控制换流程的场景,但需要注意精度和性能优化。 - OpenCV提供了一种更简洁的方式,适合快速实现且不需要深入细节的应用。 无论采用哪种方法,最终生成的YUV420数据都可以用于进一步的视频编码或其他应用。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

bkspiderx

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值