彩色空间内YUV和RGB的相互转换

一、实验目的

  1. 进一步理解彩色空间的概念并掌握不同彩色空间转换的基本方程。
  2. 通过逐步设计程序,掌握编程细节:如查找表的设计,内存分配,对 U 和 V 信号进行下采样,文件读写过程等。掌握程序调试的基本方法。
  3. 编写RGB转化为YUV程序,重点掌握函数定义,部分查找表的初始化和调用,缓冲区分配。将得到的RGB文件转换为YUV文件,用YUV Viewer播放器观看,验证是否正确。
  4. 编写将YUV转换为RGB的程序。将给定的实验数据用该程序转换为RGB文件。并与原RGB文件进行比较,如果有误差,分析误差来自何处。

二、实验内容

(1)YUV 与 RGB 空间的相互转换

RGB——>YUV
由电视原理可知,亮度和色差信号的构成如下:

Y=0.2990 R+0.5870 G+0.1140 B
R-Y=0.7010 R-0.5870 G-0.1140 B
B-Y=-0.2990 R-0.5870 G+0.8860 B

为了使色差信号的动态范围控制在0.5之间,需要进行归一化,对色差信号引入压缩系数。归一化后的色差信号为:

U=-0.1684 R-0.3316 G+0.5 B
V=0.5 R-0.4187 G-0.0813 B

为使色差零电平对应码电平128,引入128的偏置,使变化范围在【0,255】。
最后得到Y、U、V三者计算公式为:

Y=0.2990 R+0.5870 G+0.1140 B
​U=-0.1684 R-0.3316 G+0.5 B+128
V=0.5 R-0.4187 G-0.0813 B+128

YUV——>RGB
由上述公式反解可以得到:
(注意 UV 要各减128才能在对应的范围)

R=Y+1.4075(V-128);
G=Y-0.3455(U-128)-0.7169(V-128);
B=Y+1.779(U-128);

(2) 码电平分配及数字表达式
  • 亮电平信号量化后码电平分配
    在对分量信号进行8比特均匀量化时,共分为256个等间隔的量化级。为了防止信号变动造成过载,在256级上端留20级,下端留16级作为信号超越动态范围的保护带。
  • 色差信号量化后码电平分配
    色差信号经过归一化处理后,动态范围为-0.5-0.5,让色差零电平对应码电平128,色差信号总共占225个量化级。在256级上端留15级,下端留16级作为信号超越动态范围
    的保护带。
(3)色度格式

4:2:0格式是指色差信号U,V的取样频率为亮度信号取样频率的四分之一,在水平方向和垂直方向上的取样点数均为Y的一半。

三、实验思路

RGB to YUV

对UV数据进行下采样
在这里插入图片描述
YUV to RGB

对UV数据进行上采样
在这里插入图片描述

四、示例实验代码

1.示例所给的代码关键

1)定义字节长度

#define u_int8_t	unsigned __int8
#define u_int		unsigned __int32
#define u_int32_t	unsigned __int32
#define FALSE		false
#define TRUE		true

2)所有用到的计算结果的声明

static float RGBYUV02990[256], RGBYUV05870[256], RGBYUV01140[256];
static float RGBYUV01684[256], RGBYUV03316[256];
static float RGBYUV04187[256], RGBYUV00813[256];

3)所有用到的计算结果的计算,即形成查找表
(查找表虽然浪费一定空间,但是每次运算直接查找即可,无需每次都算一编,提高效率)

void InitLookupTable()
{
   
	int i;

	for (i = 0; i < 256; i++) RGBYUV02990[i] = (float)0.2990 * i;
	for (i = 0; i < 256; i++) RGBYUV05870[i] = (float)0.5870 * i;
	for (i = 0; i < 256; i++) RGBYUV01140[i] = (float)0.1140 * i;
	for (i = 0; i < 256; i++) RGBYUV01684[i] = (float)0.1684 * i;
	for (i = 0; i < 256; i++) RGBYUV03316[i] = (float)0.3316 * i;
	for (i = 0; i < 256; i++) RGBYUV04187[i] = (float)0.4187 * i;
	for (i = 0; i < 256; i++) RGBYUV00813[i] = (float)0.0813 * i;
}

2.运行结果

在这里插入图片描述

  • 原本的 rgb 文件

在这里插入图片描述

  • 程序运行后生成的 yuv 文件

在这里插入图片描述

五、自己编写的实验代码

1.RGB to YUV

在这里插入图片描述

  • rgb2yuv_ziji.h
int RGB2YUV (int x_dim, int y_dim, void *bmp, void *y_out, void *u_out, void *v_out);

void InitLookupTable();

  • main.cpp
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include<math.h>
#include "rgb2yuv_ziji.h"

int main(int argc, char** argv)
{
   
	int frameWidth ;			
	int frameHeight ;		

	char* rgbFileName = NULL;
	char* yuvFileName = NULL;
	FILE* rgbFile = NULL;
	FILE* yuvFile = NULL;
	unsigned char* rgbBuf = NULL;
	unsigned char* yBuf = NULL;
	unsigned char* uBuf = NULL;
	unsigned char* vBuf = NULL;

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

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

	//打开yuv文件
	fopen_s(&yuvFile,yuvFileName,"wb");
	if (yuvFile == NULL)
	{
   
		printf("cannot find y
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值