Go to file
2026-10-19 08:11:33 +02:00
app Prvy 2026-10-19 08:11:33 +02:00
data Prvy 2026-10-19 08:11:33 +02:00
docs Prvy 2026-10-19 08:11:33 +02:00
experiments Prvy 2026-10-19 08:11:33 +02:00
results Prvy 2026-10-19 08:11:33 +02:00
src Prvy 2026-10-19 08:11:33 +02:00
tests Prvy 2026-10-19 08:11:33 +02:00
.gitignore Prvy 2026-10-19 08:11:33 +02:00
MOBISIG.ZIP Prvy 2026-10-19 08:11:33 +02:00
pyproject.toml Prvy 2026-10-19 08:11:33 +02:00
README.md Prvy 2026-10-19 08:11:33 +02:00

Signature verification baseline

A small research starter project for online handwritten-signature verification. It includes common-format CSV/JSON loading, preprocessing, feature extraction, DTW matching, threshold metrics, and a local FastAPI capture demo.

Setup

From the project root:

py -m venv .venv
.\.venv\Scripts\Activate.ps1
python -m pip install -e ".[dev]"
$env:SIGVERIFY_FERNET_KEY = python -c "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())"
uvicorn app.main:app --reload

Open http://127.0.0.1:8000/. The generated Fernet key is for local testing; keep the same key between runs to read previously enrolled templates. Store a production key in a secret manager, never in source control. Without a key, the API rejects enrollment and verification rather than storing plaintext.

Run tests with pytest. The package can also be installed with pip install -e ..

Data format

The common signature format has one sample per point with user_id, t, x, y, optional p (pressure), optional area (contact area), and optional pen_down. CSV loaders expect these names by default; pass column overrides for a dataset with different headers. A JSON signature uses the same names with array-valued t, x, and y. For MOBISIG, check the downloaded release's layout is supported directly by load_mobisig: timestamp, x, y, pressure, and fingerarea are mapped automatically. Names such as SIGN_GEN_USER1_USER1_1.csv and SIGN_FOR_USER1_USER2_1.csv determine the claimed user and genuine/forgery label; metadata files such as users.csv are ignored. Put downloaded or self-collected material under data/raw/. Raw data is ignored by Git.

Baseline workflow

  1. Load signatures into Signature.
  2. Sort timestamps, collapse repeated times, lightly smooth, resample, and translate/scale positions. Preprocessing records the original bounding-box diagonal because size may itself be discriminative. Pen-up samples are excluded from the baseline trajectory.
  3. Extract x/y and motion features; pressure and contact area can be enabled as explicit ablations.
  4. Enroll several genuine examples, compare using band-constrained DTW, and divide by the median within-enrollment distance.
  5. Tune global and per-user thresholds on a development split; evaluate only on held-out attempts. Thresholds in the demo are illustrative, not research results.

experiments/ contains starter scripts for inspecting data, running a simple split, and comparing feature sets. Report user-disjoint development/test results separately from the API demo. Do not train or tune on the test set.

For the included MOBISIG layout, run:

python experiments/02_baseline_dtw.py --data-dir data/raw/mobisig `
  --output results/mobisig_baseline.json

The browser sends pointer positions, elapsed milliseconds, and optional pressure. It does not persist anything in the browser. Review docs/data_collection_protocol.md and docs/consent_form.md before collecting data; adapt them to institutional requirements and obtain approval where required.

The SQLite demo stores encrypted template JSON and a small lockout counter in process memory. Lockout state resets when the server restarts, so this is not a production account-security system. Use HTTPS, authentication, durable rate-limiting, access controls, key management, and a retention/deletion policy before exposing a service beyond localhost.