Structural integrity triage for offshore assets — the model classifies, it never measures.
Drone and ROV inspection photos go in. What comes out is a typed, severity-ranked list of defects tied to the exact structural zone they were found in, a temporal comparison against the previous inspection, and a PDF an engineer can actually sign off on.
Phase 1 is complete and the application runs. You can register structures and zones, upload inspection imagery, have it classified by Claude vision, browse findings on a dashboard with charts and a map, compare two inspections of the same zone, and download a technical PDF.
What is not there, said plainly: there is no authentication. Every endpoint is open, including the two that spend money on API calls. This is a single-operator local tool today — do not expose it to a network you do not control. Quantitative measurement does not exist either, by design; see the golden rule below.
An offshore inspection campaign produces thousands of photographs. A structural engineer looks at them one by one, writes findings into a spreadsheet, and tries to remember what the same weld looked like eight months ago. The bottleneck is not flying the drone — it is the days of manual triage afterwards, and the comparison across time that nobody has the patience to do properly.
The language model classifies. It never produces a number that an engineer might act on.
Claude decides what a defect is (one of twelve types), how severe it looks on a 1–5 scale, and how confident it is. It is explicitly forbidden — in the prompt, and by validation on the way into the database — from estimating physical dimensions, affected-area percentages or growth rates.
This is not caution for its own sake. A hallucinated bounding box is a visual annotation an
engineer will re-check anyway. A hallucinated "12.4% section loss" is a number that walks into
an integrity report and gets trusted. Deterministic measurement (YOLOv8 / SAM / OpenCV) is
Phase 2, and it will write to its own measurements table — never through the model.
For the same reason, bounding boxes drawn in Phase 1 are labelled approximate everywhere they appear: in the dashboard, in the viewer, and in the PDF.
Classification. Twelve defect types (surface / pitting / general corrosion, cracking, deformation, coating degradation, fouling, leaks, structural damage, missing components, cable wear, generic anomaly), each with a 1–5 severity and a confidence score. Findings are stored against the image, which is bound to a zone, which belongs to a structure — so a finding always has a location, not just a filename.
Structured output, not prompt-and-pray. Analysis and comparison both use the Claude API's
structured output format, so the response is schema-valid JSON by construction. Range limits the
schema cannot express (severity 1–5, confidence 0–1, four-element boxes) are validated in
parse_analysis() and enforced again by CHECK constraints in SQLite.
Temporal comparison. Two inspections of the same zone are compared qualitatively: what is new, what is gone, what changed severity. No growth rates — see the golden rule.
Reporting. A WeasyPrint PDF with a cover sheet, an executive summary by severity, the full findings table, the comparison against the previous inspection, and a photographic annex with bounding boxes drawn on the imagery. It carries a disclaimer stating it does not replace a certified inspector.
Design decisions that exist because of where this runs, not because of taste:
- The dashboard works with no internet. Chart.js and Leaflet are vendored into the repo, and the map draws its own dark grid layer instead of calling a tile server. On a vessel with a satellite link, an external CDN request is a blank page.
- Bad bandwidth is assumed. The Anthropic client is configured with retries and a long timeout, and batch analysis runs as a sequential queue that a single failed image cannot kill.
- SQLite, one file. No database server to install on a machine nobody can SSH into.
python -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install -r requirements.txt
cp .env.example .env # then put your ANTHROPIC_API_KEY in it
uvicorn app.main:app --reloadDashboard at http://127.0.0.1:8000. The schema is created on first start.
PDF export needs WeasyPrint's system libraries (GTK/Pango). The import is deferred, so if they
are missing the rest of the API still starts — only /report.pdf fails.
python -m pytest -qTwenty tests covering the upload guards, connection handling, rollback when the disk write fails, the findings filter, model response validation and PDF rendering. They run offline — nothing in the tested paths calls the Claude API.
The PDF test skips on a machine without WeasyPrint's system libraries, so on Windows expect nineteen passed and one skipped. CI runs the full set on Linux.
| Method | Path | Purpose |
|---|---|---|
GET POST PUT DELETE |
/structures, /zones, /inspections |
Reference data |
POST |
/images/upload |
Upload imagery (multipart) |
POST |
/images/{id}/analyze |
Analyse one image |
POST |
/inspections/{id}/analyze-all |
Queue a whole inspection |
GET |
/inspections/{id}/status |
Queue counters |
GET |
/findings |
Filter by structure, zone, type, severity, inspection, image |
PATCH |
/findings/{id}/verify |
Engineer confirms a finding |
GET |
/zones/{id}/timeline |
Severity over time |
POST |
/compare |
Qualitative comparison of two inspections |
GET |
/inspections/{id}/report.pdf |
Technical PDF |
Interactive docs at /docs.
Phase 1 — done. Classification, zoning, dashboard, qualitative comparison, PDF.
Phase 2 — quantitative measurement. YOLOv8 for pixel-accurate localisation, SAM plus OpenCV
for affected-area computation, writing to the measurements table that the schema already
reserves. This is where numbers become real, and it does not involve the language model.
Not scheduled yet. Authentication and multi-user access, EXIF-based automatic geolocation, and a corrosion-growth model across three or more inspections.
A triage aid, not an engineering assessment. Every AI-generated finding requires confirmation by a qualified professional, and this tool does not replace a certified inspector or a structural integrity report.
MIT — see LICENSE.