有什么不对的RGB到XYZ色彩空间转换算法?有什么、算法、色彩、空间

2023-09-12 21:17:36 作者:时间判爱死刑

我的目标是将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(大多采用普通的C虽然)来实现这个算法,但结果是错误的。

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

我的code是基于 easyrgb.com提供的伪实施。他们有一个在线,颜色转换器,它的伟大工程。他们说,他们的假code是同一个在他们的转换器使用。

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.

这是他们的伪code:

This is their Pseudo-Code:

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色值是pretty的接近Photoshop的东西告诉我,所以转换器的伟大工程。

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

在C-code以上给了我这样的结果虽然:

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.

基本上,所有我想要做的就是计算出两种颜色,也被称为Δ-E之间的偏差。这就是为什么我需要从RGB转换为XYZ到实验室(或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

我没有检查的code,其余为其他问题。

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