首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >使用YUV422将RGBA转换为c++格式--没有得到适当的输出

使用YUV422将RGBA转换为c++格式--没有得到适当的输出
EN

Stack Overflow用户
提问于 2016-06-14 09:54:21
回答 1查看 2.5K关注 1票数 1

我想将图像从RGBA转换为YUV422格式。下面是我的代码:

代码语言:javascript
运行
复制
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
#include <stdio.h>
#include <stdlib.h>

using namespace cv;
using namespace std;

#define CLIP(X) ( (X) > 255 ? 255 : (X) < 0 ? 0 : X)
#define RGB2Y(R, G, B) CLIP(( (  66 * (R) + 129 * (G) +  25 * (B) + 128) >> 8) +  16)
#define RGB2U(R, G, B) CLIP(( ( -38 * (R) -  74 * (G) + 112 * (B) + 128) >> 8) + 128)
#define RGB2V(R, G, B) CLIP(( ( 112 * (R) -  94 * (G) -  18 * (B) + 128) >> 8) + 128)

int main(int argc, char *argv[])
{

    Mat in_img, in_RGB, out_yuv;
    in_img = imread(argv[1],1);
    if(!in_img.data)
    {
        printf("Failed to load the image ... %s\n!", argv[1]);
        return -1;
    }
    short imgwidth  = in_img.cols;
    short imgheight = in_img.rows;

    cvtColor(in_img, in_RGB, CV_BGR2RGB);  
    out_yuv.create(imgheight, imgwidth, CV_16U);

    imwrite("RGB.jpg",in_RGB);

    for(int i = 0; i< imgheight; i++)
        for(int j = 0; j< imgwidth; j = j+2) {
            unsigned int val = in_RGB.at<unsigned int>(i,j);

/*********** for 1st pixel ***********/
            unsigned int tmp = val;
            unsigned char B = (unsigned char)(((tmp<<16) >> 24) | 0x000000ff ); //Extracting B channel data

            tmp = val;
            unsigned char G = (unsigned char)(((tmp<<8) >> 24) | 0x000000ff ); //Extracting G channel data

            tmp = val;
            unsigned char R = (unsigned char)((tmp >> 24) | 0x000000ff );  //Extracting R channel data

            unsigned char Y1 = RGB2Y(R, G, B);
            unsigned char U = RGB2U(R, G, B);
            unsigned char V = RGB2V(R, G, B);

/*********** for 2nd pixel ***********/
            unsigned int val1 = in_RGB.at<unsigned int>(i,j+1);
            unsigned int tmp1 = val1;
            unsigned char B1 = (unsigned char)(((tmp1<<16) >> 24) | 0x000000ff );

            tmp1 = val1;
            unsigned char G1 = (unsigned char)(((tmp1<<8) >> 24) | 0x000000ff );

            tmp1 = val1;
            unsigned char R1 = (unsigned char)((tmp1 >> 24) | 0x000000ff );

            unsigned char Y2 = RGB2Y(R, G, B);

/********** writing into out image in U-Y1-V-Y2 format *********************/

        unsigned short p1 = ((U << 8) | Y1) ;
        unsigned short p2 = ((V << 8) | Y2) ;
        out_yuv.at<unsigned short>(i,j) = p1;
        out_yuv.at<unsigned short>(i,j+1) = p2;

    }
        imwrite("YUV422.png",out_yuv);
return 0;   
}

但没有得到正确的输出图像。我还试着用Y1-U-Y2-V格式写它,但是输出还是一样的.上面的代码可能有什么问题,或者是输出图像格式(..png/.jpg)造成了问题?(简历:imwrite不允许以.yuv格式保存)

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-06-14 10:58:07

代码语言:javascript
运行
复制
out_yuv.create(imgheight, imgwidth, CV_16U);
...
imwrite("YUV422.png",out_yuv);

这里有几个问题:

  • imwrite认为CV_16U 成为单一频道
  • 你不能在png里面写yuv。您必须转储原始数据,并使用一个特殊的yuv查看器(如原始摇滚机 )来确保数据是正确的。

编辑:

请注意,原始像素的首字母缩写有点大,即最左边的值是内存中最不重要的字节(大多数时候,人们喜欢混淆视频)。

  • R = RGB[0]G = RGB[1]B = RGB[2]A = RGB[3]
  • 在缓冲器中p的意思是p[0]是Y0,p[1]是U,p[2]是Y1,p[3]是V

--你在做与你的轮班完全相反的事情:)

编辑2:如果您的图像仍然被置乱,您似乎愿意按照平面格式编写(YUV422P又名YV16)。平面格式意味着每个通道都在一个独立的、连续的平面上。对目标数据(unsigned char*,或std::vector<unsigned char>)使用普通的旧缓冲区会更清楚。

代码语言:javascript
运行
复制
unsigned char* out_yuv_ptr = new unsigned char[imgwidth*imgheight*2];
unsigned char* y_ptr = out_yuv_ptr;
unsigned char* u_ptr = y_ptr + imgwidth*imgheight;
unsigned char* v_ptr = u_ptr + imgwidth*imgheight/2;
...
*y_ptr = Y1;
++y_ptr
*y_ptr = Y2;
++y_ptr
*u_ptr = U;
++u_ptr;
*v_ptr = V;
++v_ptr;
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/37808695

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档