yuv422转RGB888保存bmp文件解析

uvc相机支持v4l2编程,采集格式若只支持yuv422,使用libjpeg等压缩速度降低,直接保存bmp位图速度加快.

关于v4l2对于相机的初始化部分进行省略.

分为几个关键步骤进行转换:

1:初始化正常

 

2:将底层获取与申请的内存存入缓存进行mmap进行内存映射,内核空间的地址不能直接被用户空间使用

  struct buffer{
        void *start;
        unsigned int length;
    }*buffers;

       //mmap for buffers
       buffers = (struct buffer*)malloc(req.count*sizeof (*buffers));

       buffers[n_buffers].length = buf.length;
       //map
        buffers[n_buffers].start = mmap(NULL,buf.length,PROT_READ |PROT_WRITE, MAP_SHARED, fd, buf.m.offset);inx

进行内存映射后,可以开始采集,取出缓存中的采样缓存,该buffers结构体中保存的为yuyv数据

3:对yuyv数据进行rgb888转换

基本思路:

    yuv422采集类似隔点采样存储格式编码.若采集为800*600图像数据

实际在原始的数据中width的数据为800*2.height不变为600.

进行转换时候.for(i=0;i

for(j=0;j

    y1 = *( pointer + (i*IMAGEWIDTH/2+j)*4+0);
       // u  = *( pointer + (i*IMAGEWIDTH/2+j)*4 + 1);
        y2 = *( pointer + (i*IMAGEWIDTH/2+j)*4 + 2);
       //v  = *( pointer + (i*IMAGEWIDTH/2+j)*4 + 3);
        v  = *( pointer + (i*IMAGEWIDTH/2+j)*4 + 1);
        u  = *( pointer + (i*IMAGEWIDTH/2+j)*4 + 3);

}

}

解析对于yuv422采样,思路是将列中,每次取4个字节,以4个字节为单位

所以for(j=0;j<(width*2)/4;j++)  若取指定的位置的数据

i*(width*2)跳过该行之前的数据,j*4某一列的单位的数据

*pointer指向数据的起始地址,一个单位的数据4个字节分别存放yuyv;

所以y1=*(pointer+i*(width*2)+j*4 + 0)又由于bmp中存储g b分量是颠倒的

v = *(pointer+i*(width*2)+j*4 + 1) ,y2=*(pointer+i*(width*2)+j*4 + 2)

u = *(pointer+i*(width*2)+j*4 + 3);

再此基础上再进行bgr的转换,下面的公式进行了白平衡处理

 b1 = (1.164*(y1-16)+1.159*(v-128));
        g1 = (1.164*(y1-16)-0.392*(u-128)-0.813*(v-128));
        r1 = (1.164*(y1-16)+2.018*(u-128));

        b2 = (1.164*(y2-16)+1.159*(v-128));
        g2 = (1.164*(y2-16)-0.392*(u-128)-0.813*(v-128));
        r2 = (1.164*(y2-16)+2.018*(u-128));

由于rgb格式为3个字节一个像素,使用rgb转换bmp时候.

unsigned char frame_buffer[width*height*3];

 *(frame_buffer + (i*IMAGEWIDTH/2+j)*6    ) = (unsigned char)b1;
        *(frame_buffer + (i*IMAGEWIDTH/2+j)*6 + 1) = (unsigned char)g1;
        *(frame_buffer + (i*IMAGEWIDTH/2+j)*6 + 2) = (unsigned char)r1;

        *(frame_buffer + (i*IMAGEWIDTH/2+j)*6 + 3) = (unsigned char)b2;
        *(frame_buffer + (i*IMAGEWIDTH/2+j)*6 + 4) = (unsigned char)g2;
        *(frame_buffer + (i*IMAGEWIDTH/2+j)*6 + 5) = (unsigned char)r2;

原理同上

 

 

你可能感兴趣的:(图像处理)