Convertir la temperatura de color (K) a RGB: algoritmo y ejemplo de código



Si no sabe qué temperatura de color es, comience aquí .

Mientras trabajaba en la herramienta Temperatura de color para PhotoDemon , pasé toda la noche tratando de determinar un algoritmo simple y claro para convertir entre valores de temperatura (en Kelvin) y RGB. Pensé que tal algoritmo sería fácil de encontrar, porque muchos editores de fotos tienen herramientas para corregir la temperatura del color, y en cada cámara moderna, incluidos los teléfonos inteligentes, hay un ajuste de balance de blancos basado en las condiciones de iluminación.


Un ejemplo de una pantalla de cámara con una configuración de balance de blancos. Fuente

Resultó que encontrar una fórmula confiable para convertir la temperatura a RGB es casi imposible. Por supuesto, hay algunos algoritmos, pero la mayoría de ellos funcionan convirtiendo la temperatura en el espacio de color XYZ, al que luego puede agregar la transformación RGB. Tales algoritmos parecen estar basados ​​en el método Robertson, una implementación de los cuales está aquí , y la otra está aquí .

Desafortunadamente, este enfoque no proporciona una fórmula puramente matemática, es simplemente una interpolación de acuerdo con la tabla de conversión. Esto puede ser razonable bajo ciertas circunstancias, pero si tiene en cuenta la conversión adicional XYZ → RGB, resulta demasiado lenta para un simple ajuste de la temperatura del color en tiempo real.

Así que escribí mi propio algoritmo, y funciona muy bien. Así es como lo conseguí.

Advertencias sobre este algoritmo


Advertencia 1 : mi algoritmo proporciona una aproximación de alta calidad, pero no es lo suficientemente precisa para un uso científico serio. Está destinado principalmente a manipular fotografías, así que no intente usarlo para astronomía o medicina.

Advertencia 2 : debido a su relativa simplicidad, este algoritmo es lo suficientemente rápido como para funcionar en tiempo real en imágenes de un tamaño razonable (lo probé en imágenes de 12 megapíxeles), pero para obtener los mejores resultados, utilice optimizaciones matemáticas específicas para su lenguaje de programación. Muestro el algoritmo sin optimizaciones matemáticas para no complicarlo.

Advertencia 3 : el algoritmo es solo para usar en el rango de 1000 K a 40,000 K, que es un buen rango para la fotografía. (De hecho, es mucho más grande de lo que se puede requerir en la mayoría de las situaciones). Aunque funciona para temperaturas fuera de este rango, la calidad disminuirá.

Un agradecimiento especial a Mitchell Charity


En primer lugar, tengo que pagar una gran deuda y agradecer a Mitchell Charity por los datos iniciales que utilicé para crear estos algoritmos: un archivo de cuerpo negro sin procesar . Charity proporciona dos conjuntos de datos, y mi algoritmo utiliza la función de coincidencia de color de 10 grados CIE 1964 . Una discusión sobre la función CIE 1931 de 2 grados con las correcciones de Judd Wos en comparación con el conjunto de 10 grados está más allá del alcance de este artículo, pero si está interesado, puede comenzar un análisis exhaustivo desde esta página .

Algoritmo: salida de ejemplo


Aquí está la salida del algoritmo en el rango de 1000 K a 40,000 K:


La salida de mi algoritmo es de 1000 K a 40,000 K. El punto blanco está en 6500–6600 K, lo cual es ideal para procesar fotos en un monitor LCD moderno

Aquí hay una instantánea más detallada del algoritmo en un rango interesante para fotografía de 1500 K a 15000 K:


El mismo algoritmo, pero de 1500 K a 15000 K

Como puede ver, las bandas son mínimas, lo que es una gran mejora con respecto a las tablas de coincidencia anteriores. El algoritmo también hace un gran trabajo al preservar un tono amarillo claro cerca del punto blanco, lo cual es importante para simular la luz del día en fotos de procesamiento posterior.

Cómo llegué a este algoritmo


El primer paso para derivar una fórmula confiable fue trazar los valores originales del cuerpo negro de Charity . Puede descargar toda la hoja de cálculo en el formato .ods de LibreOffice / OpenOffice (430 KB) .

Aquí están los datos después de trazar:


Datos de temperatura originales (K) en RGB (sRGB), gráfico LibreOffice Calc. Nuevamente, la conversión se basa en la función CMF de 10 grados CIE 1964. El punto blanco, según se requiera, se encuentra entre 6500 K y 6600 K (pico en el lado izquierdo del gráfico). Fuente

Es fácil notar que hay varias secciones que simplifican nuestro algoritmo. En particular:

  • Los valores rojos por debajo de 6600 K son siempre 255
  • Los valores azules por debajo de 2000 K son siempre 0
  • Los valores azules por encima de 6500 K son siempre 255

También es importante tener en cuenta que para ajustar la curva a los datos, el verde se ve mejor como dos curvas separadas: una para temperaturas por debajo de 6600 K y la otra para temperaturas por encima de este punto.

A partir de este momento, dividí los datos (sin los segmentos "siempre 0" y "siempre 255") en componentes de color separados. En un mundo ideal, la curva se puede ajustar a cada conjunto de puntos, pero, desafortunadamente, en realidad no es tan simple. Dado que existe una fuerte discrepancia entre los valores de X e Y en el gráfico, todos los valores de x son mayores que 1000 y se muestran en segmentos de 100 puntos, mientras que los valores de y están entre 255 y 0, tuve que transponer los datos de x para obtener el mejor ajuste. Para fines de optimización, primero dividí el valor de x (temperatura) entre 100 para cada color, y luego resté la cantidad que necesitaba si me ayudaba mucho a ajustar el gráfico. Aquí están los diagramas resultantes para cada curva, así como la curva más adecuada y el valor correspondiente del coeficiente de determinación (R cuadrado):









