使用C++将YUV文件和RGB文件相互转换

要求

1.编写C++将RGB格式图片转换为YUV格式
2.编写C++将YUV格式图片转换为RGB格式,并分析与原RGB图像的误差

简介

1.图片分辨率为256x256,YUV格式文件为4:2:0格式采样
2.软件用的是Visual studio 2019,用fstream库读写文件
3.虽然老师给了代码,但还是想自己写哈哈,途中只遇到了一个小问题,特此感谢李老师的帮助:出现一些小红点和小蓝点,原来是unsigned char类型的数据上限只有255,下限是0,如果给一个数260就会变成5,实际上应该把它变成255,需要定义一个int类型先接收数据进行转换

实现

1.公式

RGB转VUY的公式:
Y = 0.299R+0.587G+0.114B
U = -0.1684R-0.3316G+0.5B
V = 0.5R-0.4187G-0.0813B
用个简单的matlab程序得到RGB转YUV的公式:

%format long %多看几位小数
a = [0.299 0.587 0.114;-0.1684 -0.3316 0.5;0.5 -0.4187 -0.0813];
inv(a) % 得到逆矩阵,也就是YUV转RGB的矩阵

结果为:
ans =

1.0000 -0.0000 1.4020
1.0000 -0.3441 -0.7139
1.0000 1.7718 -0.0013
也就是:
R = Y+1.4020V
G = Y-0.3441U-0.7139V
B = Y+1.7718U-0.0013V

2.图像格式

RGB格式:读取的一列数据为[b g r][b g r][b g r]…
每一个括号为一个像素点,实际上得到的数据就是bgrbgrbgr…256x256个像素点,每个像素点3个通道分量
YUV格式:此处为4:2:0格式采样,先读取256x256个Y分量,再读取128x128个U分量,最后读取128x128个V分量

4.代码

RGB转YUV

读取数据,初始化变量

#include
#include
using namespace std;


// yuv为4:2:0格式,且图像宽高都为偶数,
// 参数:输入图像路径,输出图像路径,宽,高
void rgb2yuv(const char* in_path,const char* out_path, int width, int height)
{
   
	int i, k = 0;
	int w = width;
	int h = height;
	unsigned char* buffer = new unsigned char[w * h * 3];// 存储RGB数据
	ifstream in(in_path, ios::binary);
	ofstream out(out_path, ios::binary);
	in.read((char*)buffer, w * h * 3);// 读取RGB数据
	unsigned char* y = new unsigned char[w * h];
	unsigned char* temple_u = new unsigned char[w * h]; // 得到一个w*h的U和V的矩阵暂时存着,后面得转成w/2*h/2的矩阵
	unsigned char* temple_v = new unsigned char[w * h];
	unsigned char* u = new unsigned char[w * h / 4]; // 存储真正的UV分量
	unsigned char* v = new unsigned char[w * h / 4];

将每个像素点的BGR分量转化为YUV分量,但由于是4:2:0格式,此时的UV分量不是最后写入文件的UV分量

	for (i = 0; i < w * h; i++)
		{
   
			// [k]里面存着b,[k+1]里面存着g,[k+2]里面存	着r,k+3跳到下一个b
			y[i] = 0.114 * buffer[k] + 0.587 * 		buffer[k + 1] + 0.299 * buffer[k + 2];
			temple_u[i] = 0.5 * buffer[k] - 0.3316 * buffer[k +

你可能感兴趣的:(数据压缩实验指导)