Что не так с этим алгоритмом преобразования цветового пространства RGB в XYZ?

Моя цель - преобразовать пиксель RGB в цветовое пространство CIELab для некоторых специальных вычислений, возможных только в CIELab. Для этого я должен сначала преобразовать RGB в XYZ, что является действительно сложной частью.

Я попытался реализовать этот алгоритм в Objective-C (в основном, используя простой C), но результаты оказались неверными.

Мой код основан на псевдо-реализации, предоставленной easyrgb.com . У них есть онлайн-конвертер цветов, который отлично работает. Они говорят, что их псевдокод - тот же, что используется в их конвертере.

Это их псевдокод:

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:

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;
}

Однако я не не получают тех же результатов, что и их инструмент (с теми же настройками Observer и Illuminant).

В моем тесте я ввел эти значения в их инструмент и получил этот результат для XYZ, который далек от того, что моя реализация дает для этого RGB ценность. См. Снимок экрана:


screenshot


Полученные значения цвета Lab довольно близки к тому, что сообщает мне Photoshop, поэтому конвертер отлично работает.

Приведенный выше C-код дает мне следующие результаты:

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

Есть идеи, в чем причина этого сбоя? Я сделал ошибку в своей реализации или мне нужны другие константы?

Если вы знаете какие-то протестированные реализации RGB в XYZ, XYZ в CIELab или RGB в CIELab, XYZ в Lab или RGB в Lab, пожалуйста, не сомневайтесь разместить их здесь.

По сути, все, что мне нужно сделать, это вычислить отклонение между двумя цветами, также известное как Delta-E. Вот почему мне нужно преобразовать из RGB в XYZ в Lab (или CIELab) ...

16
задан SecretService - not really 9 July 2011 в 11:21
поделиться