FireMapper_Postprocess/manual.html

215 lines
11 KiB
HTML
Raw 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 turning a raw capture session into mapping-ready imagery.</p>
</div></header>
<main>
<p>FireMapper records, for every photo, a small <code>.json</code> file next to it
containing GPS position, platform/IMU attitude, lens and timing. These tools read those
files and:</p>
<ul>
<li><b>Embed</b> the data into the photos' EXIF/XMP so mapping software can place each
image on the map;</li>
<li><b>Stretch</b> the dark 16-bit thermal frames into easy-to-view colour images;</li>
<li><b>Map</b> the trigger points and image footprints on OpenStreetMap.</li>
</ul>
<p class="note"><b>Your originals are never changed.</b> Every step writes results into 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>Make sure Python 3 is installed, plus the packages:
<pre><code>pip install Pillow numpy tkintermapview requests</code></pre></li>
<li>Put the four scripts (<code>firemapper_gui.py</code>, <code>embed_metadata.py</code>,
<code>stretch_thermal.py</code>, <code>session_map.py</code>) 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.</li>
<li>Start the program:
<pre><code>python firemapper_gui.py</code></pre>
A window opens with three tabs. Pick a tab, read the on-screen description, fill in
the options, and click the button.</li>
</ol>
<p class="muted">The program finds session folders automatically — any folder that
contains a <code>thermal/</code>, a <code>cam…/</code> folder or a
<code>manifest.json</code> counts as a session, and it also looks one level inside
grouping folders (e.g. <code>Streifen/</code>).</p>
</section>
<section id="embed">
<h2><span class="pill blue">Tab 1</span> Embed GPS &amp; Metadata</h2>
<p>Writes each photo's JSON data into a tagged <b>copy</b> of the image: GPS position,
true camera pointing direction, capture time (UTC), lens &amp; exposure, and the full
JSON in the comment field. The copies drop straight into Pix4D, Metashape, QGIS, etc.</p>
<h3>How to use</h3>
<ol>
<li><b>Session folder</b> — auto-filled with the newest session; or click
<kbd>Browse…</kbd>.</li>
<li><b>Output folder</b> — leave blank to write to <code>&lt;session&gt;_exif</code>
next to the session.</li>
<li><b>GPS source</b><i>Fused INS (position)</i> is the most accurate (recommended);
<i>Raw GNSS (gps)</i> uses the bare satellite fix. Thermal frames always use raw GNSS.</li>
<li>Click <b>Embed metadata</b>. Progress and a log appear; when done you can open the
output folder.</li>
</ol>
<p class="muted">Requires <b>exiftool</b>. It is found automatically, and installed for
you the first time if missing (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 whose values fill only a tiny
part of the range, so the raw files look almost black and flicker between frames. This
finds <b>one brightness window shared by the whole session</b> 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.</p>
<div class="note">Values are 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> — heat colour maps (dark = cool,
bright = hot); <b>gray</b> — plain grayscale.</td></tr>
<tr><th>Window low % / high %</th><td>The brightness window, as percentiles pooled over
the whole session (default 199 %). Lower the high % / raise the low % for more
contrast; tick <b>Absolute min/max</b> to use the true extremes.</td></tr>
<tr><th>Embed metadata</th><td>When ticked (default), the stretched PNGs also get GPS
and orientation EXIF written in, so they are self-contained.</td></tr>
</table>
<h3>How to use</h3>
<ol>
<li>Pick the <b>session folder</b> and <b>palette</b>.</li>
<li>Click <b>Preview palettes</b> to compare gray / inferno / ironbow on a sample
frame before committing.</li>
<li>Click <b>Stretch all frames</b>. Output goes to
<code>&lt;session&gt;/thermal_stretched</code> unless you set an output folder.</li>
</ol>
</section>
<section id="map">
<h2><span class="pill blue">Tab 3</span> Map</h2>
<p>Plots each photo as a <b>trigger point</b> (its GPS position) and, optionally, an
<b>oblique footprint</b> — the patch of ground the photo covers — on OpenStreetMap.
Cameras are <span class="pill blue">blue</span>, thermal is
<span class="pill orange">orange</span>.</p>
<h3>How to use</h3>
<ol>
<li><b>Tick the sessions</b> to plot (use <kbd>All</kbd>/<kbd>None</kbd>; <kbd>Refresh</kbd>
rescans the folder). Several flight strips can be shown together.</li>
<li>Set the <b>options</b> (see below), then click <b>Show on map</b>. The map zooms to
fit the data.</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 your site's elevation.</td></tr>
<tr><th>Thermal FOV H/V</th><td>Field of view of the thermal camera, needed 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><i>auto</i> thins very large surveys so the map stays
responsive; set a number to override.</td></tr>
<tr><th>Trigger points / Footprints / Cameras / Thermal</th><td>Toggle what is 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 set. If the whole
swath appears on the <b>wrong side</b> of the flight line compared to reality, ask your
developer to flip the <code>SCAN_SIGN</code> setting in <code>session_map.py</code>.</div>
</section>
<section id="cli">
<h2>Command line (optional)</h2>
<p>The embed and stretch steps also run without the GUI:</p>
<pre><code>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]</code></pre>
<p class="muted">With no <code>SESSION</code> they use the newest session found nearby.</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 reopen the program.</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. Originals are never modified;
all results are written to new folders.</footer>
</body>
</html>