FireMapper_Postprocess/manual.html

238 lines
13 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>FireMapper — Session Post-Processing — User Manual</title>
<style>
:root{
--fg:#1c2230; --muted:#5b6473; --bg:#f6f7f9; --card:#ffffff; --line:#e2e6ec;
--accent:#1565c0; --accent2:#e65100; --code:#0f172a; --codebg:#f0f2f5;
}
*{box-sizing:border-box}
body{margin:0;background:var(--bg);color:var(--fg);
font:16px/1.6 "Segoe UI",system-ui,Arial,sans-serif}
header{background:linear-gradient(135deg,#1565c0,#e65100);color:#fff;padding:34px 24px}
header .wrap{max-width:900px;margin:0 auto}
header h1{margin:0 0 6px;font-size:28px}
header p{margin:0;opacity:.92}
main{max-width:900px;margin:0 auto;padding:24px}
nav{background:var(--card);border:1px solid var(--line);border-radius:10px;
padding:14px 18px;margin:22px 0}
nav b{display:block;color:var(--muted);font-size:13px;text-transform:uppercase;
letter-spacing:.04em;margin-bottom:6px}
nav a{color:var(--accent);text-decoration:none;margin-right:16px;white-space:nowrap}
nav a:hover{text-decoration:underline}
section{background:var(--card);border:1px solid var(--line);border-radius:12px;
padding:20px 24px;margin:18px 0}
h2{margin:.2em 0 .6em;font-size:22px;border-bottom:2px solid var(--line);padding-bottom:8px}
h3{margin:1.2em 0 .4em;font-size:17px;color:var(--accent)}
code,kbd{background:var(--codebg);border-radius:4px;padding:1px 6px;font-family:Consolas,monospace;font-size:.92em}
pre{background:var(--code);color:#e6edf3;border-radius:8px;padding:14px 16px;overflow:auto;font-size:13px}
pre code{background:none;color:inherit;padding:0}
ol,ul{padding-left:22px}
li{margin:4px 0}
table{border-collapse:collapse;width:100%;margin:10px 0;font-size:14.5px}
th,td{border:1px solid var(--line);padding:8px 10px;text-align:left;vertical-align:top}
th{background:var(--codebg)}
.pill{display:inline-block;border-radius:999px;padding:1px 10px;font-size:13px;font-weight:600;color:#fff}
.blue{background:var(--accent)} .orange{background:var(--accent2)}
.note{border-left:4px solid var(--accent);background:#eef4fc;padding:10px 14px;border-radius:6px;margin:12px 0}
.warn{border-left:4px solid var(--accent2);background:#fdf0e6;padding:10px 14px;border-radius:6px;margin:12px 0}
.muted{color:var(--muted)}
footer{max-width:900px;margin:0 auto;padding:10px 24px 40px;color:var(--muted);font-size:13px}
.step{counter-reset:none}
</style>
</head>
<body>
<header><div class="wrap">
<h1>FireMapper — Session Post-Processing</h1>
<p>User manual for converting a raw capture session into mapping-ready imagery.</p>
</div></header>
<main>
<p>For every image it captures, FireMapper writes a small <code>.json</code> file alongside
it containing the GPS position, platform/IMU attitude, lens parameters and timing. These
tools read those files and:</p>
<ul>
<li><b>Embed</b> the data into each image's EXIF/XMP so that mapping software can position
it geographically;</li>
<li><b>Stretch</b> the low-contrast 16-bit thermal frames into clear colour images;</li>
<li><b>Map</b> the trigger points and image footprints on OpenStreetMap.</li>
</ul>
<p class="note"><b>Original files are never modified.</b> Every step writes its results to a
new folder.</p>
<nav>
<b>Contents</b>
<a href="#start">Getting started</a>
<a href="#embed">1 · Embed</a>
<a href="#thermal">2 · Thermal</a>
<a href="#map">3 · Map</a>
<a href="#cli">Command line</a>
<a href="#trouble">Troubleshooting</a>
</nav>
<section id="start">
<h2>Getting started</h2>
<ol>
<li>Ensure Python 3 is installed, together with the required packages:
<pre><code>pip install Pillow numpy tkintermapview requests</code></pre></li>
<li>Place the four scripts (<code>firemapper_gui.py</code>, <code>embed_metadata.py</code>,
<code>stretch_thermal.py</code>, <code>session_map.py</code>) 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.</li>
<li>Start the application:
<pre><code>python firemapper_gui.py</code></pre>
A window opens with three tabs. Select a tab, review the on-screen description, set the
options, and start the operation.</li>
</ol>
<p class="muted">The program detects session folders automatically: any folder containing a
<code>thermal/</code> directory, a <code>cam…/</code> directory, or a
<code>manifest.json</code> file is treated as a session. Grouping folders (for example
<code>Streifen/</code>) are also scanned one level deep.</p>
</section>
<section id="embed">
<h2><span class="pill blue">Tab 1</span> Embed GPS &amp; Metadata</h2>
<p>Writes each image's JSON data into a tagged <b>copy</b> 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.</p>
<h3>How to use</h3>
<ol>
<li><b>Session folder</b> — pre-filled with the most recent session, or selected via
<kbd>Browse…</kbd>.</li>
<li><b>Output folder</b> — if left blank, results are written to
<code>&lt;session&gt;_exif</code> beside the session.</li>
<li><b>GPS source</b><i>Fused INS (position)</i> provides the highest accuracy
(recommended); <i>Raw GNSS (gps)</i> uses the uncorrected satellite fix. Thermal
frames always use raw GNSS.</li>
<li><b>Parallel workers</b> — the number of images copied and tagged concurrently
(default: derived from the available CPU cores). Higher values are faster on
SSD/NVMe storage.</li>
<li>Click <b>Embed metadata</b>. A progress bar and log are displayed; on completion the
output folder can be opened.</li>
</ol>
<p class="muted">Requires <b>exiftool</b>, which is located automatically and installed on
first use if it is not already present (Windows). Leave the “exiftool path” field blank.</p>
</section>
<section id="thermal">
<h2><span class="pill orange">Tab 2</span> Thermal Stretch</h2>
<p>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 <b>a single brightness window for the
entire session</b> 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.</p>
<div class="note">Pixel values represent radiometric <b>signal</b> (proportional to
temperature), not calibrated degrees.</div>
<h3>Options</h3>
<table>
<tr><th>Palette</th><td><b>inferno</b> / <b>ironbow</b> — thermal colour maps (dark = cool,
bright = hot); <b>gray</b> — plain grayscale.</td></tr>
<tr><th>Window low % / high %</th><td>The brightness window, expressed as percentiles
pooled across the whole session (default 199 %). Decrease the high % or increase the
low % for greater contrast; enable <b>Absolute min/max</b> to use the true extremes.</td></tr>
<tr><th>Embed metadata</th><td>When enabled (default), the stretched PNGs also receive
GPS and orientation EXIF, making them self-contained.</td></tr>
<tr><th>Parallel workers</th><td>The number of frames rendered and tagged concurrently
(default: derived from the available CPU cores). Higher values are faster on SSD/NVMe
storage.</td></tr>
</table>
<h3>How to use</h3>
<ol>
<li>Select the <b>session folder</b> and <b>palette</b>.</li>
<li>Click <b>Preview palettes</b> to compare gray, inferno and ironbow on a sample
frame before processing.</li>
<li>Click <b>Stretch all frames</b>. Output is written to
<code>&lt;session&gt;/thermal_stretched</code> unless an output folder is specified.</li>
</ol>
</section>
<section id="map">
<h2><span class="pill blue">Tab 3</span> Map</h2>
<p>Plots each image as a <b>trigger point</b> (its GPS position) and, optionally, as an
<b>oblique footprint</b> — the area of ground the image covers — on OpenStreetMap.
Cameras are shown in <span class="pill blue">blue</span>, thermal in
<span class="pill orange">orange</span>.</p>
<h3>How to use</h3>
<ol>
<li><b>Select the sessions</b> to display (use <kbd>All</kbd>/<kbd>None</kbd>;
<kbd>Refresh</kbd> rescans the folder). Several flight strips may be shown together.</li>
<li>Set the <b>options</b> (described below), then click <b>Show on map</b>. The map
zooms to fit the data.</li>
<li>For a complete view, click <b>Open full map in browser</b>. This renders
<b>every</b> 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.</li>
</ol>
<h3>Options</h3>
<table>
<tr><th>Ground elev (m)</th><td>Terrain height used to project the footprints (flat-ground
assumption). Default 110 m; set this to the elevation of your site.</td></tr>
<tr><th>Thermal FOV H/V</th><td>Field of view of the thermal camera, required for its
footprints. Pre-filled for the FLIR A65 25° lens (25° × 20°).</td></tr>
<tr><th>Thermal off-nadir</th><td>Mounting tilt of the thermal camera (0 = straight down).</td></tr>
<tr><th>Plot every Nth</th><td>Applies to the in-app <b>Show on map</b> only: <i>auto</i>
reduces very large surveys so the embedded map remains responsive; enter a number to
override. <b>Open full map in browser</b> ignores this and shows everything.</td></tr>
<tr><th>Trigger points / Footprints / Cameras / Thermal</th><td>Control which layers are drawn.</td></tr>
</table>
<div class="note"><b>Needs an internet connection</b> for the map tiles.</div>
<h3>How footprints are computed</h3>
<p>The footprint is projected from the true camera pointing direction: the aircraft
attitude, plus the platform's left/right swivel (<code>platform_angle_deg</code>), 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.</p>
<div class="warn">The footprints assume flat ground at the elevation you specify. If the
entire swath appears on the <b>wrong side</b> of the flight line relative to reality, flip
the <code>SCAN_SIGN</code> setting at the top of <code>session_map.py</code>.</div>
</section>
<section id="cli">
<h2>Command line (optional)</h2>
<p>The embed and stretch steps may also be run without the graphical interface:</p>
<pre><code>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]</code></pre>
<p class="muted">If <code>SESSION</code> is omitted, the most recent session found nearby is
used. <code>--workers</code> sets the number of parallel workers (default: derived from the
CPU core count).</p>
</section>
<section id="trouble">
<h2>Troubleshooting</h2>
<table>
<tr><th>“exiftool could not be found”</th>
<td>Install it once: <code>winget install OliverBetz.ExifTool</code> (or
<code>choco install exiftool</code>), then restart the application.</td></tr>
<tr><th>Stretched or embedded images have no GPS</th>
<td>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.</td></tr>
<tr><th>Map is blank / tiles don't load</th>
<td>The map needs internet access for OpenStreetMap tiles.</td></tr>
<tr><th>No sessions in the Map list</th>
<td>Click <kbd>Refresh</kbd>. Make sure the scripts are in (or next to) the folder
that holds your session folders.</td></tr>
<tr><th>Footprints / headings look mirrored</th>
<td>Flip <code>SCAN_SIGN</code> at the top of <code>session_map.py</code>.</td></tr>
<tr><th>Thermal footprints missing</th>
<td>Fill in the <b>Thermal FOV</b> fields on the Map tab.</td></tr>
</table>
</section>
</main>
<footer>FireMapper — Session Post-Processing · GGS Speyer. Original files are never modified;
all results are written to new folders.</footer>
</body>
</html>