实验一:彩色空间转换(YUV2RGB)
#ifndef/#define/#endif 使用详解:http://blog.csdn.net/abc5382334/article/details/18052757
Debug与Release版本的区别详解:http://blog.csdn.net/ithzhang/article/details/7575483#comments
VS中Release和Debug模式的区别:http://blog.csdn.net/eric491179912/article/details/6154375
YUV格式分析:http://www.cnblogs.com/armlinux/archive/2012/02/15/2396763.html
一、实验基本原理
1. 彩色空间转换的基本思想及转换公式
(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-0.5之间,需要进行归一化,对色差信号引入压缩系数,归一化后的色差信号为:
U = - 0.1684 R - 0.3316 G + 0.5 B
V = 0.5 R - 0.4187 G - 0.0813 B
(2) 码电平分配及数字表达式
亮电平信号:在对分量信号进行8比特均匀量化时,共分为256个等间隔的量化级。为了防止信号变动造成过载,在256级上端留20级,下端留16级作为信号超越动态范围的保护带。
色差信号:量化后码电平分配色差信号经过归一化处理后,动态范围为-0.5-0.5,让色差零电平对应码电平128,色差信号总共占225个量化级。在256级上端留15级,下端留16级作为信号超越动态范围的保护带。
由此可知,YUV转RGB公式为:
R = Y + 1.4075 *(V-128)
G = Y– 0.3455 *(U–128) – 0.7169 *(V–128)
B = Y + 1.779 *(U–128)
(3) 色度格式
4:2:0格式:色差信号U,V的取样频率为亮度信号取样频率的四分之一,在水平方向和垂直方向上的取样点数均为Y的一半。
所以:
RGB转换YUV格式时,根据公式计算得到一帧Y、U、V数据后,要对色差信号U、V进行下采样。
YUV转换RGB格式时,在利用公式进行计算之前首先要对色差信号U、V进行上采样。(下面是两张丑丑的图示~)
二、实验流程
1. 建立工程,C相关知识回顾(养成良好代码书写习惯)
1) 程序文件一般分为三部分:
(1)头文件:包括与结构(类)的声明和使用这些结构(类)的函数的原型,不要将函数的定义或变量的声明放在头文件中,#ifndef/#define/#endif 防止头文件被多次引用,详解见文章头部链接。
(2)源代码文件:包含与结构(类)有关的函数的代码,即函数的定义
(3)源代码文件(main.c/cpp):包含调用这些函数的代码
2) 学会使用带参主函数定义以及命令参数、可执行文件工作路径的设置
VS2013步骤为:项目→项目属性→配置属性→调试→命令参数(编辑)/工作目录(编辑:绝对路径/浏览:找到具体文件夹目录)如下图:
关于参数设置过程中Debug与Release版本的区别详解链接见文章头部链接。
2. 调试RGB转换YUV程序
理解课上所给例程,尤其对色差信号进行4:2:0下采样部分,妙用指针可以很容易实现,在课程作业编写YUV转换RGB程序中对U、V数据进行上采样也是借鉴了例程的指针用法。
3. 编写YUV转换RGB程序,具体见下一部分。
三、关键代码
#include "stdlib.h"
#include "yuv2rgb.h"
/*YUV->RGB 转换公式
R = Y + 1.4075 *(V-128)
G = Y – 0.3455 *(U –128) – 0.7169 *(V –128)
B = Y + 1.779 *(U – 128)
*/
static float YUV2RGB14075[256];
static float YUV2RGB03455[256], YUV2RGB07169[256];
static float YUV2RGB1779[256];/************************************************************************
*
* int YUV2RGB (int x_dim, int y_dim, void *ychunk, void *uchunk, void *vchunk, void *rgb_out, int flip)
*
* Purpose : It takes a YUV (4:2:0) format and convert it into
* a 24-bit RGB bitmap.
*
* Input : x_dim the x dimension of the bitmap
* y_dim the y dimension of the bitmap*
* yuv chunk pointer to the YUV structurergb_out pointer to the buffer of the bitmap
*
* Output : 0 OK
* 1 wrong dimension
* 2 memory allocation error
*
* Side Effect :
* None
*
* Date : 03/11/2017
*
************************************************************************/int YUV2RGB(int x_dim, int y_dim, void *ychunk, void *uchunk, void *vchunk, void *rgb_out, int flip)
{ static int init_done = 0;long i, j, size;unsigned char *r, *g, *b;unsigned char *y, *u, *v;unsigned char *pu1, *pu2, *pv1, *pv2, *psu, *psv; unsigned char *addu_buffer, *addv_buffer;unsigned char *addu_buf, *addv_buf;if (init_done == 0){InitLookupTable();init_done = 1;}// check to see if x_dim and y_dim are divisible by 2if ((x_dim % 2) || (y_dim % 2)) return 1;size = x_dim * y_dim;// allocate memory addu_buffer = (unsigned char *)malloc(size * sizeof(unsigned char));addv_buffer = (unsigned char *)malloc(size * sizeof(unsigned char));b = (unsigned char *)rgb_out;y = (unsigned char *)ychunk; u = (unsigned char*)uchunk;v = (unsigned char*)vchunk;addu_buf = (unsigned char *)addu_buffer;addv_buf = (unsigned char *)addv_buffer;// 对UV块进行上采样for (j = 0; j < y_dim/2; j++){psu = u + j * x_dim / 2;//原始数据U块指针psv = v + j * x_dim / 2;//原始数据V块指针pu1 = addu_buf + 2 * j * x_dim; //U块奇数行首地址pu2 = addu_buf + (2 * j + 1) * x_dim;//U块偶数行首地址pv1 = addv_buf + 2 * j * x_dim; //V块奇数行首地址pv2 = addv_buf + (2 * j + 1) * x_dim;//V块偶数行首地址for (i = 0; i < x_dim/2; i++){*pu1 = *psu;*pu2 = *psu;pu1++;pu2++;*pu1 = *psu;*pu2 = *psu; //U块上采样:“以1作4”*pv1 = *psv;*pv2 = *psv; pv1++;pv2++; *pv1 = *psv;*pv2 = *psv; //V块上采样:“以1作4”pu1++;pu2++;pv1++;pv2++;psu++;psv++; }} // convert YUV to RGBif (!flip) {for (j = 0; j < y_dim; j++){y = y + (y_dim - j - 1) * x_dim;addu_buf = addu_buf + (y_dim - j - 1) * x_dim;addv_buf = addv_buf + (y_dim - j - 1) * x_dim;for (i = 0; i < x_dim; i++) {g = b + 1;r = b + 2;adjust(b, g, r, y, addu_buf, addv_buf);b += 3;y++;addu_buf++;addv_buf++;}}}else { for (i = 0; i < size; i++){g = b + 1;r = b + 2;adjust(b, g, r, y, addu_buf, addv_buf);//对变量范围作适应性调整b += 3;y++;addu_buf++;addv_buf++;}}free(addu_buffer);free(addv_buffer);return 0;
}
void InitLookupTable()
{int i;for (i = 16; i < 240; i++) YUV2RGB14075[i] = (float)1.4075 * (i-128);for (i = 16; i < 240; i++) YUV2RGB03455[i] = (float)0.3455 * (i - 128);for (i = 16; i < 240; i++) YUV2RGB07169[i] = (float)0.7169 * (i - 128);//for (i = 16; i < 240; i++) YUV2RGB1779[i] = (float)1.779 * (i-128);
}
void adjust(unsigned char *b, unsigned char *g, unsigned char *r, unsigned char *y, unsigned char *u, unsigned char *v)
{float temp = 0;temp = (float)(*y + YUV2RGB1779[*u]);temp = temp>255 ? 255 : temp;temp = temp<0 ? 0 : temp;*b = (unsigned char)temp;temp = (float)(*y - YUV2RGB03455[*u] - YUV2RGB07169[*v]);temp = temp>255 ? 255 : temp;temp = temp<0 ? 0 : temp;*g = (unsigned char)temp;temp = (float)(*y + YUV2RGB14075[*v]);temp = temp>255 ? 255 : temp;temp = temp<0 ? 0 : temp;*r = (unsigned char)temp;
}
四、程序分析
①RGB格式裸数据部分,三通道的排列顺序依次是B\G\R,所以一个像素点有三个分别表示颜色的数据。
② YUV格式通常有两大类:
打包(packed)格式:将YUV分量存放在同一个数组中,通常是几个相邻的像素组成一个宏像素(macro-pixel);
平面(planar)格式:使用三个数组分开存放YUV三个分量,就像是一个三维平面一样。
下面是我们测试所用RGB与YUV文件的两张丑丑的排列简示图~
依次是B G R B G R.........
每帧数据Y U V分块排列......
程序实现过程:
1. 主程序实现对YUV视频逐帧读取数据分别处理,根据格式特点,开辟三个缓存分别存放YUV三个分量各自的数据。
2. 关键函数首先对U\V色差信号作上采样,下采样过程中相邻四个数据取平均得到一个U/V,所以上采样我们这里相应地就可以->以1代4。
3. 接着就是带入公式计算,依然使用查找表的方法,重点注意强制类型转换过程,在void adjust(~~~)函数中实现,超出0~255范围内的rgb值, 负数取0,大于255的取255。
4. 最后按照存储格式写入文件。
五、实验结果
(所有YUV测试文件均来自网站:http://trace.eas.asu.edu/yuv/index.html)
1. 如何检验程序结果是否正确:
由于RGB的裸数据并不构成文件格式,所以我们的YUV视频通过程序转换成RGB文件以后,再用RGB2YUV程序转换成YUV格式文件,用YUV播放 器查看,对比前后两个视频图像画面,若有明显色调失真或不明色块之类则表明程序出错。
2. 下面是这次实验程序编写过程中出现的错误整理:
①程序结果出错:
测试得到上图结果时,首先注意到明显的蓝红色块,猜测是公式计算过程中强制类型转换错误,老师上课也提醒过,查阅相关书籍得到C语言各种数据类型大小范围如下图:
改正: 将公式计算和强制类型转换过程另写函数,将计算所得结果在unsignedchar类型 0~255范围之外的再次处理。
②程序运行报错:program received signal SIGSEGV,Segmentationfault.
通过相关搜索以及不断改正调试发现,出现这种错误的原因是因为声明指针后没有初始化,指针指向地址为未知,未初始化指针直接执行运算就会出错。
改正:程序中声明的指针初始化。
③程序本身错误:对比差错图像与原图像具体差异:
下面是一组结果图:
蓝红色块错误处理完之后,得到的图像还是不对,但对于错误原因不是很清楚,于是再次进行各种测试。
看上去好像是色调改变了
继续测试
。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
还好找到了这个颜色丰富亮丽的YUV,帮了大忙
似曾相识的竖条色彩分界
。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
所以这应该是发生了某部分数据的位置偏移,问题应该出现在有关数据计算部分。
于是重新查看程序,在直接得到数据的计算过程和U/V色差信号的上采样两部分仔细排查,最终发现错误出现采样程序部分的指针使用。
错误:程序中指针psu\psv多进行了一次偏移超出数据范围。
上采样部分正确代码已经在上面程序部分给出,指针使用图示如下:
指针简图(V同理):
以上错误改正以后再次进行多次测试,结果表明程序运行结果正确。
test 1----
test 2----
test 3----
五、结论
掌握指针运算很重要,会使程序变的简单。
tips/2017/04/30:对于人眼来说,亮度信号是最敏感的,如果将彩色图像转换为灰度图像,仅仅需要转换保存亮度信号就可以。
YUV官方播放器的注册方法:
官方提供注册码:
REGEDIT4
[HKEY_CURRENT_USER\Software\tihohod.com\YUVPlayer\RegistrationInfo]
"RegistrationName"="Peace on Earth -Goodwill to Men"
"RegistrationKey"="JxsQHEseR43VXvp6kCV8w5ACtqNVJ11LhOAE4Pztk+Ksw211wohNjsR78XHoGajwlqIOU6gVz0zipwkJCfdvIqyAJrEgJLYB+NKwPGaD+OqbJD+oe+5xixyIKc7tT0ecQjNER47sA3HsUUhRl3LmKozxS2nH233WNPpJwoF4rL1Bjm5OfcM/jiixF/By85wQTdzSwAehjfvB7iO9tCaI9A=="
把上面key的内容复制到一个编辑器,另存为key.reg,点击运行这个文件会自动注册,就OK了
实验一:彩色空间转换(YUV2RGB)相关推荐
- 实验一 |彩色空间rgb和yuv的相互转换
彩色空间转换 一.实验目的 1.基本要求:编写RGB转化为YUV程序,重点掌握函数定义,部分查找表的初 始化和调用,缓冲区分配.将得到的RGB文件转换为YUV文件,用YUV Viewer播放器观 看, ...
- 彩色图像处理 彩色空间转换及代码实现
一.彩色图像基础 为什么要研究彩色图像处理? 符合人类视觉特点:人类可以辨别几千种颜色色调和亮度:只能辨别几十种灰度层次. 有用的描绘子:简化目标物的区分:目标识别,根据目标的颜色特征. 彩色图像处理 ...
- Python实现数字图像处理之5种彩色空间转换(单图+多图+视频)
本文主要运用用Python代码实现了5种彩色空间之间的转换! 具体而言,包括: 1)RGB → CMY: 2) CMY → RGB: 3) RGB → HSI: 4) HSI → RGB: 5) ...
- 与设备无关的彩色空间
文章目录 一.CIE 和 sRGB彩色空间转换 二.ICC 彩色剖面 CIE Lab 彩色空间:是在色彩科学.创造艺术和诸如打印机.摄像机和扫描仪之类的彩色设备的设计中广泛应用的彩色空间 优点: L ...
- 【学习 OpenCV】—— 将一个3通道的像素点转换到新的彩色空间
将一个3通道的像素点,cv::Vec<uchar, 3> target,转换到新的彩色空间,比如 Lab 彩色空间. 因为封装好的 api cv::cvtColor() 处理的对象是 cv ...
- (四)使用OpenCV实现图像彩色模型转换
(四)使用OpenCV实现图像彩色模型转换 全文介绍部分引自<数字图像处理>第六章 1.彩色基础 彩色光在电磁波中的波长范围是400-700nm.人眼中的锥状体负责色觉的感知,实验发现,人 ...
- 彩色空间(Color Space)
背景 学习openCV-Python Tutorial,在Image Processing in OpenCV这一节里有提到彩色空间的转换,结合其他的一些资料对彩色空间(Color Space),彩色 ...
- 数字图像处理实验之彩色图像处理
数字图像处理_彩色图像处理 1. 实验目的 2. 实验流程 2.1 彩色图像基本操作 2.2 伪彩色处理 2.3 彩色图像平滑滤波 2.4 RGB转HSI 3. 实验代码 3.1 彩色图像读取.显示与 ...
- 基于OpenCV的彩色空间互转
Datawhale干货 作者:姚童,Datawhale优秀学习者 图像彩色空间互转在图像处理中应用非常广泛,而且很多算法只对灰度图有效:另外,相比RGB,其他颜色空间(比如HSV.HSI)更具可分离性 ...
最新文章
- android.mk 里面内容介绍
- Jackson 配置 ObjectMapper
- numpy基础(part4)--统计量
- 语句 查询每个人每个科目的最高分_转行数据分析师专栏(SQL篇)-05多表查询...
- MyEclipse2014配置Git
- c语言学习-定义并调用函数求两个整数之差的绝对值
- 给MTL库添加求行列式值
- ubuntu 14.04 install teamviewer
- java acr122 读取数据_acr122读写器软件下载-Acr122读写软件 1.59 官方版 - 河东下载站...
- gitbook 插件 图片查看
- K3CLOUD业务系统编码规则设置
- solr面试题_查看您的Solr缓存大小:Eclipse Memory Analyzer
- ie浏览器怎么打开html,IE浏览器无法打开网页如何解决
- 宏程序编程实例,简单易懂
- [渝粤教育] 南京森林警察学院 森林植物识别技术 ——珍稀植物识别 参考 资料
- 【PS图像处理】修改图层中文字图形的颜色
- No JSON object could be decoded
- 2019最新黑客风云VIP 网站攻防安全课程(完整)
- 奥迪A6(C5)遥控器钥匙更换电池后无法使用的适配(对码)方法
- 【2020-11-26】不扣JS系列之某医保服务平台数据获取