opencv格式转换

opencv C++,可以转化yuv422sp或yuv422p数据到rgb嘛,找不到这个转换格式呀,有懂opencv的吗



#include <iostream>
#include <opencv2/opencv.hpp>
#include "pencv.h"

using namespace std;
using namespace cv;
using namespace pencv;

int main() {
    // 读取YUV422SP或YUV422P数据
    uchar y_plane[640*480], u_plane[640*480], v_plane[640*480];
    FILE* f = fopen("input.yuv", "rb");
    fread(y_plane, 1, sizeof(uchar)*640*480, f);
    fclose(f);
    f = fopen("input.yuv", "rb");
    fread(u_plane, 1, sizeof(uchar)*640*480, f);
    fclose(f);
    f = fopen("input.yuv", "rb");
    fread(v_plane, 1, sizeof(uchar)*640*480, f);
    fclose(f);

    // 将YUV422SP数据转换为RGB数据
    int width = 640, height = 480;
    int y_size = width * height;
    int u_size = width >> 1, v_size = height >> 1;
    uint8_t* y_rgb = new uint8_t[y_size * 3];
    uint8_t* u_rgb = new uint8_t[u_size * 3];
    uint8_t* v_rgb = new uint8_t[v_size * 3];
    memset(y_rgb, 0, y_size * 3);
    memset(u_rgb, 0, u_size * 3);
    memset(v_rgb, 0, v_size * 3);
    int y_p = 0, u_p = 0, v_p = 0;
    for (int i = 0; i < y_size; i++) {
        y_rgb[i] = y_plane[y_p++];
        if (i % (width >> 1) == 0) {
            u_p = 0;
            v_p = i / (width >> 1);
        } else if (i % (width >> 1) == (width >> 1)) {
            u_p++;
            v_p++;
        }
        if (i % (height >> 1) == 0) {
            u_rgb[(width >> 1) * v_p + u_p] = u_plane[u_p++];
            v_rgb[(width >> 1) * v_p + u_p] = v_plane[v_p++];
        } else if (i % (height >> 1) == (height >> 1)) {
            u_rgb[(width >> 1) * v_p + u_p] += u_plane[u_p++];
            v_rgb[(width >> 1) * v_p + u_p] += v_plane[v_p++];
        }
    }

    // 将RGB数据写入文件输出
    FILE* f = fopen("output.jpg", "wb");
    fwrite(y_rgb, sizeof(uint8_t), y_size * 3, f);
    fwrite(u_rgb, sizeof(uint8_t), u_size * 3, f);
    fwrite(v_rgb, sizeof(uint8
  • 关于该问题,我找了一篇非常好的博客,你可以看看是否有帮助,链接:Opencv之读取yuv420P
  • 除此之外, 这篇博客: 【OPENCV】颜色通道YUV420与RGB的转换中的 1. YUV420p 部分也许能够解决你的问题, 你可以仔细阅读以下内容或跳转源博客中阅读:
  • 这里不详细介绍YUV420, 简单的介绍一下,比如有一个 HxW 大小的图,如果是RGB颜色分量,那么每个通道都是HxW ,对于一个3通道的RGB来说,在传输的时候,所消耗的带宽是HxWx3。为了节省带宽,在视频传输,经常用的颜色通道是YUV420P, 这就意味着每4个Y共享1个U和V,这也相当于HxW 大小的Y通道,H x W x (1/4) 大小的U和 H x W x (1/4) 大小的V。这样即可节省一半的带宽。

    假设有一个YUV视频(*.yuv),从yuv视频中读取帧的代码如下:

        fp = open(videofile, 'rb')
        filename = videofile.split('/')[-1][:-4] # for save
        # fp_out = open(savepath+filename+"_out.yuv", 'wb')
    
        framesize = height * width * 3 // 2  
        h_h = height // 2
        h_w = width // 2
        fp.seek(0, 2)  
        ps = fp.tell() 
        numfrm = ps // framesize  
        fp.seek(0, 0)
        for i in range(numfrm):
            print("%d/ %d"%(i, numfrm))
            Yt = np.zeros(shape=(height, width), dtype='uint8')
            Ut = np.zeros(shape=(h_h, h_w), dtype='uint8')
            Vt = np.zeros(shape=(h_h, h_w), dtype='uint8')
    
            for m in range(height):
                for n in range(width):
                    Yt[m, n] = ord(fp.read(1))
            for m in range(h_h):
                for n in range(h_w):
                    Ut[m, n] = ord(fp.read(1))
            for m in range(h_h):
                for n in range(h_w):
                    Vt[m, n] = ord(fp.read(1))
    
            img = np.concatenate((Yt.reshape(-1), Ut.reshape(-1), Vt.reshape(-1))) 
            img = img.reshape((height*3 // 2, width)).astype('uint8') 
            bgr_img = cv2.cvtColor(img, cv2.COLOR_YUV2BGR_I420) 
    
  • 以下回答由chatgpt基于相关博客总结生成:

    解决方案: 根据参考资料中的公式,可以编写相关的代码实现YUV到RGB的转换。以下提供一种实现:

    void yuv422pToRgb(uint8_t* yuv, uint8_t* rgb, size_t height, size_t width)
    {
        int size = height * width;
        uint8_t* yFrame = yuv;
        uint8_t* uFrame = yFrame + size;
        uint8_t* vFrame = uFrame + size / 2;
        int offset = 0;
        for (int i = 0; i < height; i++)
        {
            for (int j = 0; j < width; j += 2)
            {
                int yIdxL = i * width + j;
                int yIdxR = yIdxL + 1;
                int uIdx = (i / 2) * (width / 2) + (j / 2);
                int vIdx = uIdx;
                int R1 = yFrame[yIdxL] + 1.13983 * (vFrame[vIdx] - 128);
                int G1 = yFrame[yIdxL] - 0.39465 * (uFrame[uIdx] - 128) - 0.58060 * (vFrame[vIdx] - 128);
                int B1 = yFrame[yIdxL] + 2.03211 * (uFrame[uIdx] - 128);
                int R2 = yFrame[yIdxR] + 1.13983 * (vFrame[vIdx] - 128);
                int G2 = yFrame[yIdxR] - 0.39465 * (uFrame[uIdx] - 128) - 0.58060 * (vFrame[vIdx] - 128);
                int B2 = yFrame[yIdxR] + 2.03211 * (uFrame[uIdx] - 128);
                R1 = R1 < 255 ? R1 : 255;
                G1 = G1 < 255 ? G1 : 255;
                B1 = B1 < 255 ? B1 : 255;
                R2 = R2 < 255 ? R2 : 255;
                G2 = G2 < 255 ? G2 : 255;
                B2 = B2 < 255 ? B2 : 255;
                R1 = R1 < 0 ? 0 : R1;
                G1 = G1 < 0 ? 0 : G1;
                B1 = B1 < 0 ? 0 : B1;
                R2 = R2 < 0 ? 0 : R2;
                G2 = G2 < 0 ? 0 : G2;
                B2 = B2 < 0 ? 0 : B2;
                rgb[offset++] = (unsigned char)R1;
                rgb[offset++] = (unsigned char)G1;
                rgb[offset++] = (unsigned char)B1;
                rgb[offset++] = (unsigned char)R2;
                rgb[offset++] = (unsigned char)G2;
                rgb[offset++] = (unsigned char)B2;
            }
        }
    }
    

    该函数将YUV422p格式的视频流转换为了RGB格式,其中输入参数为yuv、输出参数为rgb、视频流的高度为height、视频流的宽度为width。该函数的原理是先将每个像素点的Y、U、V值转换为R、G、B值,再将每个像素点对应的两个RGB值写入输出的rgb数组中。

    需要注意的是,该函数只是一种简单的实现方法,不一定适用于所有的视频流。对于不同的视频流,可能需要稍微修改代码中的参数才能得到正确的结果。