这个RGB到XYZ颜色空间转换算法有什么问题? [英] What's wrong with this RGB to XYZ color space conversion algorithm?

查看:213
本文介绍了这个RGB到XYZ颜色空间转换算法有什么问题?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的目标是将RGB像素转换为CIELab色彩空间,以便仅在CIELab中进行某些特殊计算。为此,我必须首先将RGB转换为XYZ,这是非常困难的部分。

My goal is to convert an RGB pixel into CIELab color space for some special calculations only possible in CIELab. For this, I must convert RGB to XYZ first, which is the really hard part.

我试图在Objective-C中实现这个算法,但结果是错误的。

I tried to implement this algorithm in Objective-C (mostly using plain C though), but the results are wrong.

我的代码是基于 easyrgb.com 。他们有一个在线颜色转换器工作伟大。

My code is based on the pseudo-implementation provided by easyrgb.com. They have an online-color-converter which works great. They say that their pseudo-code is the same one used in their converter.

这是他们的伪代码:

var_R = ( R / 255 )        //R from 0 to 255
var_G = ( G / 255 )        //G from 0 to 255
var_B = ( B / 255 )        //B from 0 to 255

if ( var_R > 0.04045 ) var_R = ( ( var_R + 0.055 ) / 1.055 ) ^ 2.4
else                   var_R = var_R / 12.92
if ( var_G > 0.04045 ) var_G = ( ( var_G + 0.055 ) / 1.055 ) ^ 2.4
else                   var_G = var_G / 12.92
if ( var_B > 0.04045 ) var_B = ( ( var_B + 0.055 ) / 1.055 ) ^ 2.4
else                   var_B = var_B / 12.92

var_R = var_R * 100
var_G = var_G * 100
var_B = var_B * 100

//Observer. = 2°, Illuminant = D65
X = var_R * 0.4124 + var_G * 0.3576 + var_B * 0.1805
Y = var_R * 0.2126 + var_G * 0.7152 + var_B * 0.0722
Z = var_R * 0.0193 + var_G * 0.1192 + var_B * 0.9505

这是我尝试在Objective-C / C :

This is my attempt to implement it in Objective-C / C:

void convertRGBtoXYZ(NSInteger * inR, NSInteger * inG, NSInteger * inB, CGFloat * outX, CGFloat * outY, CGFloat * outZ) {
    // http://www.easyrgb.com/index.php?X=MATH&H=02#text2

    CGFloat var_R = (*inR / 255); //R from 0 to 255
    CGFloat var_G = (*inG / 255); //G from 0 to 255
    CGFloat var_B = (*inB / 255); //B from 0 to 255

    if (var_R > 0.04045f) {
        var_R = powf(( (var_R + 0.055f) / 1.055f), 2.4f);
    } else {
        var_R = var_R / 12.92f;
    }

    if (var_G > 0.04045) {
        var_G = powf(( (var_G + 0.055f) / 1.055f), 2.4f);
    } else {
        var_G = var_G / 12.92f;
    }

    if (var_B > 0.04045f) {
        var_B = powf(( (var_B + 0.055f) / 1.055f), 2.4f);
    } else {
        var_B = var_B / 12.92f;
    }

    var_R = var_R * 100;
    var_G = var_G * 100;
    var_B = var_B * 100;

    //Observer. = 2°, Illuminant = D65
    *outX = var_R * 0.4124f + var_G * 0.3576f + var_B * 0.1805f;
    *outY = var_R * 0.2126f + var_G * 0.7152f + var_B * 0.0722f;
    *outZ = var_R * 0.0193f + var_G * 0.1192f + var_B * 0.9505f;
}

但是,我没有得到与他们的工具观察者和照明设置)。

However, I don't get the same results as their tool (with same Observer and Illuminant setting).

在我的测试中,我将这些值输入到他们的工具中,得到了XYZ的结果,这远离我的实现产生的RGB值。请参阅屏幕截图:

In my test, I entered these values into their tool and got this result for XYZ which is far off from what my implementation produces for that RGB value. Please see screenshot:

得到的Lab颜色值非常接近Photoshop告诉我的值,工作伟大。

The resulting Lab color values are pretty close to what Photoshop tells me, so the converter works great.

上面的C代码给我这个结果:

The C-code above gives me this results though:

X = 35.76... // should be 42.282
Y = 71.52... // should be 74.129
Z = 11.92... // should be 46.262

任何想法导致这种失败的原因是什么?

Any idea what's the cause for this failure? Did I do a mistake in my implementation, or do I need other constants?

如果你知道一些测试的RGB到XYZ,XYZ到CIELab或RGB到CIELab,XYZ到实验室或RGB到实验室实施,请不要犹豫,在这里张贴。

If you know some tested RGB to XYZ, XYZ to CIELab or RGB to CIELab, XYZ to Lab or RGB to Lab implementations, please don't hesitate to post them here.

基本上,我想做的只是计算两种颜色之间的偏差,也称为Delta-E。这就是为什么我需要从RGB转换为XYZ到Lab(或CIELab)...

Basically, all I want to do is calculate the deviation between two colors, also known as Delta-E. That's why I need to convert from RGB to XYZ to Lab (or CIELab)...

推荐答案

我相信这里是你的问题,这是截断为整数:

I believe here is your problem, this is truncating to an integer:

CGFloat var_R = (*inR / 255); //R from 0 to 255
CGFloat var_G = (*inG / 255); //G from 0 to 255
CGFloat var_B = (*inB / 255); //B from 0 to 255

尝试:

CGFloat var_R = (*inR / 255.0f); //R from 0 to 255
CGFloat var_G = (*inG / 255.0f); //G from 0 to 255
CGFloat var_B = (*inB / 255.0f); //B from 0 to 255



我还没有检查其他问题的代码。

I haven't checked the rest of the code for other problems.

这篇关于这个RGB到XYZ颜色空间转换算法有什么问题?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