Skip to main content

UTi712S

Extrae la matriz térmica de los BMP que guarda la cámara UNI-T UTi712S, la convierte a grados Celsius con la misma escala que usa el software de la cámara, y permite consultar cada punto en un visor.

El archivo no trae la lectura del sensor. Trae la imagen de pantalla, de 8 bits, y tres temperaturas puntuales (mínima, máxima y central). La matriz en °C es la interpolación que arma ImageFile.dll a partir de esos datos. Sirve para reproducir lo que muestra el programa oficial. No mejora la medición.

La cámara

La UTi712S guarda las capturas en BMP. El sensor es de 120×90. La pantalla es de 320×240 y el archivo sale en 240×320, el mismo recuadro girado a vertical. El rango publicado por UNI-T es de -20 °C a 400 °C, con exactitud de ±2 °C o ±2 %, el que sea mayor. La emisividad de fábrica es 0,95.

Esas tres cifras (rango, exactitud, emisividad) describen los puntos que mide la cámara. No describen el byte de cada píxel.

Instalación

Hace falta Python 3.10 o posterior. El paquete está en PyPI. Con pipx:

pipx install uti712s

Quedan dos comandos: uti712s-extract y uti712s-view.

Pillow es opcional. Sin él se escriben el JSON y los CSV, y no los PNG. El extra se llama png. En el entorno de pipx:

pipx inject uti712s pillow

El visor usa tkinter, que no se instala por pip. En Debian o Ubuntu: sudo apt install python3-tk. Tiene que estar en el mismo Python que usa pipx.

Desde el repositorio, sin pasar por PyPI:

pipx install git+https://github.com/pablogventura/uti712s.git

O, desde una copia local:

pipx install .

Uso

uti712s-extract 'images/IMG 0001.bmp'

Sin instalar, desde el repositorio:

python3 uti712s_extract.py 'images/IMG 0001.bmp'

Los archivos salen al lado del BMP:

Archivo Contenido
IMG 0001_metadatos.json Temperaturas puntuales, anclas, modo y píxeles de control
IMG 0001_intensidades.csv Matriz de 8 bits, una fila de imagen por línea, sin encabezado
IMG 0001_celsius.csv La misma grilla en °C, ocho decimales
IMG 0001_intensidades.png La matriz en gris, sin la interfaz de la cámara
IMG 0001_termica_sin_indicadores.png La misma matriz coloreada con la paleta embebida

La fila 0 es el borde de arriba. En modo 7, que es el de las capturas de images/, el orden es el del archivo.

Desde Python

read_capture lee el BMP y no escribe archivos. celsius_at calcula un punto con la escala de dos tramos. extract escribe el JSON, los CSV y, si Pillow está instalado, los PNG.

from pathlib import Path
from uti712s_extract import read_capture, extract

capture = read_capture(Path("images/IMG 0001.bmp"))
print(capture.celsius_at(119, 159))
extract(Path("images/IMG 0001.bmp"))

Visor

Abre la escena térmica sin la interfaz de la cámara y muestra la temperatura estimada de cada píxel. Usa la paleta embebida y la misma escala que el CSV. Abrir un BMP no escribe archivos.

uti712s-view
uti712s-view 'images/IMG 0001.bmp'

Sin instalar, desde el repositorio: python3 uti712s_view.py y python3 uti712s_view.py 'images/IMG 0001.bmp'.

Archivo, Abrir, carga otro BMP. La rueda del mouse sobre la imagen cambia el zoom, de 1 a 6. Cada píxel de origen sigue siendo un bloque. La rueda sobre el panel desplaza el texto, si no entra en la ventana.

El panel tiene tres bloques.

Bajo el mouse. La temperatura en °C, con un decimal, del píxel que está bajo el puntero. También muestra la columna y la fila. La columna se cuenta desde la izquierda y la fila desde arriba. El brillo es el byte de 0 a 255 guardado en el archivo. La temperatura es la estimación en °C. Si el puntero no está sobre la imagen, el bloque pide pasar el mouse por ella.

Punto fijado. Un clic deja esa lectura marcada, aunque el mouse se mueva. Otro clic, o Escape, la suelta. El punto se dibuja con un cuadrado rosa, un poco más grande que el píxel.

Mediciones de la cámara. Los tres valores del pie, la emisividad y el modo.

  • Mínima y máxima: el punto más frío y el más caliente que midió la cámara. No se marcan en la imagen. Esas coordenadas a veces caen fuera, y no siempre coinciden con el byte más frío o más caliente.
  • Central: la lectura del centro. El cuadrado celeste queda en ese valor. Los demás píxeles se estiman a partir de estos tres.
  • Emisividad: la que tenía configurada la cámara. En estas capturas es 0,95, el valor de fábrica.
  • Modo 7: la foto no se gira. Arriba es arriba.

