RGB2YUV相互转换实验

news/2024/7/21 7:10:56 标签: 图像处理

rgb2yuv

实验思路:
在这里插入图片描述
在这里插入图片描述

main函数关键代码:

#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include "rgb2yuv.h"
#define u_int8_t	unsigned __int8
#define u_int		unsigned __int32
#define u_int32_t	unsigned __int32
#define FALSE		false
#define TRUE		true


int main(int argc, char** argv)
{
	u_int frameWidth = 352;			/width/
	u_int frameHeight = 240;		/height/
	bool flip = TRUE;				/flip/
	unsigned int i;
	char* rgbFileName = NULL;
	char* yuvFileName = NULL;
	FILE* rgbFile = NULL;
	FILE* yuvFile = NULL;
	u_int8_t* rgbBuf = NULL;
	u_int8_t* yBuf = NULL;
	u_int8_t* uBuf = NULL;
	u_int8_t* vBuf = NULL;
	u_int32_t videoFramesWritten = 0;

	rgbFileName = argv[1];
	yuvFileName = argv[2];

	frameWidth = atoi(argv[3]);
	frameHeight = atoi(argv[4]);
	
	rgbFile = fopen(rgbFileName, "rb");
	if (rgbFile == NULL)
	{
		printf("cannot find rgb file\n");
		exit(1);
	}
	else
	{
		printf("The input rgb file is %s\n", rgbFileName);
	}

	yuvFile = fopen(yuvFileName, "wb");
	if (yuvFile == NULL)
	{
		printf("cannot find yuv file\n");
		exit(1);
	}
	else
	{
		printf("The output yuv file is %s\n", yuvFileName);
	}

	rgbBuf = (u_int8_t*)malloc(frameWidth * frameHeight * 3);
	yBuf = (u_int8_t*)malloc(frameWidth * frameHeight);
	uBuf = (u_int8_t*)malloc((frameWidth * frameHeight) / 4);
	vBuf = (u_int8_t*)malloc((frameWidth * frameHeight) / 4);

	if (rgbBuf == NULL || yBuf == NULL || uBuf == NULL || vBuf == NULL)
	{
		printf("no enought memory\n");
		exit(1);
	}

	while (fread(rgbBuf, 1, frameWidth * frameHeight * 3, rgbFile)) 
	{
		if(RGB2YUV(frameWidth, frameHeight, rgbBuf, yBuf, uBuf, vBuf, flip))
		{
			printf("error");
			return 0;
					}

		for (i = 0; i < frameWidth*frameHeight; i++)
		{
			if (yBuf[i] < 16) yBuf[i] = 16;
			if (yBuf[i] > 235) yBuf[i] = 235;
		}

		for (i = 0; i < frameWidth*frameHeight/4; i++)
		{
			if (uBuf[i] < 16) uBuf[i] = 16;
			if (uBuf[i] > 240) uBuf[i] = 240;

			if (vBuf[i] < 16) vBuf[i] = 16;
			if (vBuf[i] > 240) vBuf[i] = 240;
		}

		fwrite(yBuf, 1, frameWidth * frameHeight, yuvFile);
		fwrite(uBuf, 1, (frameWidth * frameHeight) / 4, yuvFile);
		fwrite(vBuf, 1, (frameWidth * frameHeight) / 4, yuvFile);

		printf("\r...%d", ++videoFramesWritten);
	}
	printf("\n%u %ux%u video frames written\n", 
		videoFramesWritten, frameWidth, frameHeight);
	/* cleanup */
	fclose(rgbFile);
	fclose(yuvFile);
	return(0);

YUV2RGB实验思路

本次实验为YUV格式与RGB格式的转换,这里的YUV其实是指数字高清的YCbCr。

根据亮度和色差计算公式,可以得到:

Y=0.299R+0.587G+0.114B
Cr=R-Y=0.701R-0.587G-0.114B
Cb=B-Y=-0.299R-0.587G+0.886B

使色差信号的动态范围控制在-0.5~+0.5之间,要对色差信号进行归一化处理,得到UV的计算公式:
U=-0.1684R-0.3316G+0.5B
V=0.5R-0.4187G-0.0813B
由上式得到的UV范围在-128~+127之间,为避免负数,将其数值各扩大128达到非负。

  • YUV在存储时,为了防止信号变得造成过载,在对分量信号进行8比特均匀量化时,各自预留分量所限制的保护带,防止数值超越动态范围。

  • 得到YUV转换RUV的公式:
    B=Y+1.779U
    G=Y-0.3455U-0.7169V
    R=Y+1.4075V
    注意:这里在计算RBG时应先将UV的值减128。
    这里YUV采用的是4:2:0格式,即色度信号是亮度信号取样频率的四分之一。

主函数思路:

  • 读取YUV文件,新建导出的RGB文件及空间

  • RGB文件是按照BGRBGRBGR……的顺序存储一帧的,所以RGB设定一个3倍像素数的数组,而YUV文件是YYYY……U……V……存储文件的,可以开辟一个像素数大小的数组存放Y分量和两个四分之一像素数大小的数组存放U和V分量。

  • 读取图像YUV值存储于YUV三个缓存数组中

  • 因为YUV有动态范围,需要判断Y和UV是否逾出

  • 对YUV进行上采样,恢复出444格式的YUV。

  • 按照转换公式,将每一个像素分别转换为RGB格式存在RGB缓存数组中。

#include <iostream>
#include"yuv2rgb. h"
#include" stdlib. h"
#include <malloc.h>
static float YUVRGB14075 [256] ;
static float YUVRGB07169 [256],YUVRGB03455 [256];
static float YUVRGB01779 [256] ;
int YUV2RGB( void* y_ in. void* u_ in. void* v_ in. void* rgb_ out,int W,int H)
{
unsigned char *b, *g, *r, *uBuff, *vBuff ;
unsigned char *y,*u,*v;
b = (unsigned char *)rgb_ out:
y = (unsigned char *)y_ in:
uBuff = (unsigned char *)u_ in;
vBuff = (unsigned char *)v_ in;
u = uBuff:
v = vBuff;
InitLookupTable();
float rt,gt, bt;
int i, j;

for (j = 0;j <H;j++)
{
    for (i = 0: i < W; i++)
   {
      g = b + 1;
      r = b + 2;
      rt = (*y) + YUVRGB14075[*v];
      gt =(*y) - YUVRGB07169[*v] - YUVRGB03455[*u];
      bt = (*y) + YUVRGB01779[*u];
     if (bt < 0)
         bt = 0;
     if (bt > 255)
         bt = 255;
     if (gt < 0)
         gt = 0;
     if (gt >255)
         gt = 255;
     if (rt< 0)
         rt = 0;
     if (rt > 255)
         rt = 255;
   *r = (unsigned char) rt ;
   *g = (unsigned char)gt ;
   *b= (unsigned char)bt ;
   b+=3; 
   y++;
    if (i % 2== 0 && j %2== 0)
     {
       u++;
       v++;
     }
   }
 } 
return 0;
}
void InitLookupTable()
{
  int i;
  for (i = 0;i < 256; i++)
{
YUVRGB14075[i] = (float) 1.4075 * i ;
YUVRGB07169[i] = (float)0.7169* i ;
YUVRGB03455[i] = (float)0.3455 * i;
YUVRGB01779[i] = (float)0.1779 * i ;
 }
 }

打开与写入相关代码

 errno_t err;
 err = fopen_s(&yuvFile,yuvFileName, "rb");
 
 if (err==0)
 {
  printf("The yuv file is %s\n", yuvFileName);
 }
 else
 {
  printf("yuv file can not be found \n");
 }
 //写入rgb文件
 err = fopen_s(&rgbFile,rgbFileName, "wb");
 if (err == 0)
 {
  printf("The  rgb file is %s\n", rgbFileName);
 }
 else
 {
  printf("rgb file can not be found \n");
 }
 //rgb内存
 while (fread(yBuf, 1, frameWidth * frameHeight, yuvFile)&&fread(uBuf, 1, frameWidth * frameHeight /4, yuvFile)&&fread(vBuf, 1, frameWidth * frameHeight /4, yuvFile)) 
 {
  //写入rgb
  fwrite(rgbBuf, 1, frameWidth * frameHeight*3, rgbFile);
 }

在这里插入图片描述
在这里插入图片描述

感想总结巴拉巴拉:

对于一个编程一直是很怕很怕而且基础很弱的人来说,这样的实验看要求总会是一头雾水,不知道是什么的慌张感。能够完成首先感谢老师一步一步给出的一个方向转换的讲解,能够对整个过程有了解,不惧怕,然后感谢小伙伴和网络上的宝藏资源,能够慢慢尝试,想必之后的实验也是费时费力,希望随着学习能够有思路,不逃避,有进步!


http://www.niftyadmin.cn/n/792314.html

相关文章

WPF使用声音资源

1.在项目上右键&#xff0c;增加Resources文件夹&#xff1b;在Resources文件夹上右键&#xff0c;增加Audio文件夹&#xff1b;往Audio文件夹中增加声音资源文件&#xff1a;didi.wav。 2.右键didi.wav&#xff0c;选择属性&#xff0c;设置属性复制到输出目录为始终复制&…

javaCV入门指南:调用FFmpeg原生API和JavaCV是如何封装了FFmpeg的音视频操作?

JavaCV入门指南系列: JavaCV入门指南:序章(看完本章后,不想看原理的小伙伴可直接跳转到《快速上手篇》) JavaCV入门指南:调用FFmpeg原生API和JavaCV是如何封装了FFmpeg的音视频操作 JavaCV入门指南:调用opencv原生API和JavaCV是如何封装了opencv的图像处理操作 JavaCV入…

javaFX游戏开发实战:从零开始开发和实现自娱自乐小游戏:奥赛罗(黑白棋、翻转棋),支持可落子位置提示,原创翻转算法,基于JavaFX2.0的Canvas画板,界面逻辑与算法分离结构

前言: 这次是从前就特别喜欢玩的“奥赛罗”,但是国内玩的人不多,后来也就慢慢淡忘了。偶然想起来,觉得还是挺有意思的,就着手开发了。之前已经写过两三个小游戏,所以开发起来也很顺畅,原以为利用业余时间几天应该能写完的,断断续续写了两三个星期。中间觉得不好又推翻…

BMP2YUV文件转化

BMP文件数据中的四层结构&#xff0c;分别是位图文件头、位图信息头、调色板、实际的位图数据。从位图信息头中提取图像宽高、实际的位图数据所在数据&#xff0c;从BMP中读取实际的位图数据&#xff0c;进而索引调色板数组得到每一数据的实际物理意义&#xff0c;即查找得到各…

开始整理过去的知识点

最近开始找工作&#xff0c;知识点太多&#xff0c;想好好整理一下。 好久没有写博客了&#xff0c;哇&#xff0c;距离上一篇随笔整整5个月了&#xff01;我够懒&#xff01;够“坚持不懈”&#xff01; 真对自己无语~~~ 好吧&#xff0c;开始&#xff0c;Just do it!转载于:h…

LZW解码原理和实现算法及效率评估

LZW解码原理和实现算法* &#xff1a; LZW解码算法开始时&#xff0c;译码词典和编码词典相同&#xff0c;包含所有可能的前缀根。具体解码算法如下&#xff1a; 步骤1&#xff1a;在开始译码时词典包含所有可能的前缀根。 步骤2&#xff1a;令CW&#xff1a;码字流中的第一个…

云游戏流媒体整体架构设计(云游戏流媒体技术前瞻,最近云游戏概念很火,加之对流媒体技术略有研究,简单写一些)

前言&#xff1a; 遥想当年阿法狗战败一众围棋国手&#xff0c;风气一转&#xff0c;似乎所有人都懂AI。这次谷歌又放出了stadia&#xff0c;国内鹅厂再次跑步进场&#xff0c;贵州某xx云提前布局。 闲来无事&#xff0c;尝试体验了一下贵州某xx云的云游戏&#xff08;不打广…

DPCM系统的实现与分析

1&#xff0e;DPCM编解码原理 DPCM是差分预测编码调制的缩写&#xff0c;是比较典型的预测编码系统。在DPCM系统中&#xff0c; 需要注意的是预测器的输入是已经解码以后的样本。之所以不用原始样本来做预测&#xff0c;是因为在解码端无法得到原始样本&#xff0c;只能得到存…