Рассчитать цветовую температуру в K

Я написал библиотеку для работы с цветами и застрял, пытаясь вычислить Tc(k). Из того, что я читал, работа в цветовом пространстве CIE 1931 XYZ — это путь, и он может можно получить с помощью xyY.

До сих пор у меня все было правильно, чтобы выяснить правильные x и y из:

          X                 Y
x = ____________  y = ____________
    ( X + Y + Z)      ( X + Y + Z)

Цифры соответствуют диаграмме, но не могу найти ничего, что бы подробно описало, как вы переходите от x и y к Tc(K)

введите здесь описание изображения

например: Для # FF0000 я получаю следующее.

x: 0.64007449945677
y: 0.32997051063169

Я прочитал ряд статей по этой теме и буквально все статьи в Википедии. Все вопросы, с которыми я столкнулся на SO, просто ссылаются на вики-статью о цветах, но не видели ту, в которой есть фактическая формула для расчета Tc(k)


person dogmatic69    schedule 20.12.2012    source источник
comment
Вы можете попробовать один из этих приблизительных значений цветовой температуры. С другой стороны, вы ищете планковский локус.   -  person user7116    schedule 20.12.2012
comment
Цвет черного тела на самом деле представляет собой спектр, а не чистый спектральный цвет. Например, цвет может быть белым, хотя цвет пика может быть зеленым. Любая формула должна включать определение эквивалентного цвета CIE путем анализа реакции палочек и колбочек глаза.   -  person uncleO    schedule 20.12.2012


Ответы (6)


Основываясь на статье в Википедии, я ввел приблизительную формулу для расчета Color Temperature в Excel как

=(-449*((R1-0,332)/(S1-0,1858))^3)+(3525*((R1-0,332)/(S1-0,1858))^2)-(6823,3*((R1-0,332)/(S1-0,1858)))+(5520,33)

R1 is color space x coordinate from 0 to 1
S1 is color space y coordinate from 0 to 1

Работает отлично!

person Tarmo    schedule 12.04.2014

Если я вас правильно понял, см. это pdf, где описан ряд методов. PDF:

[CCT1] Расчеты выполняются с использованием координат u и v в едином цветовом пространстве CIE 1960. Координаты u и v выводятся из x и y по формулам: u = 4x/(12y-2x+3) и v = 6y/(12y- 2x+3) Коррелированная цветовая температура определяется как температура абсолютно черного тела, которая находится ближе всего к координатам u, v тестового источника. Результаты дают два отдельных метода: один представляет собой итерационный метод, основанный на определении, а другой — широко используемый метод Робертсона, включающий интерполяцию на основе таблицы из 30 предварительно рассчитанных параметров u, v и обратного наклона. Итерация Если uS и vS — значения для тестового источника, а uT и vT — значения черного тела при температуре T, коррелированная цветовая температура — это значение T, где:

sqrt( (uS - uT)^2 + (vS - vT)^2 )

сведен к минимуму. Настройка температуры T для получения минимума этой функции проводилась с использованием электронных таблиц (Quattro Pro 8 и Excel 97). Обе таблицы дали одинаковые значения.

Не знаю, поможет ли это вам на самом деле.

person maverik    schedule 20.12.2012

Я немного покопался в некоторых приложениях с открытым исходным кодом и нашел кое-что в UFRaw. Я не совсем понял, что именно происходит.

Также нашел документ, который, кажется, достаточно хорошо освещает тему .

Преобразованный в php, и это то, что у меня есть до сих пор:

$temp = array(9500, 7000, 5500, 3750, 3000, 2700, 2250, 1800, 1500);
$hex = array('9DBEFF', 'E4EEFF', 'FFE4BE', 'FFA04C', 'FF7A26', 'FF6A19', 'FF500B', 'FF3403', 'FF2300');

echo '<h3>K -> RGB</h3>';
foreach ($temp as $k) {
    $rgb = ColourConverter::temperature2rgb($k);
    echo sprintf('<div style="background-color:rgb(%s); text-align: center; width: 100px; height: 25px; clear: both;">%s</div>', implode(', ', $rgb), $k);
}

echo '<h3>RGB -> K</h3>';
foreach ($hex as $v) {
    $rgb = array_values(ColourConverter::hex2rgb($v));
    $k = round(ColourConverter::rgb2temperature($rgb[0], $rgb[1], $rgb[2]));
    echo sprintf('<div style="background-color:rgb(%s); text-align: center; width: 100px; height: 25px; clear: both;">%s</div>', implode(', ', $rgb), $k);
}

Ссылка

Мой вывод:

выход

Довольно близко, но еще не на 100%. (Нашел ошибку в моем коде, и теперь он почти идеален)

  • Цвета немного отличаются от k -> rgb
  • Не работает k -> rgb -> k. Вы не вернетесь к тому же значению.

Код

строка UFRaw 246–294

