Skip to content

Universal viewer with Topdon TC002C Duo radiometric support#29

Open
AronNovak wants to merge 5 commits into
leswright1977:mainfrom
AronNovak:tc002c-duo-radiometric
Open

Universal viewer with Topdon TC002C Duo radiometric support#29
AronNovak wants to merge 5 commits into
leswright1977:mainfrom
AronNovak:tc002c-duo-radiometric

Conversation

@AronNovak

@AronNovak AronNovak commented Jun 11, 2026

Copy link
Copy Markdown

Adds src/thermalcam.py, a camera-agnostic rewrite of tc001v4.2.py that also works with newer InfiRay/Topdon models (tested on a TC002C Duo).

  • Auto-detects the camera on the USB bus and its frame geometry (no --device).
  • Real temperatures by auto-selecting the radiometric mode: TC001 256x384 (/64) and TC002C Duo 512x484 (/16, which also gives a clean 512×384 image). Relative fallback otherwise, clearly labelled.
  • Robustness fixes these cameras need on Linux: CAP_PROP_BUFFERSIZE=1 (OpenCV returns desynced buffers), VIDIOC_ENUM_FRAMESIZES (opening an unsupported mode desyncs the stream), skip desynced frames, telemetry trim, fixed-pattern-noise removal.
  • Keeps colormaps/HUD/recording/snapshots; adds a headless --selftest.
  • docs/TC002C-DUO.md documents the frame layout and the reverse-engineered vendor command protocol; src/thermal_protocol.py is an experimental (dry-run) module for optional NUC/calibration.

The original tc001v4.2.py is left untouched.

AronNovak and others added 5 commits June 11, 2026 10:34
New src/thermalcam.py auto-detects InfiRay/Topdon USB thermal cameras and
decodes real temperatures: TC001 (256x384, /64) and TC002C Duo (512x484, /16,
which also yields a clean 512x384 image), with a labelled relative fallback
otherwise. Adds docs/TC002C-DUO.md (frame layout + reverse-engineered vendor
protocol), requirements.txt, and an experimental command module.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- src/thermal_bridge.py: serve the parsed/colormapped thermal image as an
  MJPEG-over-HTTP stream so any app (OpenCV, ffmpeg, browser) can consume it
  like a webcam, no dependency.
- thermalcam: --rotate / --flip (live 'o' key) and a clean colormap_frame()
  method (overlay-free) used by the bridge.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
These cameras occasionally emit a horizontally-tiled/desynced frame. The frame
validity check only looked at the temperature band, so such frames slipped
through as garbage. Add an image-band alignment guard (mean-abs-difference vs a
shifted copy; gradients and flat scenes are exempt) so the viewer and the MJPEG
bridge never emit them. The bridge also reopens the camera after a run of
unusable frames to recover from a stuck desync.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Reproduce the InfiRay temperature-correction math on Linux from the Android
libadvirtemp tables, so the camera can report true object °C off-device:

- tables.py extracts the embedded float64 ems/distance/target-temp LUTs into
  adv_tables.npz via a self-contained ELF reader.
- corrector.py: graybody emissivity / reflected-temp inversion (temp_correct),
  round-trip validated <1e-6 °C against the decoded inverse; temperature-dependent
  effective-emissivity LUT; Magnus vapour pressure.
- profile.py: per-unit JSON profile (keyed by USB serial) with scene defaults and
  NUC/kt/bt slots filled at provisioning.

Vendor-protocol read of per-unit NUC/kt/bt is still to come.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Open the camera's 8x12578 mode (header + 256x192 temperature plane +
image) and decode temperature as raw/64 - K, validated against the
official app to 0.1 °C (the captured frame's app min/max/avg 22.6/34.7/
27.8 reproduce exactly). radiometry/duo.py + thermalcam auto-detect/wiring;
white_hot grayscale palette default for cleaner detector input.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant