颜色空间BGR转YCbCr

    颜色空间系列代码下载链接:http://files.cnblogs.com/Imageshop/ImageInfo.rar (同文章同步更新)

在常用的几种颜色空间中,YCbCr颜色空间在学术论文中出现的频率是相当高的,常用于肤色检测等等。其和RGB空间之间的相互转换公式在网上也有多种,我们这里取http://en.wikipedia.org/wiki/YCbCr 描述的JPG转换时使用的计算公式:

  JPEG conversion

  JFIF usage of JPEG allows Y′CbCr where Y′, CB and CR have the full 8-bit range of 0-255:

  And back:

上述公式的主要优点是转换后的各分量的范围也在0到255之间,因此用 byte类型的变量即可容纳新的颜色空间。

要避免浮点运算带来的速度瓶颈,这里同样可以用 颜色空间系列1: RGB和CIEXYZ颜色空间的转换及相关优化  文章中同样的优化技巧。

为了可以指定位移的大小,我们采用常量的定义方式是计算各放大系数。

        const float YCbCrYRF = 0.299F;              // RGB转YCbCr的系数(浮点类型)const float YCbCrYGF = 0.587F;const float YCbCrYBF = 0.114F;const float YCbCrCbRF = -0.168736F;        const float YCbCrCbGF = -0.331264F;const float YCbCrCbBF = 0.500000F;const float YCbCrCrRF = 0.500000F;const float YCbCrCrGF = -0.418688F;const float YCbCrCrBF = -0.081312F;
    </span><span style="color: #0000ff;">const</span> <span style="color: #0000ff;">float</span> RGBRYF = <span style="color: #800080;">1.00000F</span>;            <span style="color: #008000;">//</span><span style="color: #008000;"> YCbCr转RGB的系数(浮点类型)</span><span style="color: #0000ff;">const</span> <span style="color: #0000ff;">float</span> RGBRCbF = <span style="color: #800080;">0.0000F</span><span style="color: #000000;">;</span><span style="color: #0000ff;">const</span> <span style="color: #0000ff;">float</span> RGBRCrF = <span style="color: #800080;">1.40200F</span><span style="color: #000000;">;</span><span style="color: #0000ff;">const</span> <span style="color: #0000ff;">float</span> RGBGYF = <span style="color: #800080;">1.00000F</span><span style="color: #000000;">;          </span><span style="color: #0000ff;">const</span> <span style="color: #0000ff;">float</span> RGBGCbF = -<span style="color: #800080;">0.34414F</span><span style="color: #000000;">;</span><span style="color: #0000ff;">const</span> <span style="color: #0000ff;">float</span> RGBGCrF = -<span style="color: #800080;">0.71414F</span><span style="color: #000000;">;</span><span style="color: #0000ff;">const</span> <span style="color: #0000ff;">float</span> RGBBYF = <span style="color: #800080;">1.00000F</span><span style="color: #000000;">;          </span><span style="color: #0000ff;">const</span> <span style="color: #0000ff;">float</span> RGBBCbF = <span style="color: #800080;">1.77200F</span><span style="color: #000000;">;</span><span style="color: #0000ff;">const</span> <span style="color: #0000ff;">float</span> RGBBCrF = <span style="color: #800080;">0.00000F</span><span style="color: #000000;">; </span><span style="color: #0000ff;">const</span> <span style="color: #0000ff;">int</span> Shift = <span style="color: #800080;">20</span><span style="color: #000000;">;</span><span style="color: #0000ff;">const</span> <span style="color: #0000ff;">int</span> HalfShiftValue = <span style="color: #800080;">1</span> &lt;&lt; (Shift - <span style="color: #800080;">1</span><span style="color: #000000;">);</span><span style="color: #0000ff;">const</span> <span style="color: #0000ff;">int</span> YCbCrYRI = (<span style="color: #0000ff;">int</span>)(YCbCrYRF * (<span style="color: #800080;">1</span> &lt;&lt; Shift) + <span style="color: #800080;">0.5</span>);         <span style="color: #008000;">//</span><span style="color: #008000;"> RGB转YCbCr的系数(整数类型)</span><span style="color: #0000ff;">const</span> <span style="color: #0000ff;">int</span> YCbCrYGI = (<span style="color: #0000ff;">int</span>)(YCbCrYGF * (<span style="color: #800080;">1</span> &lt;&lt; Shift) + <span style="color: #800080;">0.5</span><span style="color: #000000;">);</span><span style="color: #0000ff;">const</span> <span style="color: #0000ff;">int</span> YCbCrYBI = (<span style="color: #0000ff;">int</span>)(YCbCrYBF * (<span style="color: #800080;">1</span> &lt;&lt; Shift) + <span style="color: #800080;">0.5</span><span style="color: #000000;">);</span><span style="color: #0000ff;">const</span> <span style="color: #0000ff;">int</span> YCbCrCbRI = (<span style="color: #0000ff;">int</span>)(YCbCrCbRF * (<span style="color: #800080;">1</span> &lt;&lt; Shift) + <span style="color: #800080;">0.5</span><span style="color: #000000;">);</span><span style="color: #0000ff;">const</span> <span style="color: #0000ff;">int</span> YCbCrCbGI = (<span style="color: #0000ff;">int</span>)(YCbCrCbGF * (<span style="color: #800080;">1</span> &lt;&lt; Shift) + <span style="color: #800080;">0.5</span><span style="color: #000000;">);</span><span style="color: #0000ff;">const</span> <span style="color: #0000ff;">int</span> YCbCrCbBI = (<span style="color: #0000ff;">int</span>)(YCbCrCbBF * (<span style="color: #800080;">1</span> &lt;&lt; Shift) + <span style="color: #800080;">0.5</span><span style="color: #000000;">);</span><span style="color: #0000ff;">const</span> <span style="color: #0000ff;">int</span> YCbCrCrRI = (<span style="color: #0000ff;">int</span>)(YCbCrCrRF * (<span style="color: #800080;">1</span> &lt;&lt; Shift) + <span style="color: #800080;">0.5</span><span style="color: #000000;">);</span><span style="color: #0000ff;">const</span> <span style="color: #0000ff;">int</span> YCbCrCrGI = (<span style="color: #0000ff;">int</span>)(YCbCrCrGF * (<span style="color: #800080;">1</span> &lt;&lt; Shift) + <span style="color: #800080;">0.5</span><span style="color: #000000;">);</span><span style="color: #0000ff;">const</span> <span style="color: #0000ff;">int</span> YCbCrCrBI = (<span style="color: #0000ff;">int</span>)(YCbCrCrBF * (<span style="color: #800080;">1</span> &lt;&lt; Shift) + <span style="color: #800080;">0.5</span><span style="color: #000000;">);</span><span style="color: #0000ff;">const</span> <span style="color: #0000ff;">int</span> RGBRYI = (<span style="color: #0000ff;">int</span>)(RGBRYF * (<span style="color: #800080;">1</span> &lt;&lt; Shift) + <span style="color: #800080;">0.5</span>);              <span style="color: #008000;">//</span><span style="color: #008000;"> YCbCr转RGB的系数(整数类型)</span><span style="color: #0000ff;">const</span> <span style="color: #0000ff;">int</span> RGBRCbI = (<span style="color: #0000ff;">int</span>)(RGBRCbF * (<span style="color: #800080;">1</span> &lt;&lt; Shift) + <span style="color: #800080;">0.5</span><span style="color: #000000;">);</span><span style="color: #0000ff;">const</span> <span style="color: #0000ff;">int</span> RGBRCrI = (<span style="color: #0000ff;">int</span>)(RGBRCrF * (<span style="color: #800080;">1</span> &lt;&lt; Shift) + <span style="color: #800080;">0.5</span><span style="color: #000000;">);</span><span style="color: #0000ff;">const</span> <span style="color: #0000ff;">int</span> RGBGYI = (<span style="color: #0000ff;">int</span>)(RGBGYF * (<span style="color: #800080;">1</span> &lt;&lt; Shift) + <span style="color: #800080;">0.5</span><span style="color: #000000;">);</span><span style="color: #0000ff;">const</span> <span style="color: #0000ff;">int</span> RGBGCbI = (<span style="color: #0000ff;">int</span>)(RGBGCbF * (<span style="color: #800080;">1</span> &lt;&lt; Shift) + <span style="color: #800080;">0.5</span><span style="color: #000000;">);</span><span style="color: #0000ff;">const</span> <span style="color: #0000ff;">int</span> RGBGCrI = (<span style="color: #0000ff;">int</span>)(RGBGCrF * (<span style="color: #800080;">1</span> &lt;&lt; Shift) + <span style="color: #800080;">0.5</span><span style="color: #000000;">);</span><span style="color: #0000ff;">const</span> <span style="color: #0000ff;">int</span> RGBBYI = (<span style="color: #0000ff;">int</span>)(RGBBYF * (<span style="color: #800080;">1</span> &lt;&lt; Shift) + <span style="color: #800080;">0.5</span><span style="color: #000000;">);</span><span style="color: #0000ff;">const</span> <span style="color: #0000ff;">int</span> RGBBCbI = (<span style="color: #0000ff;">int</span>)(RGBBCbF * (<span style="color: #800080;">1</span> &lt;&lt; Shift) + <span style="color: #800080;">0.5</span><span style="color: #000000;">);</span><span style="color: #0000ff;">const</span> <span style="color: #0000ff;">int</span> RGBBCrI = (<span style="color: #0000ff;">int</span>)(RGBBCrF * (<span style="color: #800080;">1</span> &lt;&lt; Shift) + <span style="color: #800080;">0.5</span>); </pre>