Hay dos marcas fijas. El cuadrado celeste es el píxel de la curva. En estas capturas está en la columna 119, fila 159, y su temperatura es la central. La cruz amarilla es el centro que dibuja el software, en la columna 120, fila 160. En modo 7 son píxeles distintos. Si el mouse cae en una, el panel lo dice.

Qué hay en el BMP

Las 32 capturas de images/ miden 230995 bytes y comparten esta forma: BMP de 16 bits, 240×320, sin compresión, y un bloque extra de 77341 bytes.

El programa oficial no lee el ancho ni el alto del encabezado. Fija 240×320 y empieza la zona térmica en el offset 0x25839 (153657). Este script lee el tamaño en el encabezado y entra en bfSize + 3. En un BMP de 16 bits y 240×320, bfSize vale 153654 (54 bytes de encabezado más 153600 de píxeles), así que bfSize + 3 cae en el mismo byte. Además exige que el bloque extra mida 3 + ancho*alto + 512 + 26 y que arranque con tres ceros.

0            encabezado BMP y píxeles de 16 bits     153654 bytes
153654       00 00 00                                3 bytes
153657       intensidades, 1 byte por píxel          240 * 320 = 76800
230457       paleta RGB565, 256 colores              512
230969       pie                                     26
230995       fin

El BMP visible es la pantalla: cruz, textos, batería, fecha y barra de color. La matriz de 8 bits es la escena térmica sin esa interfaz. El origen vertical coincide con la foto: arriba es arriba.

La paleta embebida no reproduce los píxeles del BMP. En estas capturas la coincidencia exacta es prácticamente nula. La pantalla lleva la interfaz encima y usa otro estirado de color. El PNG sin indicadores muestra la escena limpia, con la paleta del archivo, no una copia de la pantalla.

Paleta

Son 256 colores de 16 bits, little-endian, RGB565:

Canal Bits Expansión que usa el software
Rojo 15..11 los 5 bits, desplazados 3 a la izquierda (máximo 248)
Verde 10..5 los 6 bits, desplazados 2 a la izquierda
Azul 4..0 los 5 bits, desplazados 3 a la izquierda

El índice es el byte de intensidad, sin estirar al rango de la escena.

Pie de 26 bytes

Little-endian. Las temperaturas son enteros con signo, en décimas. Las coordenadas son enteros sin signo.

Offset Tipo Campo
0 uint8 Unidad. 0 es °C, 1 es °F
1 int16 Temperatura máxima × 10
3 int16 Temperatura mínima × 10
5 uint8 Ancla caliente: intensidad que el software iguala a la máxima
6 uint8 Ancla fría: intensidad que el software iguala a la mínima
7 int16 Temperatura central × 10
9 uint8 Emisividad × 100
10 uint8 Modo de orientación
11 3 bytes El software no los lee. En estas capturas valen 0
14 uint16 X del mínimo
16 uint16 Y del mínimo
18 uint16 X del máximo
20 uint16 Y del máximo
22 uint16 X del centro guardado
24 uint16 Y del centro guardado

En las 32 capturas: unidad °C, emisividad 0,95, modo 7, ancla fría 0, ancla caliente igual al máximo de la matriz, centro guardado en (120, 160).

El byte 5 y el byte 6 juntos parecen un int16. No lo son. El software los lee por separado. Como el byte 6 es 0, ese int16 coincide con la intensidad máxima, y por eso un parseo anterior lo veía como "el máximo de la matriz" metido en un solo campo.

Modo de orientación

El modo es el byte 10. Cambia el orden de la matriz antes de convertir, y también cómo se interpretan las coordenadas de mínimo y máximo. El centro dibujado no sale del pie: el software lo fija según el modo.

Modo Matriz Mínimo y máximo Centro dibujado
1 salida[fila, col] = origen[alto * (ancho - col - 1) + fila] x' = ancho - y - 1, y' = x - 1 (alto/2 - 1, ancho/2 - 1) = (159, 119)
2 y 5 el buffer al revés x' = ancho - x - 1, y' = alto - y - 1 (ancho/2 - 1, alto/2 - 1) = (119, 159)
otro, incluido el 7 se deja como está se dejan como están (ancho/2, alto/2) = (120, 160)

Las 32 capturas son modo 7. Los modos 1, 2 y 5 están implementados como en el DLL, pero este conjunto no los trae.

Las coordenadas de mínimo y máximo pueden caer fuera del raster. En estas fotos aparece x = 240 o y = 321. El software las guarda igual, sin recortarlas. A veces el marcador cae a unos pocos píxeles del extremo de intensidad, y a veces a decenas. La temperatura puntual y el byte más frío o más caliente no son el mismo dato: el byte ya pasó por el realce de contraste.

Escala a °C

El píxel de la curva no es la cruz. Después de reordenar, el software toma la intensidad Ic en (ancho/2 - 1, alto/2 - 1). En 240×320 eso es (119, 159), un píxel arriba y a la izquierda de la cruz (120, 160).