Pido disculpas por el terrible interletraje de las fuentes y las insinuaciones en los gráficos. LibreOffice tiene muchas ventajas, pero la incapacidad de suavizar las fuentes en los gráficos es completamente vergonzosa. Tampoco me gusta extraer diagramas de capturas de pantalla, porque no tienen una opción de exportación, pero es mejor dejarla para más adelante.

Como puede ver, todas las curvas están bastante bien alineadas, con valores del coeficiente de determinación superiores a 0.987. Podría pasar más tiempo ajustando las curvas, pero eso es suficiente para procesar fotos. Ningún habitante dirá que las curvas no corresponden exactamente a las observaciones idealizadas iniciales del cuerpo negro, ¿verdad?

Algoritmo


Aquí está el algoritmo en todo su esplendor.

Primero, seudocódigo:

     -  1000  40000. (   ,             40000 K).  ,             . Set Temperature = Temperature \ 100  : If Temperature <= 66 Then Red = 255 Else Red = Temperature - 60 Red = 329.698727446 * (Red ^ -0.1332047592) If Red < 0 Then Red = 0 If Red > 255 Then Red = 255 End If  : If Temperature <= 66 Then Green = Temperature Green = 99.4708025861 * Ln(Green) - 161.1195681661 If Green < 0 Then Green = 0 If Green > 255 Then Green = 255 Else Green = Temperature - 60 Green = 288.1221695283 * (Green ^ -0.0755148492) If Green < 0 Then Green = 0 If Green > 255 Then Green = 255 End If  : If Temperature >= 66 Then Blue = 255 Else If Temperature <= 19 Then Blue = 0 Else Blue = Temperature - 10 Blue = 138.5177312231 * Ln(Blue) - 305.0447927307 If Blue < 0 Then Blue = 0 If Blue > 255 Then Blue = 255 End If End If 

Tenga en cuenta que en el pseudocódigo anterior, Ln () significa el logaritmo natural . También tenga en cuenta que puede omitir la comprobación si el color es inferior a 0, si la temperatura siempre está en el rango recomendado. (Sin embargo, aún debe dejar la marca "si el color es mayor que 255").

Con respecto al código real, aquí está la función exacta de Visual Basic que uso en PhotoDemon . Todavía no se ha optimizado (por ejemplo, los logaritmos serán mucho más rápidos con las tablas de correspondencia), pero al menos el código es conciso y legible:

 '   ( )  RGB- Private Sub getRGBfromTemperature(ByRef r As Long, ByRef g As Long, ByRef b As Long, ByVal tmpKelvin As Long) Static tmpCalc As Double '      1000  40000  If tmpKelvin < 1000 Then tmpKelvin = 1000 If tmpKelvin > 40000 Then tmpKelvin = 40000 '   tmpKelvin \ 100,       tmpKelvin = tmpKelvin \ 100 '     '  If tmpKelvin <= 66 Then r = 255 Else ':  R-    0,988 tmpCalc = tmpKelvin - 60 tmpCalc = 329.698727446 * (tmpCalc ^ -0.1332047592) r = tmpCalc If r < 0 Then r = 0 If r > 255 Then r = 255 End If '  If tmpKelvin <= 66 Then ':  R-    0,996 tmpCalc = tmpKelvin tmpCalc = 99.4708025861 * Log(tmpCalc) - 161.1195681661 g = tmpCalc If g < 0 Then g = 0 If g > 255 Then g = 255 Else ':  R-    0,987 tmpCalc = tmpKelvin - 60 tmpCalc = 288.1221695283 * (tmpCalc ^ -0.0755148492) g = tmpCalc If g < 0 Then g = 0 If g > 255 Then g = 255 End If ',  If tmpKelvin >= 66 Then b = 255 ElseIf tmpKelvin <= 19 Then b = 0 Else ':  R-    0,998 tmpCalc = tmpKelvin - 10 tmpCalc = 138.5177312231 * Log(tmpCalc) - 305.0447927307 b = tmpCalc If b < 0 Then b = 0 If b > 255 Then b = 255 End If End Sub 

La función se usó para generar la salida de muestra al comienzo de este artículo, por lo que puedo garantizar que funcione.

Imágenes de muestra


Aquí hay un gran ejemplo de lo que pueden hacer los ajustes de temperatura de color. La imagen a continuación, un póster publicitario de True Blood de HBO, muestra espectacularmente el potencial para ajustar la temperatura del color. A la izquierda está el marco original; a la derecha: ajuste la temperatura del color con el código anterior. Con un clic, la escena nocturna se puede rehacer a la luz del día.


Ajuste de temperatura de color en acción

La herramienta de temperatura de color real en mi programa PhotoDemon es la siguiente:


Herramienta de temperatura de color PhotoDemon

Descarga el programa y míralo en acción.

Actualización octubre 2014


Renault Bedar hizo una gran demostración en línea para este algoritmo. Gracias Renault!

Actualización de abril de 2015


Gracias a todos los que sugirieron mejoras al algoritmo original. Sé que el artículo tiene muchos comentarios, pero vale la pena leerlos si planeas implementar tu propia versión.

Quiero destacar dos mejoras específicas. Primero, Neil B proporcionó amablemente la mejor versión para las funciones originales de ajuste de curvas, que cambia ligeramente los coeficientes de temperatura. Los cambios se describen en detalle en su excelente artículo .

Luego, Francis Loch agregó algunos comentarios y ejemplos de imágenes, que son muy útiles si desea aplicar estas transformaciones a las fotos. Sus modificaciones producen una imagen mucho más detallada, como se ve en los ejemplos .

Source: https://habr.com/ru/post/es427333/


All Articles