v1.0.0 Apache-2.0 · Windows & Linux · offline-first

Enhance the image.
Never lose track of what is real.

ForensicVision is a native desktop workstation for forensic image analysis and enhancement. It imports evidence under a documented chain of custody, measures what is wrong with an image, proposes a restoration pipeline for you to review, and produces a report that states exactly what was done — and what it does not prove.

Licence: Apache-2.0 Python 3.11+ GUI: PyQt5 291 tests passing Offline first, no telemetry
ForensicVision — CASE-0007 · forecourt camera 04
The ForensicVision main window: evidence loaded in the viewer, the Inspector open on the Case tab, and the status bar showing Forensic Safe Mode enabled.
The problem it exists to solve

A model asked for a licence plate will give you a licence plate

Crisp, confident, and possibly not the one that was there. Image enhancement in a forensic context is dangerous in one specific way: a learned model can produce a result that looks like recovered detail but is actually invented. Every part of ForensicVision is built around keeping that distinction visible.

Classical Deterministic DSP

  • Cannot invent detail. Every output sample derives from measured input samples.
  • No download required — all ten operators work the moment you pip install.
  • Listed in reports as deterministic.
  • Non-local means, bilateral, Wiener, Richardson–Lucy, CLAHE, Lanczos, unsharp mask, dark-channel dehaze, deblocking, exposure correction.

Neural Learned prior

  • Usually can invent detail — what it adds comes from the training distribution, not from this frame. Four of the twenty-two declare that they cannot; see below.
  • Weights are never downloaded silently — you approve each one after seeing its licence, size, digest and source.
  • Flagged may synthesise in the database, the sidecar and the report.
  • Real-ESRGAN, SwinIR, Restormer, FBCNN, DnCNN, NAFNet, CodeFormer, Zero-DCE.
The distinction is declared once and surfaces everywhere

A single may_synthesise flag on each model drives the restoration panel, the pipeline review dialog, the confirmation prompt, the case-tree colouring, the provenance sidecar, the database row and the PDF report. There is no second place where it could be forgotten.

Kind and synthesis are two axes, not one

Four of the twenty-two neural models are declared incapable of synthesising, and the reason is structural rather than a judgement call. Zero-DCE outputs the coefficients of a tone curve rather than pixels, and that curve is provably monotonic — so each output pixel is a monotone function of that pixel's own input value, and no learned prior can paint an edge, a character or a face into it. DnCNN is discriminative: it predicts and subtracts a noise residual, with no image prior to draw new structure from.

A report can therefore read neural and may synthesise: no on the same line, and both are true. Collapsing the axes would make the warning meaningless exactly where it matters — you could no longer tell CodeFormer, which invents faces, from a tone curve.

32operators (10 classical, 22 neural)
9degradation indicators
14report sections
291automated tests
0bytes of telemetry
Features

Built like evidence handling, not like a photo editor

Everything below ships in v1.0.0 and is exercised by the test suite.

Chain of custody

Evidence is copied into the case, hashed with SHA-256, SHA-512 and MD5, and set read-only. Every state change writes an append-only audit entry.

Nine degradation indicators

Blur, motion blur, noise, JPEG artefacts, low resolution, under- and over-exposure, low contrast and haze — each with a 0–100 severity and the raw measurements behind it.

Pipelines you approve first

Auto Enhance proposes a sequence with a rationale for every step, tied to the measurement that triggered it. Nothing runs until you press Run.

Real checkpoints, natively loaded

Six architectures reimplemented with upstream layer naming, so official .pth files load with zero key mismatches — and with no dependency on the unmaintained basicsr stack.

Comparison that stays honest

Side-by-side, split, overlay and five difference modes, locked to the same apparent scale even when the derivative is four times larger, with PSNR and changed-pixel statistics.

Fourteen-section PDF report

Case, evidence, hashes, metadata, analysis, pipeline with rationale, parameters, model provenance, before/after, difference, history, audit trail and limitations.

Forensic Safe Mode

On by default. Originals are read-only, never a write target; deleting evidence and editing history are refused; turning it off is itself audited.

Eleven forensic visualisations

RGB and luminance histograms, edge map, high pass, noise residual, saturation, exposure and clipping maps, frequency spectrum and error level analysis — overlaid, never baked in.

GPU when you have one

CUDA with FP16, tiled inference with feathered blending for images larger than VRAM, and automatic tile-size backoff on out-of-memory. CPU works throughout.

Nothing is faked

A model with no weights shows Weights missing and an Install button. A model that is declared but not integrated says exactly what is missing. Neither ever returns a substitute.

Batch and ROI processing

Apply one reviewed pipeline across a folder, or restrict analysis and enhancement to a rectangle, ellipse, polygon or freehand region.

A headless engine

