79 lines
3.5 KiB
Markdown
79 lines
3.5 KiB
Markdown
# 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:
|
|
|
|
```powershell
|
|
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:
|
|
|
|
```powershell
|
|
python experiments/02_baseline_dtw.py --data-dir data/raw/mobisig `
|
|
--output results/mobisig_baseline.json
|
|
```
|
|
|
|
## Capture and consent
|
|
|
|
The browser sends pointer positions, elapsed milliseconds, and optional
|
|
pressure. It does not persist anything in the browser. Review
|
|
[`docs/data_collection_protocol.md`](docs/data_collection_protocol.md) and
|
|
[`docs/consent_form.md`](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.
|