文档章节

颜色空间系列4: RGB和YDbDr颜色空间的转换及优化算法

abcijkxyz
 abcijkxyz
发布于 2016/11/22 16:39
字数 918
阅读 0
收藏 0
点赞 0
评论 0

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

    YDbDr颜色空间和YCbCr颜色空间类似,其和RGB空间之间的相互转换公式里取http://en.wikipedia.org/wiki/YDbDr 所描述的。

     RGB转为YDbDr为:

                             (1)

      对应的YDbDr转换为RGB的公式为:

                       (2)

     由式(1)可知Y的范围是[0,255],Db的范围是[-1.333*255,1.333*255],Dr的范围亦为[-1.333*255,1.333*255]。

     为了使Db,Dr的变换量程也为255-0大小,需要将上述Db/Dr压缩1.333*2倍,即将各系数处理( 1.333*2),得到新的转换: 

   [Y  ]     [0.2990  -0.1688   -0.5000 ]    [R]
     [Db] =   [0.5870     -0.3312    0.4186  ]    [G]      
   [Dr]     [0.1140     0.5000     0.0814   ]    [B]

     对应的逆变换可用matlab求上述矩阵的逆阵即可:

   [R]     [ 1.000000000000000   0.000246081707249  -1.402083073344533 ]    [Y]
     [G] =   [ 1.000000000000000  -0.344268308442098   0.714219609001458 ]    [Db]      
   [B]     [ 1.000000000000000   1.772034373903893  -0.000211153981059 ]    [Dr]

      理论上 YDbDr和RGB之间的转换时完全无损可逆的。不过如果YDbDr采用byte类型表达会有一定的精度损失。

      附上最终的代码供大家参考:

