实验一:彩色空间转换

#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)   YUVRGB空间的相互转换

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.50.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.50.5,让色差零电平对应码电平128,色差信号总共占225个量化级。在256级上端留15级,下端留16级作为信号超越动态范围的保护带。

由此可知,YUVRGB公式为:

                          R = Y + 1.4075 *V-128

G = Y 0.3455 *U128) – 0.7169 *V128

B = Y + 1.779 *U128

(3)   色度格式

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

所以:

RGB转换YUV格式时,根据公式计算得到一帧YUV数据后,要对色差信号UV进行下采样。

YUV转换RGB格式时,在利用公式进行计算之前首先要对色差信号UV进行上采样。(下面是两张丑丑的图示~)



二、实验流程

1.    建立工程,C相关知识回顾(养成良好代码书写习惯)

1)     程序文件一般分为三部分:

(1)头文件:包括与结构(类)的声明和使用这些结构(类)的函数的原型,不要将函数的定义或变量的声明放在头文件中,#ifndef/#define/#endif 防止头文件被多次引用,详解见文章头部链接。

(2)源代码文件:包含与结构(类)有关的函数的代码,即函数的定义

(3)源代码文件(main.c/cpp):包含调用这些函数的代码

2)     学会使用带参主函数定义以及命令参数、可执行文件工作路径的设置

VS2013步骤为:项目项目属性配置属性调试命令参数(编辑)/工作目录(编辑:绝对路径/浏览:找到具体文件夹目录)如下图:


      

        关于参数设置过程中DebugRelease版本的区别详解链接见文章头部链接。


2.    调试RGB转换YUV程序

理解课上所给例程,尤其对色差信号进行4:2:0下采样部分,妙用指针可以很容易实现,在课程作业编写YUV转换RGB程序中对UV数据进行上采样也是借鉴了例程的指针用法。

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)相关推荐

  1. 实验一 |彩色空间rgb和yuv的相互转换

    彩色空间转换 一.实验目的 1.基本要求:编写RGB转化为YUV程序,重点掌握函数定义,部分查找表的初 始化和调用,缓冲区分配.将得到的RGB文件转换为YUV文件,用YUV Viewer播放器观 看, ...

  2. 彩色图像处理 彩色空间转换及代码实现

    一.彩色图像基础 为什么要研究彩色图像处理? 符合人类视觉特点:人类可以辨别几千种颜色色调和亮度:只能辨别几十种灰度层次. 有用的描绘子:简化目标物的区分:目标识别,根据目标的颜色特征. 彩色图像处理 ...

  3. Python实现数字图像处理之5种彩色空间转换(单图+多图+视频)

    本文主要运用用Python代码实现了5种彩色空间之间的转换! 具体而言,包括: 1)RGB → CMY: 2)  CMY → RGB: 3)  RGB → HSI: 4)  HSI → RGB: 5) ...

  4. 与设备无关的彩色空间

    文章目录 一.CIE 和 sRGB彩色空间转换 二.ICC 彩色剖面 CIE Lab 彩色空间:是在色彩科学.创造艺术和诸如打印机.摄像机和扫描仪之类的彩色设备的设计中广泛应用的彩色空间 优点: L ...

  5. 【学习 OpenCV】—— 将一个3通道的像素点转换到新的彩色空间

    将一个3通道的像素点,cv::Vec<uchar, 3> target,转换到新的彩色空间,比如 Lab 彩色空间. 因为封装好的 api cv::cvtColor() 处理的对象是 cv ...

  6. (四)使用OpenCV实现图像彩色模型转换

    (四)使用OpenCV实现图像彩色模型转换 全文介绍部分引自<数字图像处理>第六章 1.彩色基础 彩色光在电磁波中的波长范围是400-700nm.人眼中的锥状体负责色觉的感知,实验发现,人 ...

  7. 彩色空间(Color Space)

    背景 学习openCV-Python Tutorial,在Image Processing in OpenCV这一节里有提到彩色空间的转换,结合其他的一些资料对彩色空间(Color Space),彩色 ...

  8. 数字图像处理实验之彩色图像处理

    数字图像处理_彩色图像处理 1. 实验目的 2. 实验流程 2.1 彩色图像基本操作 2.2 伪彩色处理 2.3 彩色图像平滑滤波 2.4 RGB转HSI 3. 实验代码 3.1 彩色图像读取.显示与 ...

  9. 基于OpenCV的彩色空间互转

    Datawhale干货 作者:姚童,Datawhale优秀学习者 图像彩色空间互转在图像处理中应用非常广泛,而且很多算法只对灰度图有效:另外,相比RGB,其他颜色空间(比如HSV.HSI)更具可分离性 ...

最新文章

  1. android.mk 里面内容介绍
  2. Jackson 配置 ObjectMapper
  3. numpy基础(part4)--统计量
  4. 语句 查询每个人每个科目的最高分_转行数据分析师专栏(SQL篇)-05多表查询...
  5. MyEclipse2014配置Git
  6. c语言学习-定义并调用函数求两个整数之差的绝对值
  7. 给MTL库添加求行列式值
  8. ubuntu 14.04 install teamviewer
  9. java acr122 读取数据_acr122读写器软件下载-Acr122读写软件 1.59 官方版 - 河东下载站...
  10. gitbook 插件 图片查看
  11. K3CLOUD业务系统编码规则设置
  12. solr面试题_查看您的Solr缓存大小:Eclipse Memory Analyzer
  13. ie浏览器怎么打开html,IE浏览器无法打开网页如何解决
  14. 宏程序编程实例,简单易懂
  15. [渝粤教育] 南京森林警察学院 森林植物识别技术 ——珍稀植物识别 参考 资料
  16. 【PS图像处理】修改图层中文字图形的颜色
  17. No JSON object could be decoded
  18. 2019最新黑客风云VIP 网站攻防安全课程(完整)
  19. 奥迪A6(C5)遥控器钥匙更换电池后无法使用的适配(对码)方法
  20. 【2020-11-26】不扣JS系列之某医保服务平台数据获取

热门文章

  1. 视频编码器接入指挥调度平台的一种可行方法
  2. Hibernate:DisjunctionConjunction构造复杂的查询条件.
  3. JPA与Hibernate的区别
  4. Python数据可视化之随机点图
  5. 统计各个分数段的人数python_怎么利用Excel统计各分数段的人数
  6. 前端vue方法导出为xsml
  7. 学会读懂 MySql 的慢查询日志
  8. 将某个GitLab上的项目同步到另一个GitLab
  9. redis 基础数据类型及应用 1
  10. Typecho炫彩鼠标插件:HoerMouse