Отображать температуру в цвете с C#?

Кто-то знает алгоритм, который получает температуру в градусах Кельвина / Цельсия и возвращает RGB?

Как в тепловизорах.

Я нашел несколько ссылок:

http://www.brucelindbloom.com/index.html?Eqn_XYZ_to_T.html

http://www.fourmilab.ch/documents/specrend/specrend.c

Но я не могу понять, что цвет XYZ?

У меня только температура в градусах Цельсия..

Я могу преобразовать его в любую температуру Формулы преобразования температуры

ОБНОВЛЕНИЕ: файл данных о цвете черного тела Я нашел это... но эти градусы Кельвина невозможны... я имею в виду, что красный цвет должен быть горячим... так почему 8000k это синий, а 1000k это красный...

5 ответов

Решение

Лучший вариант - использовать изображение с GetPixel:

Градиент температуры

private void UpdateTemp()
{
    Bitmap temps = (Bitmap)Properties.Resources.temp;
    if (curTemp >= 0)
    {
        int i = curTemp;
        if (i < 0)
            i = 0;
        if (i > temps.Width-1)
            i = temps.Width-1;
        this.BackColor = temps.GetPixel(i, 10);
    }
}

Или строит массив. Источник

    private static Color[] colors = 
    {
        Color.FromArgb(155, 188, 255), //    40000
        Color.FromArgb(155, 188, 255), //    39500
        Color.FromArgb(155, 188, 255), //    39000
        Color.FromArgb(155, 188, 255), //    38500
        Color.FromArgb(156, 188, 255), //    38000
        Color.FromArgb(156, 188, 255), //    37500
        Color.FromArgb(156, 189, 255), //    37000
        Color.FromArgb(156, 189, 255), //    36500
        Color.FromArgb(156, 189, 255), //    36000
        Color.FromArgb(157, 189, 255), //    35500
        Color.FromArgb(157, 189, 255), //    35000
        Color.FromArgb(157, 189, 255), //    34500
        Color.FromArgb(157, 189, 255), //    34000
        Color.FromArgb(157, 189, 255), //    33500
        Color.FromArgb(158, 190, 255), //    33000
        Color.FromArgb(158, 190, 255), //    32500
        Color.FromArgb(158, 190, 255), //    32000
        Color.FromArgb(158, 190, 255), //    31500
        Color.FromArgb(159, 190, 255), //    31000
        Color.FromArgb(159, 190, 255), //    30500
        Color.FromArgb(159, 191, 255), //    30000
        Color.FromArgb(159, 191, 255), //    29500
        Color.FromArgb(160, 191, 255), //    29000
        Color.FromArgb(160, 191, 255), //    28500
        Color.FromArgb(160, 191, 255), //    28000
        Color.FromArgb(161, 192, 255), //    27500
        Color.FromArgb(161, 192, 255), //    27000
        Color.FromArgb(161, 192, 255), //    26500
        Color.FromArgb(162, 192, 255), //    26000
        Color.FromArgb(162, 193, 255), //    25500
        Color.FromArgb(163, 193, 255), //    25000
        Color.FromArgb(163, 193, 255), //    24500
        Color.FromArgb(163, 194, 255), //    24000
        Color.FromArgb(164, 194, 255), //    23500
        Color.FromArgb(164, 194, 255), //    23000
        Color.FromArgb(165, 195, 255), //    22500
        Color.FromArgb(166, 195, 255), //    22000
        Color.FromArgb(166, 195, 255), //    21500
        Color.FromArgb(167, 196, 255), //    21000
        Color.FromArgb(168, 196, 255), //    20500
        Color.FromArgb(168, 197, 255), //    20000
        Color.FromArgb(169, 197, 255), //    19500
        Color.FromArgb(170, 198, 255), //    19000
        Color.FromArgb(171, 198, 255), //    18500
        Color.FromArgb(172, 199, 255), //    18000
        Color.FromArgb(173, 200, 255), //    17500
        Color.FromArgb(174, 200, 255), //    17000
        Color.FromArgb(175, 201, 255), //    16500
        Color.FromArgb(176, 202, 255), //    16000
        Color.FromArgb(177, 203, 255), //    15500
        Color.FromArgb(179, 204, 255), //    15000
        Color.FromArgb(180, 205, 255), //    14500
        Color.FromArgb(182, 206, 255), //    14000
        Color.FromArgb(184, 207, 255), //    13500
        Color.FromArgb(186, 208, 255), //    13000
        Color.FromArgb(188, 210, 255), //    12500
        Color.FromArgb(191, 211, 255), //    12000
        Color.FromArgb(193, 213, 255), //    11500
        Color.FromArgb(196, 215, 255), //    11000
        Color.FromArgb(200, 217, 255), //    10500  
        Color.FromArgb(204, 219, 255), //    10000
        Color.FromArgb(208, 222, 255), //    9500
        Color.FromArgb(214, 225, 255), //    9000
        Color.FromArgb(220, 229, 255), //    8500
        Color.FromArgb(227, 233, 255), //    8000
        Color.FromArgb(235, 238, 255), //    7500
        Color.FromArgb(245, 243, 255), //    7000
        Color.FromArgb(255, 249, 253), //    6500
        Color.FromArgb(255, 243, 239), //    6000
        Color.FromArgb(255, 236, 224), //    5500
        Color.FromArgb(255, 228, 206), //    5000
        Color.FromArgb(255, 219, 186), //    4500
        Color.FromArgb(255, 209, 163), //    4000
        Color.FromArgb(255, 196, 137), //    3500
        Color.FromArgb(255, 180, 107), //    3000
        Color.FromArgb(255, 161,  72), //    2500
        Color.FromArgb(255, 137,  18), //    2000
        Color.FromArgb(255, 109,   0), //    1500 
        Color.FromArgb(255,  51,   0), //    1000
    };

