作业|彩色空间转换

一、实验目的

1.学会从计算和程序的角度分析问题
通过完成本实验,理解计算思维,即从问题出发,通过逐步分析和分解,把原问题转化 为可用程序方式解决的问题。在此过程中设计出一个解决方案。
2.进一步理解彩色空间的概念并掌握不同彩色空间转换的基本方程。
3.通过逐步设计程序,掌握编程细节:如查找表的设计,内存分配,对 U 和 V 信号进 行下采样,文件读写过程等。掌握程序调试的基本方法。

二、知识基础

1、亮度方程

{ 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 \begin{cases} Y=0.2990R+0.5870G+0.1140B\\ R-Y=0.7010R-0.5870G-0.1140B\\ B-Y=-0.2990R-0.5870G+0.8860B\\ \end{cases} Y=0.2990R+0.5870G+0.1140BRY=0.7010R0.5870G0.1140BBY=0.2990R0.5870G+0.8860B

2、模拟分量

{ P b = 0.564 ( B − Y ) = − 0.1684 R − 0.3316 G + 0.5000 B P r = 0.713 ( R − Y ) = 0.5000 R − 0.4187 G − 0.0813 B \begin{cases} P_b=0.564(B-Y)=-0.1684R-0.3316G+0.5000B\\ P_r=0.713(R-Y)=0.5000R-0.4187G-0.0813B\\ \end{cases} {Pb=0.564(BY)=0.1684R0.3316G+0.5000BPr=0.713(RY)=0.5000R0.4187G0.0813B

3、电平分配

亮度信号

图片来自Endless Ferry

  • Y动态范围为16-235

色度信号

  • Cr、Cb动态范围为16-240

三、实验记录

1、RGB2YUV

自己按照自己理解写的很垃圾的版本,没有用到老师讲的一些知识点(想试来着但是一直出bug),将会在YUV2RGB中继续尝试。

#include<iostream>
#include<math.h>
using namespace std;
int main()
{
    unsigned char* RGB = new unsigned char[256*256*3]; //存储图像所有值
    unsigned char* R = new unsigned char[256*256];
    unsigned char* G = new unsigned char[256*256];
    unsigned char* B = new unsigned char[256*256];
    unsigned char* Y = new unsigned char[256*256]; 
    unsigned char* U = new unsigned char[256*256];
    unsigned char* V = new unsigned char[256*256];


   //读取RGB文件内容
    FILE* fp1=fopen("/Users/hugo/Desktop/数据压缩/第二周/down.rgb","rb");
    if(fp1 == NULL)
        cout<<"错误读取"<<endl;
    fread(RGB,sizeof(unsigned char),256*256*3,fp1);
    fclose(fp1);

    //创建yuv文件
     FILE* data=fopen("/Users/hugo/Desktop/数据压缩/第二周/RGB2YUV.yuv","w");


    //RGB2YUV
    for (int i = 0, j = 0; i < 256*256*3; i += 3, j++) 
    {
		B[j] = RGB[i];
		G[j] = RGB[1 + i];
		R[j] = RGB[2 + i];
		Y[j] = ((66 * R[j] + 129 * G[j] + 25 * B[j]) >> 8) + 16;
		U[j] = ((-38 * R[j] - 74 * G[j] + 112 * B[j])>> 8) + 128;
		V[j] = ((112 * R[j] - 94 * G[j] - 18 * B[j]) >> 8) + 128;
	
    }

    //写入文件
    fwrite(Y,sizeof(unsigned char),256*256,data);
    fwrite(U,sizeof(unsigned char),256*256,data);
    fwrite(V,sizeof(unsigned char),256*256,data);

    //关闭文件
    fclose(data);

    return 0;
}

实验结果
在这里插入图片描述

2、YUV2RGB

# include<iostream>
# include <fstream>
using namespace std;

static int RGB298[256];
static int RGB411[256];
static int RGB101[256];
static int RGB211[256];
static int RGB519[256];

//查找表
void initLookupTable() 
{
	int i;

	for (i = 0; i < 256; i++) RGB298[i] = 298 * i;
	for (i = 0; i < 256; i++) RGB411[i] = 411 * i;
	for (i = 0; i < 256; i++) RGB101[i] = 101 * i;
	for (i = 0; i < 256; i++) RGB211[i] = 211 * i;
	for (i = 0; i < 256; i++) RGB519[i] = 519 * i;

}

void yuv2rgb(unsigned char* YUV_Buffer, unsigned char* RGB_Buffer_out, int size,int width) {
	initLookupTable();
	int uoffset = size;
	int voffset = 1.25 * size;
	
	unsigned char* U_dataExpand = new unsigned char[size];
	unsigned char* V_dataExpand = new unsigned char[size];

	for (int i = 0; i < size/4; i++) {
		unsigned char temp = *(YUV_Buffer + i + uoffset);
		int offset = 2*(i%(width/2))+i/(width/2)*2*width;
		*(U_dataExpand + offset)= temp;
		*(U_dataExpand + offset+1) = temp;
		*(U_dataExpand + offset+width) = temp;
		*(U_dataExpand + offset + 1+width) = temp;

		temp= *(YUV_Buffer + i + voffset);
		*(V_dataExpand + offset) = temp;
		*(V_dataExpand + offset + 1) = temp;
		*(V_dataExpand + offset + width) = temp;
		*(V_dataExpand + offset + 1 + width) = temp;
	}

	for (int i = 0, j = 0; i < size; i++, j += 3) {
		unsigned char Y = *(YUV_Buffer + i);
		unsigned char U = *(U_dataExpand + i);
		unsigned char V = *(V_dataExpand + i);
		int B = (RGB298[Y] + RGB519[U] - 71200) >> 8;
		if (B > 255) B = 255;
		if(B < 0) B = 0;
		int G = (RGB298[Y] - RGB101[U] - RGB211[V] + 35168) >> 8;
		if (G > 255) G = 255;
		if (G < 0) G = 0;
		int R = (RGB298[Y] + RGB411[V] - 57376) >> 8;
		if (R > 255) R = 255;
		if (R < 0) R = 0;
		*(RGB_Buffer_out + j) = (unsigned char)(B);
		*(RGB_Buffer_out + 1 + j) = (unsigned char)(G);
		*(RGB_Buffer_out + 2 + j) = (unsigned char)(R);

	}
	
	
}

int main()
 {
	FILE* originYUV=fopen("/Users/hugo/Desktop/数据压缩/第二周/down.yuv","rb");
	FILE* RGB_out=fopen("/Users/hugo/Desktop/数据压缩/第二周/YUV2RGB.rgb","w");
	if (!originYUV || !RGB_out) {
		cout << "错误读取" << endl;
		return 0;
	}
	int size = 256*256; 
	unsigned char* YUV_Buffer = new unsigned char[size * 1.5];
	unsigned char* RGB_Buffer_out = new unsigned char[size * 3];
    fread((char*)YUV_Buffer,sizeof(unsigned char),size * 1.5,originYUV);

	yuv2rgb(YUV_Buffer,RGB_Buffer_out,size,256);
    fwrite((char*)RGB_Buffer_out,sizeof(unsigned char),size * 3,RGB_out);

	delete[] YUV_Buffer;
	delete[] RGB_Buffer_out;
	fclose(originYUV);
	fclose(RGB_out);

	return 0;
}

实验结果
由于实在没找到mac平台的看rgb文件的软件,所以找同学帮忙打开
在这里插入图片描述

四、反思总结

  • 整体来说自己的编程能力还是较差,且还没弄清楚mac平台的vscode全部功能所以本来想用老师说的命令行参数argc和argv来着还没琢磨出来。
  • 在编程过程中对于U、V格式的扩展和下采样处理方式还是没有太清楚,借鉴学习了Endless Ferry同学文章。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值