void Temperature_to_RGB(double T, double RGB[3])
{
    int c;
    double xD, yD, X, Y, Z, max;
    // Fit for CIE Daylight illuminant
    if (T <= 4000) {
        xD = 0.27475e9 / (T * T * T) - 0.98598e6 / (T * T) + 1.17444e3 / T + 0.145986;
    } else if (T <= 7000) {
        xD = -4.6070e9 / (T * T * T) + 2.9678e6 / (T * T) + 0.09911e3 / T + 0.244063;
    } else {
        xD = -2.0064e9 / (T * T * T) + 1.9018e6 / (T * T) + 0.24748e3 / T + 0.237040;
    }
    yD = -3 * xD * xD + 2.87 * xD - 0.275;

    // Fit for Blackbody using CIE standard observer function at 2 degrees
    //xD = -1.8596e9/(T*T*T) + 1.37686e6/(T*T) + 0.360496e3/T + 0.232632;
    //yD = -2.6046*xD*xD + 2.6106*xD - 0.239156;

    // Fit for Blackbody using CIE standard observer function at 10 degrees
    //xD = -1.98883e9/(T*T*T) + 1.45155e6/(T*T) + 0.364774e3/T + 0.231136;
    //yD = -2.35563*xD*xD + 2.39688*xD - 0.196035;

    X = xD / yD;
    Y = 1;
    Z = (1 - xD - yD) / yD;
    max = 0;
    for (c = 0; c < 3; c++) {
        RGB[c] = X * XYZ_to_RGB[0][c] + Y * XYZ_to_RGB[1][c] + Z * XYZ_to_RGB[2][c];
        if (RGB[c] > max) max = RGB[c];
    }
    for (c = 0; c < 3; c++) RGB[c] = RGB[c] / max;
}

void RGB_to_Temperature(double RGB[3], double *T, double *Green)
{
    double Tmax, Tmin, testRGB[3];
    Tmin = 2000;
    Tmax = 23000;
    for (*T = (Tmax + Tmin) / 2; Tmax - Tmin > 0.1; *T = (Tmax + Tmin) / 2) {
        Temperature_to_RGB(*T, testRGB);
        if (testRGB[2] / testRGB[0] > RGB[2] / RGB[0])
            Tmax = *T;
        else
            Tmin = *T;
    }
    *Green = (testRGB[1] / testRGB[0]) / (RGB[1] / RGB[0]);
    if (*Green < 0.2) *Green = 0.2;
    if (*Green > 2.5) *Green = 2.5;
}
person dogmatic69    schedule 20.12.2012
comment
Привет, друг, ссылка не работает, можешь обновить этот ответ? - person Khai Nguyen; 23.09.2014

В Википедии говорится, что цветовая температура рассчитывается с учетом цветности u-v, а не x-y, поэтому вам необходимо выполнить перевод. Тем не менее, я рекомендую использовать приближение (также объясненное в Википедии), предложенное @sixlettervariables.

Настоящий вопрос в том, для чего вы пытаетесь найти цветовую температуру? Я вижу ссылку (#FF0000) на цвета RGB, которые бессмысленны без указания цветового пространства. Предположим, вы находитесь в sRGB (чтобы я мог снова указать вам на Википедию), вы должны сначала получить линейные координаты RGB перед переходом к XYZ.

person Emre    schedule 29.12.2012

Я понимаю, что это старый вопрос, но я тоже изо всех сил пытался найти ответ. Наконец-то я наткнулся на этот отличный калькулятор, который также публикует формулу следующим образом:

n = (x-0.3320)/(0.1858-y)

CCT = 437*n^3 + 3601*n^2 + 6861*n + 5517

Надеюсь, это поможет любому, кто все еще ищет.

person Randy Melville    schedule 22.01.2018

Нашел решение для преобразования температуры в RGB, написанное на JavaScript, и преобразовал его в PHP.

<?php
function colorTemperatureToRGB($kelvin)
{
    $temp = $kelvin / 100;

    $red = null;
    $green = null;
    $blue = null;

    if ($temp <= 66)
    {
        $red = 255; 

        $green = $temp;
        $green = 99.4708025861 * log($green) - 161.1195681661;


        if ($temp <= 19)
        {
            $blue = 0;
        }
        else
        {
            $blue = $temp - 10;
            $blue = 138.5177312231 * log($blue) - 305.0447927307;
        }

    }
    else
    {
        $red = $temp - 60;
        $red = 329.698727446 * pow($red, -0.1332047592);

        $green = $temp - 60;
        $green = 288.1221695283 * pow($green, -0.0755148492);

        $blue = 255;
    }

    return [
        'r' => clamp($red,   0, 255),
        'g' => clamp($green, 0, 255),
        'b' => clamp($blue,  0, 255)
    ];
}

function clamp($x, $min, $max)
{
    if ($x < $min)
        return $min;

    if ($x > $max)
        return $max;

    return $x;
}

var_dump(colorTemperatureToRGB(7000));
person NXT    schedule 18.11.2019
comment
Вы сослались на скрипт по существу, который сам ссылается на другой источник. Вы могли бы просто сослаться на это, так как это очень тщательно tannerhelland.com /4435/convert-temporary-rgb-algorithm-code - person dogmatic69; 28.11.2019
comment
@dogmatic69 Не совсем так, GIST предлагает готовое решение на JavaScript, но да, ссылку на источник стоит упомянуть - спасибо - person NXT; 29.11.2019