Я понимаю, что это двухлетняя нить, но у меня было то же затруднительное положение.

Я взял данные из таблицы цветов и применил кусочную полиномиальную аппроксимацию 5-го порядка, используя Numpy.polyfit в Python. Из этих коэффициентов я смог придумать функцию C# ниже. R-квадрат значения для посадки близки или превышают 0,999. Он имеет ошибку менее 0,01% на большей части своего домена, но у него есть пара точек, где он ближе к 3%. Должно быть достаточно хорошо для большинства ситуаций, хотя.

private Color blackBodyColor(double temp)
{
    float x = (float)(temp / 1000.0);
    float x2 = x * x;
    float x3 = x2 * x;
    float x4 = x3 * x;
    float x5 = x4 * x;

    float R, G, B = 0f;

    // red
    if (temp <= 6600)
        R = 1f;
    else
        R = 0.0002889f * x5 - 0.01258f * x4 + 0.2148f * x3 - 1.776f * x2 + 6.907f * x - 8.723f;

    // green
    if (temp <= 6600)
        G = -4.593e-05f * x5 + 0.001424f * x4 - 0.01489f * x3 + 0.0498f * x2 + 0.1669f * x - 0.1653f;
    else
        G = -1.308e-07f * x5 + 1.745e-05f * x4 - 0.0009116f * x3 + 0.02348f * x2 - 0.3048f * x + 2.159f;

    // blue
    if (temp <= 2000f)
        B = 0f;
    else if (temp < 6600f)
        B = 1.764e-05f * x5 + 0.0003575f * x4 - 0.01554f * x3 + 0.1549f * x2 - 0.3682f * x + 0.2386f;
    else
        B = 1f;

    return Color.FromScRgb(1f, R, G, B);
}

Если вы правы, вы ищете теоретический фон по цветовому пространству XYZ

Цветовая температура основана на фактическом цвете света, излучаемого чем-то (теоретически, "идеальным черным телом"), который излучает свет, основываясь исключительно на его температуре.

Некоторые примеры этого вида источника света: если у вас есть элемент электрической плиты, который светится красным, он может быть около 1000K. Обычная нить накаливания составляет около 2700K, а солнце - около 5700K. Все три являются справедливым приближением к "черному телу"; они излучают определенный спектр света в зависимости от их фактической температуры.

Многие искусственные источники света на самом деле не являются "температурой" света, который они излучают (и их спектры, как правило, тоже не являются спектрами черного тела...). Вместо этого, их "температурный" рейтинг - это температура, которой должно быть теоретическое черное тело, чтобы излучать свет этого цвета. Есть также цвета, которые не могут быть созданы черным телом: свет, который зеленоватый или пурпурный по сравнению с более "естественным" на вид освещением черного тела.

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

Поскольку отображение ложных цветов является произвольным, вам действительно нужно проверить цветовую клавишу для определенного изображения или системы, если вы хотите оценить температуру (научные изображения обычно должны иметь какую-то цветовую клавишу для этой цели). Если у вас нет цветового ключа и нет документации о том, как было сгенерировано изображение, вам не повезло.

Вышеуказанная функция переоценивает красный цвет, когда температура> 10000 К. Цвета становятся фиолетовыми, когда температура>14000. Я уточнил данные полиномами 7-го порядка. Коэффициенты должны быть:

def temp_to_rgb(temp):
    t = temp/1000.

    # calculate red
    if t < 6.527:
        red = 1.0
    else:
        coeffs = [  4.93596077e+00,  -1.29917429e+00,
                    1.64810386e-01,  -1.16449912e-02,
                    4.86540872e-04,  -1.19453511e-05,
                    1.59255189e-07,  -8.89357601e-10]
        tt = min(t,40)
        red = poly(coeffs,tt)
    red = max(red,0)
    red = min(red,1)

    # calcuate green
    if t < 0.85:
        green = 0.0
    elif t < 6.6:
        coeffs = [ -4.95931720e-01,   1.08442658e+00,
                   -9.17444217e-01,   4.94501179e-01,
                   -1.48487675e-01,   2.49910386e-02,
                   -2.21528530e-03,   8.06118266e-05]
        green = poly(coeffs,t)
    else:
        coeffs = [  3.06119745e+00,  -6.76337896e-01,
                    8.28276286e-02,  -5.72828699e-03,
                    2.35931130e-04,  -5.73391101e-06,
                    7.58711054e-08,  -4.21266737e-10]
        tt = min(t,40)
        green = poly(coeffs,tt)
    green = max(green,0)
    green = min(green,1)

    # calculate blue
    if t < 1.9:
        blue = 0.0
    elif t < 6.6:
        coeffs = [  4.93997706e-01,  -8.59349314e-01,
                    5.45514949e-01,  -1.81694167e-01,
                    4.16704799e-02,  -6.01602324e-03,
                    4.80731598e-04,  -1.61366693e-05]
        blue = poly(coeffs,t)
    else:
        blue = 1.0
    blue = max(blue,0)
    blue = min(blue,1)

    return (red,green,blue)

Здесь poly(coeffs,x) = coeffs[0] + coeffs[1]*x + coeffs[2]*x**2 + ...

Извините, я не знаком с C#, но вы можете легко прочитать коды.

В большинстве случаев ошибка находится в пределах только 0,5% и не более 1,2% для красного при температуре = 6600 К. Здесь принимаются полиномы высокого порядка, поэтому красный и зеленый должны оставаться постоянными при температуре> 40000 К, в противном случае могут произойти странные вещи.

Другие вопросы по тегам