Nothing in the analysis, restoration, forensic, database or report packages imports Qt — so the same engine can back a CLI, a service or a video pipeline.

Screenshots

The application, end to end

Click any image to open it full size. The sample throughout is synthetic evidence generated by scripts/make_sample.py — a 320×213 frame degraded with blur, sensor noise and quality-28 JPEG compression. No real case material ships with the project.

A measured example

The output invented eyeglasses the subject does not wear

CodeFormer is fully integrated — detect with OpenCV YuNet, align to the canonical FFHQ frame, restore, blend back. Run on the standard astronaut benchmark degraded to 128 px, it produced a sharp, confident, entirely plausible face that also altered apparent age, face shape and hairline. Nothing in the result distinguishes the measured features from the invented ones.

Three panels: ground truth, the 128-pixel degraded input, and the CodeFormer output wearing eyeglasses the subject does not wear
It must never be used for identification

So it is fenced off: a face-specific confirmation before every run, the inter-ocular distance of each source face measured and recorded with a warning below 30 px, the fidelity weight exposed so the range can be swept, and every derivative marked may synthesise. This example is kept in LIMITATIONS.md §5 rather than hidden, because it is the clearest demonstration of what the whole application exists to guard against.

Measured results

Sometimes the classical operator wins — and the tool says so

Peak signal-to-noise ratio against ground truth on the bundled synthetic evidence. These numbers are why both operator classes are kept rather than defaulting to whichever is newer.

OperationClassical baselineNeuralWinner
Denoise (σ ≈ 18/255) Non-local means +9.7 dB DnCNN blind +14.4 dB Neural
JPEG quality 18 Deblocking +0.1 dB, −15% blockiness FBCNN +3.5 dB, −73% Neural
Motion deblur Wiener +6.6 dB Restormer +2.5 dB Classical
Defocus deblur Richardson–Lucy +1.9 dB Wiener −1.2 dB Classical
Low light (clean) Gamma 0.35 +10.2 dB Zero-DCE++ +12.7 dB Neural
Low light (with sensor noise) Gamma 0.35 +9.5 dB Zero-DCE++ +9.6 dB Tied

Gains are against the untouched degraded frame. Wiener deconvolution scores negative on a pillbox defocus kernel because the transfer function has genuine zeros — documented in the operator's own description rather than hidden. The two low-light rows are the same lesson from the other direction: on a clean dark frame Zero-DCE++ beats the best hand-set gamma curve by 2.4 dB, but add the sensor noise a real low-light frame actually has and the advantage collapses to 0.03 dB, because brightening shadows brightens their noise with them at roughly five times the input sigma.

Checkpoint verification

Every neural architecture is reimplemented with upstream layer naming, so the official weight files load with no key remapping at all.

ModelTaskState-dict keysMissing / unexpectedParameters
Real-ESRGAN x4plusSuper-resolution7020 / 016.70 M
SwinIRSR · denoise · JPEG5500 / 011.90 M
RestormerDeblur · denoise4940 / 026.13 M
FBCNNJPEG artefacts1840 / 071.92 M
DnCNNDenoise400 / 00.67 M
CodeFormerFace restoration5150 / 094.11 M
Zero-DCE · Zero-DCE++Low-light exposure14 · 280 / 00.079 M · 0.011 M
NAFNetDeblur · denoiseImplemented; never verified against a published checkpoint — upstream is Google-Drive-only
How it compares

Where ForensicVision fits — and where it loses

The last four rows are the ones this project loses, and they are in the table on purpose. A tool arguing for honest labelling that oversold itself would undercut its own position.

ForensicVision Amped FIVE Photoshop GIMP + G'MIC chaiNNer · Upscayl Topaz Photo AI
LicenceApache-2.0, openCommercialCommercialGPL, openGPL/AGPL, openCommercial
CostFreePaid, per seatSubscriptionFreeFreePaid
Purpose-built for forensicsYesYesNoNoNoNo
Case and evidence managementYesYesNoNoNoNo
Cryptographic evidence hashingYesYesNoNoNoNo
Per-derivative provenance recordYesYesXMP historyNoNoNo
Append-only audit trailYesYesNoNoNoNo
Automated forensic PDF reportYesYesNoNoNoNo
Classical / deterministic operators10ExtensiveYesExtensiveNoNo
Deep-learning restoration22 adaptersSomePlug-insYesYes
Per-step “may synthesise” labellingYesNoNoNoNo
Explains why each step is proposedYesNoNoNoNo
Review-before-run pipeline gateYesNoNoPartialNo
Runs fully offline, no accountYesYesNoYesYesActivation
Never auto-downloads weightsYesn/an/an/aNon/a
Reusable headless engineYesNoNoScript-FuYesNo
Video / DVR supportNoYesNoNoNoNo
Established in courtNoneExtensiven/an/an/an/a
Vendor support and trainingNoneYesYesCommunityCommunityYes
PlatformsWin · LinuxWindowsWin · macOSWin · macOS · LinuxWin · macOS · LinuxWin · macOS

