FireMapper records, for every photo, a small .json file next to it
containing GPS position, platform/IMU attitude, lens and timing. These tools read those
files and:
- Embed the data into the photos' EXIF/XMP so mapping software can place each image on the map;
- Stretch the dark 16-bit thermal frames into easy-to-view colour images;
- Map the trigger points and image footprints on OpenStreetMap.
Your originals are never changed. Every step writes results into a new folder.
Getting started
- Make sure Python 3 is installed, plus the packages:
pip install Pillow numpy tkintermapview requests - Put the four scripts (
firemapper_gui.py,embed_metadata.py,stretch_thermal.py,session_map.py) in one folder. Placing them next to your session folders (or next to a parent folder that groups several flight strips) lets the program find your data automatically. - Start the program:
A window opens with three tabs. Pick a tab, read the on-screen description, fill in the options, and click the button.python firemapper_gui.py
The program finds session folders automatically — any folder that
contains a thermal/, a cam…/ folder or a
manifest.json counts as a session, and it also looks one level inside
grouping folders (e.g. Streifen/).
Tab 1 Embed GPS & Metadata
Writes each photo's JSON data into a tagged copy of the image: GPS position, true camera pointing direction, capture time (UTC), lens & exposure, and the full JSON in the comment field. The copies drop straight into Pix4D, Metashape, QGIS, etc.
How to use
- Session folder — auto-filled with the newest session; or click Browse….
- Output folder — leave blank to write to
<session>_exifnext to the session. - GPS source — Fused INS (position) is the most accurate (recommended); Raw GNSS (gps) uses the bare satellite fix. Thermal frames always use raw GNSS.
- Click Embed metadata. Progress and a log appear; when done you can open the output folder.
Requires exiftool. It is found automatically, and installed for you the first time if missing (Windows). Leave the “exiftool path” field blank.
Tab 2 Thermal Stretch
The thermal camera records 16-bit radiometric frames whose values fill only a tiny part of the range, so the raw files look almost black and flicker between frames. This finds one brightness window shared by the whole session and stretches every frame into it, saving easy-to-view 8-bit images. Because all frames use the same window, hot and cold areas stay consistent across the flight.
Options
| Palette | inferno / ironbow — heat colour maps (dark = cool, bright = hot); gray — plain grayscale. |
|---|---|
| Window low % / high % | The brightness window, as percentiles pooled over the whole session (default 1–99 %). Lower the high % / raise the low % for more contrast; tick Absolute min/max to use the true extremes. |
| Embed metadata | When ticked (default), the stretched PNGs also get GPS and orientation EXIF written in, so they are self-contained. |
How to use
- Pick the session folder and palette.
- Click Preview palettes to compare gray / inferno / ironbow on a sample frame before committing.
- Click Stretch all frames. Output goes to
<session>/thermal_stretchedunless you set an output folder.
Tab 3 Map
Plots each photo as a trigger point (its GPS position) and, optionally, an oblique footprint — the patch of ground the photo covers — on OpenStreetMap. Cameras are blue, thermal is orange.
How to use
- Tick the sessions to plot (use All/None; Refresh rescans the folder). Several flight strips can be shown together.
- Set the options (see below), then click Show on map. The map zooms to fit the data.
Options
| Ground elev (m) | Terrain height used to project the footprints (flat-ground assumption). Default 110 m — set this to your site's elevation. |
|---|---|
| Thermal FOV H/V | Field of view of the thermal camera, needed for its footprints. Pre-filled for the FLIR A65 25° lens (25° × 20°). |
| Thermal off-nadir | Mounting tilt of the thermal camera (0 = straight down). |
| Plot every Nth | auto thins very large surveys so the map stays responsive; set a number to override. |
| Trigger points / Footprints / Cameras / Thermal | Toggle what is drawn. |
How footprints are computed
The footprint is projected from the true camera pointing direction: the aircraft
attitude, plus the platform's left/right swivel (platform_angle_deg), plus
each camera's fixed mounting — thermal looks straight down (mounted vertical to the
flight line); the RGB cameras look forward-and-down by their off-nadir angle
(cam25 = 25°, cam45 = 45°) and are mounted landscape across the flight line.
SCAN_SIGN setting in session_map.py.Command line (optional)
The embed and stretch steps also run without the GUI:
python embed_metadata.py [SESSION] [--out DIR] [--gps-source position|gps] [--dry-run]
python stretch_thermal.py [SESSION] [--colormap inferno|ironbow|gray]
[--lo-pct 1 --hi-pct 99 | --absolute | --lo N --hi N]
[--out DIR] [--no-embed-exif] [--sample]
With no SESSION they use the newest session found nearby.
Troubleshooting
| “exiftool could not be found” | Install it once: winget install OliverBetz.ExifTool (or
choco install exiftool), then reopen the program. |
|---|---|
| Map is blank / tiles don't load | The map needs internet access for OpenStreetMap tiles. |
| No sessions in the Map list | Click Refresh. Make sure the scripts are in (or next to) the folder that holds your session folders. |
| Footprints / headings look mirrored | Flip SCAN_SIGN at the top of session_map.py. |
| Thermal footprints missing | Fill in the Thermal FOV fields on the Map tab. |