RGB转为YCbCr的代码:

        public static void ToYCbCr(byte* From, byte* To, int Length = 1){if (Length < 1) return;byte* End = From + Length * 3;int Red, Green, Blue;// int Y, Cb, Cr;while (From != End){Blue = *From; Green = *(From + 1); Red = *(From + 2);// 无需判断是否存在溢出,因为测试过整个RGB空间的所有颜色值,无颜色存在溢出*To = (byte)((YCbCrYRI * Red + YCbCrYGI * Green + YCbCrYBI * Blue + HalfShiftValue) >> Shift);     *(To + 1) = (byte)( 128 + ( (YCbCrCbRI * Red + YCbCrCbGI * Green + YCbCrCbBI * Blue + HalfShiftValue) >> Shift));*(To + 2) = (byte) (128+( (YCbCrCrRI * Red + YCbCrCrGI * Green + YCbCrCrBI * Blue + HalfShiftValue) >> Shift));// *To = (byte)Y;          // 不要把直接计算的代码放在这里,会降低速度,//*(To + 1) = (byte)Cb;//*(To + 2) = (byte)Cr;From += 3;To += 3;}}

  被注释掉的代码时原始的,因为这种比较简单的代码,直接对表达式进行强制类型转换比用中间变量要少几条汇编码,并且中间变量越少,在编译后越有可能让CPU用寄存器来缓存一些变量,而不是用内存。

比如我们比较下注释部分和上述代码的反编译码:

注释掉的部分的反编译码:

                Y = (YCbCrYRI * Red + YCbCrYGI * Green + YCbCrYBI * Blue + HalfShiftValue) >> Shift;
0000003a  imul        eax,eax,4C8B4h
00000040  imul        edx,ebx,9645Ah
00000046  add         eax,edx
00000048  imul        edx,edi,1D2F2h
0000004e  lea         eax,[eax+edx+00080000h]
00000055  sar         eax,14h
00000058  mov         dword ptr [ebp-18h],eax *To = (byte)Y;
0000005b  mov         byte ptr [esi],al 

上述代码的反编译码:

  *To = (byte) ( (YCbCrYRI * Red + YCbCrYGI * Green + YCbCrYBI * Blue + HalfShiftValue) >> Shift);
0000003a  imul        eax,ebx,4C8B4h
00000040  imul        edx,edi,9645Ah
00000046  add         eax,edx
00000048  imul        edx,dword ptr [ebp-14h],1D2F2h
0000004f  lea         eax,[eax+edx+00080000h]
00000056  sar         eax,14h
00000059  mov         byte ptr [esi],al 

当然,如果循环中的代码复杂一些,这个就不一定了。

YCbCr转为RGB空间的代码:

        public static void ToRGB(byte* From, byte* To, int Length = 1){if (Length < 1) return;byte* End = From + Length * 3;int Red, Green, Blue;int Y, Cb, Cr;while (From != End){Y = *From; Cb = *(From + 1)-128; Cr = *(From + 2)-128;Red = Y + ((RGBRCrI * Cr + HalfShiftValue) >> Shift);Green = Y + ((RGBGCbI * Cb + RGBGCrI * Cr+ HalfShiftValue) >> Shift);Blue = Y + ((RGBBCbI * Cb + HalfShiftValue) >> Shift);if (Red > 255) Red = 255; else if (Red < 0) Red = 0;if (Green > 255) Green = 255; else if (Green < 0) Green = 0;    // 编译后应该比三目运算符的效率高if (Blue > 255) Blue = 255; else if (Blue < 0) Blue = 0;*To = (byte)Blue;                                               // 由于不是一一对应的,需要判断是否越界*(To + 1) = (byte)Green;*(To + 2) = (byte)Red;From += 3;To += 3;}}

实际中这种逆变换用的不多。

照例给出一些转换效果:

YCbCr综合图:

Y分量:

Cb分量:

Cr分量:

在皮肤识别方面,常用YCbCr空间的数据进行分析,从上面几个图中也可以看出  ,肤色在CbCr有着一定的集聚性,这个在日后的文章中再说。

颜色空间BGR转YCbCr相关推荐

  1. OpenCV颜色空间——BGR颜色空间

    #include<opencv2/core.hpp> #include<opencv2/imgproc.hpp> #include<opencv2/highgui.hpp ...

  2. OpenCV Using Python——HSV颜色空间和改进的YCbCr颜色空间中的肤色检测

    HSV颜色空间中的肤色检测 1. HSV颜色空间的肤色模型简介 Pitas等人提出在HSV空间建立肤色模型.不要求颜色归一化并且对光照鲁棒性很强,条件同时满足才会被分割成皮肤.实现条件如下: 2. 实 ...

  3. Opencv颜色空间转换---BGR和HSV详解

    目录 色彩空间简介 BGR颜色空间 HSV颜色空间 BGR和HSV之间的转换 BGR转HSV HSV转BGR OpenCV中的实现 相关函数说明 BGR2HSV HSV2BGR 实例说明 代码 参考资 ...

  4. Opencv图像处理之改变颜色空间

    本节中,你将学习到 如何改变图像颜色空间 1.如何将图像从一个色彩空间转换到另一个,像BGR-->灰色,BGR-->HSV 等 2.创建应用程序,提取视频中的彩色对象 1.如何将图像从一个 ...

  5. MPEG-7描述子(0)——颜色空间

    RGB 计算机颜色显示器显示颜色的原理与彩色电视机一样,都是采用R.G.B相加混色的原理,通过发射出三种不同强度的电子束,使屏幕内侧覆盖的红.绿.蓝磷光材料发光而产生颜色的.这种颜色的表示方法称为RG ...

  6. 【opencv图像处理】--2. 颜色空间,绘制图形,绘制(中文)文本

    "人群里敞着一扇门" 1. 颜色空间的基础知识 1.1 色彩空间转换 2. mat数据结构的深浅拷贝 ndarray的常见属性 3.颜色通道的分离和合并 4. 绘制图形 5. 绘制 ...

  7. 颜色空间转换RGB-YCbCr

    颜色空间 颜色空间(Color Space)是描述颜色的一种方式,它是一个由数学模型表示的三维空间,通常用于将数字表示的颜色转换成可见的颜色.颜色空间的不同取决于所选的坐标轴和原点,以及用于表示颜色的 ...

  8. OpenCV系列之改变颜色空间 | 十三

    目标 在本教程中,你将学习如何将图像从一个色彩空间转换到另一个,像BGR↔灰色,BGR↔HSV等 除此之外,我们还将创建一个应用程序,以提取视频中的彩色对象 你将学习以下功能:cv.cvtColor, ...

  9. OpenCV中的图像处理 —— 改变颜色空间+图像几何变换

    OpenCV中的图像处理 -- 改变颜色空间+图像几何变换 这一部分主要介绍OpenCV图像处理中的改变颜色空间和图像的几何变换,颜色空间的改变应用非常广泛,在处理图像的实际问题中,经常需要要图像变换 ...

最新文章

  1. python打印浮点数_python怎么输出浮点数
  2. Rhino脚本引擎技术介绍
  3. glance部署及操作
  4. GeneralList-广义表
  5. 滚动字幕Marquee
  6. 你知道哪些情况下不该使用深度学习吗?
  7. Java高并发编程详解系列-JVM类加载器
  8. echart itemStyle属性设置
  9. 找上海或深圳塑胶模具工作
  10. 一个数字几个字节_技术工坊40期-DAG技术特性以及在字节雪球Obyte项目的使用实践...
  11. 1. webpack 复制文件
  12. 2021-04-18
  13. 在 MacOS 上使用 Qt 开发 Android APP
  14. 中兴网络设备交换机路由器查看MC-LAG状态检查命令方法
  15. 产品策划流程体系、工具
  16. 无边无际的虚拟城市来了!能走能飞的Demo,一火再火的“波函数坍缩”开源算法...
  17. [转载]煮酒论英雄nbsp;-nbsp;漫谈Java数据库存取技术
  18. 普通pc电脑安装苹果系统mac_详细教程(精)附带所有工具下载
  19. 大型网站架构设计及技术总结
  20. 十八:享元模式(共享重复对象,分离不同对象)

热门文章

  1. 华为OD机试题:充分发挥GPU算力
  2. 珠心算对小孩用处大吗
  3. 华为oj-名字的漂亮度
  4. Android 实用自定义Dialog页面加载动画
  5. mybatis plus 查询排序,Mybatis Plus带多条件的多表联合、分页、排序查询
  6. 【报错记录】SpringBoot中MultipartFile上传报/tmp/tomcat.***.tmp (No such file or directory)
  7. 开发新产品离不开CRM需求分析
  8. Tableau可视化——超市常见问题分析
  9. Kmeans中的K值选取
  10. 名画377 齐白石《石门二十四景图》