“—” marks a capability we were not able to confirm from public documentation, not an assertion that it is absent. Commercial feature sets change; verify current capabilities with the vendor.

Against research repositories

Real-ESRGAN, CodeFormer and SwinIR CLIs, chaiNNer, Upscayl give you the model, not the workflow — no case, no hash, no record of what ran with which parameters, no report. And they present neural output as “the enhanced image,” full stop.

Against general editors

Photoshop and GIMP are vastly more capable as editors and completely unsuited to evidence: destructive by default, no chain of custody, and nothing in the saved result separating a deterministic filter from a generative fill.

Against commercial suites

Amped FIVE is the professional standard, with a substantial court record, video support and vendor validation. ForensicVision does not replace it and claims no court acceptance whatsoever. What it offers is open source, modern models, and explicit synthesis labelling.

Quick start

Running in about two minutes

Python 3.11 or newer. Everything except the neural models works out of the box — PyTorch is optional and imported lazily, so the application starts with no ML stack installed at all.

PowerShell
# 1. Clone and enter the project
git clone https://github.com/SihabSahariar/ForensicVision.git
cd ForensicVision

# 2. Create an isolated environment
py -3.11 -m venv .venv
.venv\Scripts\Activate.ps1

# 3. Install dependencies
python -m pip install --upgrade pip
python -m pip install -r requirements.txt

# 4. Check the environment, then launch
python main.py --check
python main.py

Try it without a case

shell
python scripts/make_sample.py                             # synthetic test evidence
python main.py --image samples/sample_cctv.jpg --no-case  # inspect, no case
python main.py --self-test                                # functional end-to-end check
GPU acceleration is optional

Install a CUDA build of PyTorch to use the neural models on an NVIDIA card; without one they run on CPU, more slowly. Model weights are never downloaded automatically — open Tools → Model Manager (Ctrl+M) and install what you need. Full instructions are in the documentation.

The workflow

Six steps from evidence to report

  1. Create a case

    Ctrl+N — a self-contained directory with its own SQLite database, so a case folder can be archived or handed over as a unit.

  2. Import evidence

    Ctrl+O — copies the file, computes three digests, extracts EXIF and JPEG quantisation tables, and sets the stored original read-only.

  3. Analyse

    A — nine degradation indicators, each with its severity, its raw measurements and the name of the estimator that produced it.

  4. Review the proposed pipeline

    E — Auto Enhance builds a recommendation from the measurements and shows it. Reorder, disable, re-parameterise or reject any step. Nothing has run yet.

  5. Compare

    Ctrl+D — side-by-side, split, overlay or difference, locked to the same apparent scale, with PSNR and changed-pixel statistics.

  6. Generate the report

    Ctrl+P — fourteen sections including the full hash chain, the rationale for every step, and the model provenance behind each one.

Roadmap

What is planned, and what never will be

Contributions towards any of these are very welcome — see the contribution conventions.

Next

  • Video and DVR support. The largest gap against commercial tools; the engine is already frame-agnostic.
  • Multi-frame super-resolution and stacking. Recovers real detail instead of inferring it.
  • A proper CLI front end. The engine is already headless.
  • CPU-only packaging profile. 4.7 GB today; 400–600 MB without the CUDA libraries.
  • Publish weight digests for the files whose upstream projects do not.

Verification and platforms

  • Test the Linux build on real hardware. The AppImage script has never been run on Linux.
  • End-to-end OCR verification against genuinely degraded text.
  • Verify NAFNet against a published checkpoint.
  • macOS support. Nothing is known to block it; it has simply never been run.
  • Signed, reproducible release builds.

Models and capability

  • GFPGAN and LaMa — declared, not integrated; blockers documented in-app.
  • SCUNet and DiffBIR adapters.
  • A public benchmark harness, so the classical-versus-neural claims stay honest.
  • PRNU / sensor pattern noise for source camera identification.
  • Manipulation detection beyond ELA — always as an indicator, never a verdict.

Explicit non-goals

  • Facial recognition, face matching or identification of any kind.
  • Any feature that presents a synthesised result without labelling it as one.
  • Cloud processing, accounts, or telemetry.
Author

Built and maintained by Sihab Sahariar

Sihab Sahariar

If you use ForensicVision in research or casework, I would genuinely like to hear about it — particularly about anything it got wrong.

Acknowledgements

This project implements architectures published by others and loads their official checkpoints. Credit belongs to the original authors: Real-ESRGAN · SwinIR · Restormer · FBCNN · DnCNN · NAFNet · CodeFormer · YuNet, and the OpenCV, PyTorch, NumPy, ReportLab, SQLAlchemy and Qt projects.