FireMapper — Session Post-Processing

User manual for converting a raw capture session into mapping-ready imagery.

For every image it captures, FireMapper writes a small .json file alongside it containing the GPS position, platform/IMU attitude, lens parameters and timing. These tools read those files and:

Original files are never modified. Every step writes its results to a new folder.

Getting started

  1. Ensure Python 3 is installed, together with the required packages:
    pip install Pillow numpy tkintermapview requests
  2. Place the four scripts (firemapper_gui.py, embed_metadata.py, stretch_thermal.py, session_map.py) in a single folder. Locating them alongside your session folders (or alongside a parent folder that groups several flight strips) allows the program to detect your data automatically.
  3. Start the application:
    python firemapper_gui.py
    A window opens with three tabs. Select a tab, review the on-screen description, set the options, and start the operation.

The program detects session folders automatically: any folder containing a thermal/ directory, a cam…/ directory, or a manifest.json file is treated as a session. Grouping folders (for example Streifen/) are also scanned one level deep.

Tab 1 Embed GPS & Metadata

Writes each image's JSON data into a tagged copy of the file: GPS position, true camera pointing direction, capture time (UTC), lens and exposure, and the complete JSON record in the comment field. The copies are compatible with Pix4D, Metashape, QGIS and similar applications.

How to use

  1. Session folder — pre-filled with the most recent session, or selected via Browse….
  2. Output folder — if left blank, results are written to <session>_exif beside the session.
  3. GPS sourceFused INS (position) provides the highest accuracy (recommended); Raw GNSS (gps) uses the uncorrected satellite fix. Thermal frames always use raw GNSS.
  4. Parallel workers — the number of images copied and tagged concurrently (default: derived from the available CPU cores). Higher values are faster on SSD/NVMe storage.
  5. Click Embed metadata. A progress bar and log are displayed; on completion the output folder can be opened.

Requires exiftool, which is located automatically and installed on first use if it is not already present (Windows). Leave the “exiftool path” field blank.

Tab 2 Thermal Stretch

The thermal camera records 16-bit radiometric frames that occupy only a small portion of the available range; consequently the raw files appear nearly black and vary in brightness from frame to frame. This step determines a single brightness window for the entire session and rescales every frame into it, producing viewable 8-bit images. Because all frames share one window, warm and cool areas remain consistent across the flight.

Pixel values represent radiometric signal (proportional to temperature), not calibrated degrees.

Options

Paletteinferno / ironbow — thermal colour maps (dark = cool, bright = hot); gray — plain grayscale.
Window low % / high %The brightness window, expressed as percentiles pooled across the whole session (default 1–99 %). Decrease the high % or increase the low % for greater contrast; enable Absolute min/max to use the true extremes.
Embed metadataWhen enabled (default), the stretched PNGs also receive GPS and orientation EXIF, making them self-contained.
Parallel workersThe number of frames rendered and tagged concurrently (default: derived from the available CPU cores). Higher values are faster on SSD/NVMe storage.

How to use

  1. Select the session folder and palette.
  2. Click Preview palettes to compare gray, inferno and ironbow on a sample frame before processing.
  3. Click Stretch all frames. Output is written to <session>/thermal_stretched unless an output folder is specified.

Tab 3 Map

Plots each image as a trigger point (its GPS position) and, optionally, as an oblique footprint — the area of ground the image covers — on OpenStreetMap. Cameras are shown in blue, thermal in orange.

How to use

  1. Select the sessions to display (use All/None; Refresh rescans the folder). Several flight strips may be shown together.
  2. Set the options (described below), then click Show on map. The map zooms to fit the data.
  3. For a complete view, click Open full map in browser. This renders every trigger point and footprint (the in-app map thins dense flights for speed) on an interactive page in your web browser, with marker clustering and a panel to toggle individual sessions on and off and to switch each camera's footprints separately (cam25, cam45 and thermal each have their own colour). Click any point or footprint to see its metadata.

Options

Ground elev (m)Terrain height used to project the footprints (flat-ground assumption). Default 110 m; set this to the elevation of your site.
Thermal FOV H/VField of view of the thermal camera, required for its footprints. Pre-filled for the FLIR A65 25° lens (25° × 20°).
Thermal off-nadirMounting tilt of the thermal camera (0 = straight down).
Plot every NthApplies to the in-app Show on map only: auto reduces very large surveys so the embedded map remains responsive; enter a number to override. Open full map in browser ignores this and shows everything.
Trigger points / Footprints / Cameras / ThermalControl which layers are drawn.
Needs an internet connection for the map tiles.

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.

The footprints assume flat ground at the elevation you specify. If the entire swath appears on the wrong side of the flight line relative to reality, flip the SCAN_SIGN setting at the top of session_map.py.

Command line (optional)

The embed and stretch steps may also be run without the graphical interface:

python embed_metadata.py [SESSION] [--out DIR] [--gps-source position|gps]
                         [--workers N] [--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] [--workers N] [--sample]

If SESSION is omitted, the most recent session found nearby is used. --workers sets the number of parallel workers (default: derived from the CPU core count).

Troubleshooting

“exiftool could not be found” Install it once: winget install OliverBetz.ExifTool (or choco install exiftool), then restart the application.
Stretched or embedded images have no GPS exiftool writes metadata via a temporary copy, so a full (or nearly full) disk can drop the GPS tag. Free up disk space and run the step again. The tools verify that GPS was written and report a clear error rather than producing files without it.
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.