sealed unsafe class RGBYDbDr
    {
        //const float YDbDrYRF = 0.299F;              // RGB转YDbDr的系数(浮点类型)
        //const float YDbDrYGF = 0.587F;
        //const float YDbDrYBF = 0.114F;
        //const float YDbDrDbRF = -0.450F;
        //const float YDbDrDbGF = -0.883F;
        //const float YDbDrDbBF = 1.333F;
        //const float YDbDrDrRF = -1.333F;
        //const float YDbDrDrGF = 1.116F;
        //const float YDbDrDrBF = 0.217F;

        //const float RGBRYF = 1.00000F;            // YDbDr转RGB的系数(浮点类型)
        //const float RGBRDbF = 0.000092303716148F;
        //const float RGBRDrF = -0.525912630661865F;
        //const float RGBGYF = 1.00000F;
        //const float RGBGDbF = -0.129132898890509F;
        //const float RGBGDrF = 0.267899328207599F;
        //const float RGBBYF = 1.00000F;
        //const float RGBBDbF = 0.664679059978955F;
        //const float RGBBDrF = -0.000079202543533F;


        const float YDbDrYRF = 0.299F;              // RGB转YDbDr的系数(浮点类型)
        const float YDbDrYGF = 0.587F;
        const float YDbDrYBF = 0.114F;
        const float YDbDrDbRF = -0.1688F;
        const float YDbDrDbGF = -0.3312F;
        const float YDbDrDbBF = 0.5F;
        const float YDbDrDrRF = -0.5F;
        const float YDbDrDrGF = 0.4186F;
        const float YDbDrDrBF = 0.0814F;

        const float RGBRYF = 1.00000F;            // YDbDr转RGB的系数(浮点类型)
        const float RGBRDbF = 0.0002460817072494899F;
        const float RGBRDrF = -1.402083073344533F;
        const float RGBGYF = 1.00000F;
        const float RGBGDbF = -0.344268308442098F;
        const float RGBGDrF = 0.714219609001458F;
        const float RGBBYF = 1.00000F;
        const float RGBBDbF = 1.772034373903893F;
        const float RGBBDrF = 0.0002111539810593343F;

        const int Shift = 20;
        const int HalfShiftValue = 1 << (Shift - 1);

        const int YDbDrYRI = (int)(YDbDrYRF * (1 << Shift) + 0.5);         // RGB转YDbDr的系数(整数类型)
        const int YDbDrYGI = (int)(YDbDrYGF * (1 << Shift) + 0.5);
        const int YDbDrYBI = (int)(YDbDrYBF * (1 << Shift) + 0.5);
        const int YDbDrDbRI = (int)(YDbDrDbRF * (1 << Shift) + 0.5);
        const int YDbDrDbGI = (int)(YDbDrDbGF * (1 << Shift) + 0.5);
        const int YDbDrDbBI = (int)(YDbDrDbBF * (1 << Shift) + 0.5);
        const int YDbDrDrRI = (int)(YDbDrDrRF * (1 << Shift) + 0.5);
        const int YDbDrDrGI = (int)(YDbDrDrGF * (1 << Shift) + 0.5);
        const int YDbDrDrBI = (int)(YDbDrDrBF * (1 << Shift) + 0.5);

        const int RGBRYI = (int)(RGBRYF * (1 << Shift) + 0.5);              // YDbDr转RGB的系数(整数类型)
        const int RGBRDbI = (int)(RGBRDbF * (1 << Shift) + 0.5);
        const int RGBRDrI = (int)(RGBRDrF * (1 << Shift) + 0.5);
        const int RGBGYI = (int)(RGBGYF * (1 << Shift) + 0.5);
        const int RGBGDbI = (int)(RGBGDbF * (1 << Shift) + 0.5);
        const int RGBGDrI = (int)(RGBGDrF * (1 << Shift) + 0.5);
        const int RGBBYI = (int)(RGBBYF * (1 << Shift) + 0.5);
        const int RGBBDbI = (int)(RGBBDbF * (1 << Shift) + 0.5);
        const int RGBBDrI = (int)(RGBBDrF * (1 << Shift) + 0.5);
public static void ToYDbDr(byte* From, byte* To, int Length = 1)
        {
            if (Length < 1) return;
            byte* End = From + Length * 3;
            int Red, Green, Blue;
            while (From != End)
            {
                Blue = *From; Green = *(From + 1); Red = *(From + 2);
                // 无需判断是否存在溢出,因为测试过整个RGB空间的所有颜色值,无颜色存在溢出
                *To = (byte)((YDbDrYRI * Red + YDbDrYGI * Green + YDbDrYBI * Blue + HalfShiftValue) >> Shift);         // YDbDr和YUV的Y相同
                *(To + 1) = (byte)(128 + ((YDbDrDbRI * Red + YDbDrDbGI * Green + YDbDrDbBI * Blue + HalfShiftValue) >> Shift));     
                *(To + 2) = (byte)(128 + ((YDbDrDrRI * Red + YDbDrDrGI * Green + YDbDrDrBI * Blue + HalfShiftValue) >> Shift));     
                From += 3;
                To += 3;
            }
        }

        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, Db, Dr;
            while (From != End)
            {
                Y = *From; Db = *(From + 1) - 128; Dr = *(From + 2) - 128;
                Red = Y + ((RGBRDbI * Db + RGBRDrI * Dr + HalfShiftValue) >> Shift);
                Green = Y + ((RGBGDbI * Db + RGBGDrI * Dr + HalfShiftValue) >> Shift);
                Blue = Y + ((RGBBDbI * Db + RGBBDrI * Dr + 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;
            }
        }
    }

  由于有些转换系数很小,建议Shift 常数取值不得小于10,否则会有更多的损失。

     照例附上一些效果:

     原图:

    

    YDbDr综合效果图:

    

    Y通道图:

    

    Db通道:

    

    Dr通道:

    

本文转载自:http://www.cnblogs.com/Imageshop/archive/2013/02/15/2912907.html

共有 人打赏支持
abcijkxyz
粉丝 60
博文 6196
码字总数 1876
作品 0
深圳
项目经理
将RGB值转换为灰度值的简单算法

原文地址:点击打开链接 RGB是如何转换为灰度的?这是让人困惑已久的一道难题 1、RGB复合通道转灰度:转换后的色阶值只与RGB空间有关,而与作为目的地的灰度空间无关。也就是说,只要当前的R...

floatdreamed
01/09
0
0
YUV / RGB 格式分析及快速查表算法设计

1 前言 自然界的颜色千变万化,为了给颜色一个量化的衡量标准,就需要建立色彩空间模型来描述各种各样的颜色,由于人对色彩的感知是一个复杂的生理和心理联合作用的过程,所以在不同的应用领...

鉴客
2011/10/01
389
0
颜色空间:RGB,CMY,HSV,HSL,Lab详解

颜色空间(彩色模型、色彩空间、 彩色系统etc)是对色彩的一种描述方式,定义有很多种,区别在于面向不同的应用背景。 例如显示器中采用的RGB颜色空间是基于物体发光定义的(RGB正好对应光的...

li_wen01
2017/06/05
0
0
RGB和YUV的转换与区别

YUV与RGB互转各种公式- http://www.cnblogs.com/luoyinjie/p/7219319.html > YUV YUV是被欧洲电视系统所采用的一种颜色编码方法(属于PAL),是PAL和SECAM模拟彩色电视制式采用的颜色空间。在...

shareus
2017/11/12
0
0
【Python+OpenCV】实现RGB转HSI

cv2.cvtColor函数封装了各种颜色空间之间的转换,唯独没有RGB与HSI之间的转换,网上查来查去也只有C++或MATLAB版本的,自己要用到python里,所以就写写python版本的。 HSI颜色模型是一个满足...

lwplwf
2017/08/23
0
0
视频监控之颜色模型——RGB、HSV模型

目前常用的颜色模型可分为两类,一类面向诸如彩色显示器或打印机之类的硬件设备,另一类面向以彩色处理为目的的应用,如动画中的彩色图形。面向硬件设备的最常用彩色模型是 RGB 模型,而面向...

小薇
2013/03/01
0
0
8- OpenCV+TensorFlow 入门人工智能图像处理-浮雕效果&油画效果

浮雕效果 浮雕效果与边缘检测类似,也是计算梯度的一个过程 计算公式: 加上150是为了增强图片的浮雕灰度等级。 相邻像素相减,是为了突出灰度的突片。边缘特征。 代码实现 150就是当前的灰度值...

天涯明月笙
05/07
0
0
老旧黑白片修复机——使用卷积神经网络图像自动着色实战(附PyTorch代码)

摘要: 照片承载了很多人在某个时刻的记忆,尤其是一些老旧的黑白照片,尘封于脑海之中,随着时间的流逝,记忆中对当时颜色的印象也会慢慢消散,这确实有些可惜。技术的发展会解决一些现有的...

阿里云云栖社区
06/04
0
0
使用QT5绘制OpenCV3的Mat图像

QT在跨平台编程中应用越来越广泛,C++中用跨平台开发界面(包括嵌入式设备),QT基本成为第一选择,OpenCV从3.0开始已经慢慢抛弃了过去的C接口,统一改为C++接口,存储图像的IplImage也在被M...

夏曹俊
2017/05/11
0
0
解决问题的艺术:半小时编程实现照片的反转负冲特效

如何直接有效的解决问题是一门艺术。我们是做产品、做系统、做服务的,不是玩技术的,需要做的是在最短的时间内以最有效的方式来解决工作中面对的难题。就在刚才,用了半小时不到时间,俺用一...

最美的回忆
2017/03/06
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

Weblogic问题解决记录

问题:点击登录,页面刷新但是不进去管理界面。解决:删除cookies再登录。

wffger
23分钟前
0
0
RxJava2的错误处理方案

最近使用retrofit2 + rxKotlin2写接口访问,想尽量平铺代码,于是就想到当借口返回的状态码为「不成功」时(比如:code != 200),就连同网络错误一起,统一在onError方法中处理。想法总是好的...

猴亮屏
31分钟前
0
0
程序的调试信息

调试二进制程序时,经常要借助GDB工具,跟踪程序的执行流程,获取程序执行时变量的值,以发现问题所在。GDB能得到这些信息,是因为编译程序时,编译器保存了相应的信息。Linux下的可执行程序...

qlee
54分钟前
0
0
应用级缓存

缓存命中率 从缓存中读取数据的次数与总读取次数的比例,命中率越高越好 java缓存类型 堆缓存 guavaCache Ehcache3.x 没有序列化和反序列化 堆外缓存ehcache3.x 磁盘缓存 存储在磁盘上 分布式...

writeademo
今天
0
0
python爬虫日志(3)find(),find_all()函数

1.一般来说,为了找到BeautifulSoup对象内任何第一个标签入口,使用find()方法。 以上代码是一个生态金字塔的简单展示,为了找到第一生产者,第一消费者或第二消费者,可以使用Beautiful Sou...

茫羽行
今天
0
0
java:thread:顺序执行多条线程

实现方案: 1.调用线程的join方法:阻塞主线程 2.线程池 package com.java.thread.test;public class MyThread01 implements Runnable {@Overridepublic void run() {Syste...

人觉非常君
今天
0
0
ElasticSearch 重写IK分词器源码设置mysql热词更新词库

常用热词词库的配置方式 1.采用IK 内置词库 优点:部署方便,不用额外指定其他词库位置 缺点:分词单一化,不能指定想分词的词条 2.IK 外置静态词库 优点:部署相对方便,可以通过编辑指定文...

键走偏锋
今天
19
0
Git 2.18版本发布:支持Git协议v2,提升性能

Git 2.18版本发布:支持Git协议v2,提升性能Git 2.18版本发布:支持Git协议v2,提升性能 新版本协议的主要驱动力是使 Git 服务端能够对各种 ref(分支与 tag)进行过滤操作。 这就意味着,G...

linux-tao
今天
0
0
python浏览器自动化测试库【2018/7/22-更新】

64位py2.7版本 更新 document_GetResources 枚举页面资源 document_GetresourceText 获取指定url的内容 包括页面图片 下载地址下载地址 密码:upr47x...

开飞色
今天
44
0
关于DCL双重锁失效及解决方案

关于DCL双重锁失效及解决方案 Double Check Lock (DCL)实现单例 DCL 方式实现单例的优点是既能够在需要时才初始化单例,又能够保证线程安全,且单例对象初始化后调用getInstance方法不进行...

DannyCoder
今天
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部