Con las temperaturas todavía en décimas:

  • si la intensidad p es mayor o igual que Ic, la recta une (ancla caliente, máxima) con (Ic, central);
  • si es menor, une (Ic, central) con (ancla fría, mínima).
raw = p * (Tb - Ta) / (Ib - Ia) + (Ta * Ib - Tb * Ia) / (Ib - Ia)
°C  = raw / 10

(Ia, Ta) es el primer punto del tramo y (Ib, Tb) el segundo. Si el archivo está en Fahrenheit, este script pasa el resultado a Celsius con (°F - 32) / 1.8. El programa oficial, en ese caso, deja la primera matriz en la unidad del archivo y arma otra con valor * 1.8 + 32. En las capturas de images/ la unidad es °C, así que el CSV coincide con la matriz del programa.

El píxel de la curva queda, por construcción, en la temperatura central. La cruz no. En IMG 0001.bmp:

Intensidad °C
Curva (119, 159) 17 13,3
Cruz (120, 160) 16 12,84705882
Ancla fría 0 5,6
Píxel más frío de esa foto 1 6,05294118
Ancla caliente 253 21,6

La mínima del pie es 5,6 °C y la máxima 21,6 °C. El píxel más frío no llega a 5,6 °C porque la ancla fría está en la intensidad 0 y ese píxel vale 1.

Lo que no se puede recuperar

El sensor entrega bastante más que 8 bits. Antes de guardar, la cámara realza el contraste y estira el resultado a 240×320. Muchas temperaturas distintas caen en el mismo byte, y la tabla de ese realce no viaja en el archivo. Con tres puntos medidos se puede clavar la curva en la mínima, la máxima y el centro. Cualquier otro píxel sigue siendo una estimación, y otra curva que pase por los mismos tres puntos no está mejor medida.

El error acompaña el rango de la escena. Con menos de 2 °C de diferencia, como en IMG 0008.bmp o IMG 0031.bmp, queda por debajo de 0,1 °C. En IMG 0001.bmp la cruz ya difiere 0,45 °C de la medición central. En una escena de cientos de grados la diferencia es de decenas de grados.

IMG 0003.bmp guarda una máxima de 431,7 °C y la pantalla muestra OL. IMG 0004.bmp guarda 429,6 °C, por encima del rango de -20 °C a 400 °C publicado para esta cámara. Esos máximos están en el archivo, y la cámara no los trata como una lectura normal.

Para un punto que importe, la lectura que vale es la del puntero en la cámara.

Software oficial y otros parseos

UNI-T publica el UTi712S PC Software (junio de 2022, un Setup.exe de Windows dentro del zip). La lógica de este formato está en ImageFile.dll, en refreshParam y en el pasaje de intensidad a temperatura. Este repositorio no incluye ese instalador.

El programa oficial hace esta misma escala de dos tramos. No tiene un plano radiométrico escondido.

UNI-T Thermal Utilities documenta un BMP parecido, el de la UTi260B. No sirve para estos archivos: aquella cámara guarda BMP de 24 bits, sin los 3 bytes de relleno, y ordena primero el punto máximo. El autor describe el mismo límite en temperature_issue.md: la imagen embebida ya viene realzada, y en el postproceso solo se pueden fiar la mínima, la máxima y el centro.

Muestras

images/ tiene 32 BMP sacados de una UTi712S, de septiembre de 2020 a agosto de 2026. Todas entran en el formato de arriba, en modo 7 y en °C. Sirven para comprobar el parseo y la escala. No son una calibración.

Metadata

Release files for uti712s 0.1.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for uti712s 0.1.1
File Size Uploaded Provenance Actions
uti712s-0.1.1.tar.gz 15.2 kB Without provenance Details for uti712s-0.1.1.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for uti712s 0.1.1
File Interpreter ABI Platform Actions
uti712s-0.1.1-py3-none-any.whl Python 3 none any Details for uti712s-0.1.1-py3-none-any.whl

Total release size: 30.9 kB

Release files / uti712s-0.1.1.tar.gz

Download URL uti712s-0.1.1.tar.gz
Size 15.2 kB
Tags Source
SHA-256 checksum
How to use checksums
2a0e2ebe06454a1efe9337afe80bf287984869be81041ea96bd4d93ed1186bd2
BLAKE2b-256 checksum
How to use checksums
417896c6bf5a8ee2904b445e7fb390d3b5254cd5ba7c8462e870f4d60c0be312
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.4

Release files / uti712s-0.1.1-py3-none-any.whl

Download URL uti712s-0.1.1-py3-none-any.whl
Size 15.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
d48bbd144c6a97b94f42263ed611441ff50f0878f14e335d3932568ef30dd68c
BLAKE2b-256 checksum
How to use checksums
b4b98c822ea2eea1d31725c438024948f44a9f209f83a890366d04ca176c5887
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.4

Security for uti712s 0.1.1

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page