Display temperature as a color with C#?

后端 未结 5 520
死守一世寂寞
死守一世寂寞 2020-12-15 08:01

Someone knows an algorithm that gets temperatue in Kelvin/Celsius and returns RGB?

Like in thermal cameras.

I found some links :

http://www.brucelind

相关标签:
5条回答
  • 2020-12-15 08:26

    I realize this is a two-year old thread, but I had the same predicament.

    I took the data from the color table and did applied piece-wise 5th order polynomial fitting using Numpy.polyfit in Python. From those coefficients I was able to come up with the C# function below. R-squared values for the fits are close to or exceed 0.999. It has less than .01% error through most of its domain, but it does have a couple of points where it is closer to 3%. Should be good enough for most situations though.

    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);
    }
    
    0 讨论(0)
  • 2020-12-15 08:35

    The above function overestimate red color when temp > 10000 K. Colors turn to purple when temp>14000. I refitted the data with 7th order polynomials. The coefficients of should be:

    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)
    

    Here poly(coeffs,x) = coeffs[0] + coeffs[1]*x + coeffs[2]*x**2 + ...

    Sorry I am not familiar with C# but you can easily read the codes.

    The error is within only 0.5% for most cases and at most 1.2% for red in temp = 6600 K. High order polynomials are adopted here so red and green must keep constant for temp > 40000 K, otherwise strange things will happen.

    0 讨论(0)
  • 2020-12-15 08:36

    Color temperature is based on the actual color of light emitted from something (theoretically, an "ideal black body") that emits light based solely on its temperature.

    Some examples of this kind of light source: if you have an electric stove element that is glowing red, it might be around 1000K. A regular incandescent bulb filament is around 2700K, and the sun is roughly 5700K. All three are fair approximations of a "black body"; they emit a particular spectrum of light based on their actual temperature.

    Many artificial light sources are not actually the "temperature" of the light they emit (and their spectra are generally not black-body spectra, either...). Instead, their "temperature" rating is the temperature a theoretical black body would have to be in order to emit light of that color. There are also colors that cannot be generated by a black body: light which is greenish or purplish compared to a more "natural"-looking black body illumination.

    As mentioned in one of the comments, the kind of thermal camera displays you are probably thinking about are all false-color. In a false-color display, the colors are chosen for convenience only: so, for a thermal camera they might choose a "hot"-looking red for warm, and "cold"-looking blue for cold. But, they could just as easily choose a range from black to white, or fuschia to green.

    Because false-color displays are arbitrary, you really need to check the color key to a particular image or system if you want to estimate the temperature (scientific images should generally have some kind of color key for this purpose). If you have no color key, and no documentation on how the image was generated, you are out of luck.

    0 讨论(0)
  • 2020-12-15 08:44

    If get you right you are looking for a theoretical background on XYZ color space

    0 讨论(0)
  • 2020-12-15 08:46

    The best option is to use an image with GetPixel:

    Temperature Gradient

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

    Or building an array. Source

        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
        };
    
    0 讨论(0)
提交回复
热议问题