gofacekit

A minimal, professional Go SDK for consent-based 1:1 face verification.
gofacekit compares a reference face image with a probe (selfie) image and
returns a similarity score and a match decision. It is a library, not a web
service, and it keeps dependencies to a minimum (the v0.1 core is pure Go
standard library).
⚠️ Ethics first. gofacekit is for consent-based one-to-one verification
only — not surveillance, not covert identification, not one-to-many search.
Please read docs/privacy.md before using it.
What it is
- A clean, embeddable Go library for "is this the same person who enrolled?"
- A small CLI for quick comparisons.
- An interface-driven design: swap in real detectors and ONNX models without
changing the public API.
What it is not
- ❌ Not a surveillance or 1:N identification tool.
- ❌ Not a web framework (no Gin/Echo/Fiber) and not a database.
- ❌ Not a bundled model — you bring your own ONNX weights (see
models/README.md).
- ❌ Not dependent on OpenCV or dlib.
Features
- Decode JPEG/PNG, detect a face, crop, optional quality gate, embed, compare.
- Cosine similarity matching with a configurable threshold.
- Blur and brightness quality checks.
- Safe by default: demo fallbacks (mock embedder / center detector) are
opt-in only — the library won't silently fake a result.
- Real, working Pigo face detector (pure Go) — supply a cascade file to
enable it.
- Real ONNX recognition embedder behind an opt-in
onnx build tag (no
native dependency in the default build).
- Stable public API, unit tests, benchmarks, and CI.
Installation
go get github.com/BaxtiyorUrolov/gofacekit
Requires Go 1.22+.
Modes: demo vs. real verification
gofacekit ships with non-identity fallback components (a non-ML
CenterDetector and a deterministic MockEmbedder) so the project runs end to
end with zero setup. These produce plausible-looking but meaningless results.
To prevent accidents, NewVerifier refuses to use them by default:
| Mode |
Detector |
Embedder |
How to enable |
| Demo (not real verification) |
CenterDetector |
MockEmbedder |
Config.AllowInsecureFallbacks: true (CLI: --demo) |
| Real — detection only |
Pigo (cascade) |
— |
set CascadePath; ModelPath still required or demo embedder |
| Real — full |
Pigo (cascade) |
ONNX (-tags onnx) |
set CascadePath and ModelPath, build -tags onnx |
Without a real cascade/model and without opting in, NewVerifier returns
ErrDetectorNotConfigured / ErrEmbedderNotConfigured (wrapping
ErrInsecureFallbackDisabled).
Quick start
Real verification
verifier, err := gofacekit.NewVerifier(gofacekit.Config{
CascadePath: "./models/facefinder", // real Pigo detector
ModelPath: "./models/arcface.onnx", // real ONNX embedder (build with -tags onnx)
Threshold: 0.65,
})
if err != nil {
log.Fatal(err)
}
result, err := verifier.VerifyImages("reference.jpg", "selfie.jpg")
if err != nil {
log.Fatal(err)
}
fmt.Printf("Match: %v Similarity: %.4f\n", result.Match, result.Similarity)
Build and run with the ONNX engine enabled:
CGO_ENABLED=1 go run -tags onnx .
export GOFACEKIT_ORT_LIB=/path/to/libonnxruntime.so # .dylib / .dll per OS
Demo mode (NOT real verification)
verifier, err := gofacekit.NewVerifier(gofacekit.Config{
AllowInsecureFallbacks: true, // mock/center fallbacks — demonstration only
Threshold: 0.65,
})
You can also verify in-memory images with verifier.VerifyBytes(refBytes, probeBytes).
A runnable demo lives in examples/compare-images
(make run-example).
⚠️ Demo mode does not model identity. Never use it for real decisions.
CLI usage
# Build
go build -o gofacekit ./cmd/gofacekit
# Real verification (requires a cascade + an ONNX model; build the CLI with -tags onnx)
./gofacekit compare --ref a.jpg --probe b.jpg \
--cascade ./models/facefinder --model ./models/arcface.onnx --quality
# Demo mode (mock/center fallbacks; prints a stderr warning)
./gofacekit compare --ref reference.jpg --probe selfie.jpg --demo
# Version
./gofacekit version
Running compare without --cascade/--model and without --demo fails with a
clear message instead of silently returning demo results.
Example JSON output:
{
"match": true,
"similarity": 0.9912,
"threshold": 0.65,
"reference_face": { "found": true, "box": { "x": 15, "y": 15, "width": 70, "height": 70 }, "confidence": 1 },
"probe_face": { "found": true, "box": { "x": 15, "y": 15, "width": 70, "height": 70 }, "confidence": 1 },
"quality": { "ok": true, "blur_score": 0, "brightness_score": 0, "message": "quality check disabled" }
}
Architecture
The public package (pkg/gofacekit) wraps an internal pipeline that orchestrates
swappable Detector and Embedder interfaces.
flowchart LR
A([Reference image]) --> P
B([Probe image]) --> P
subgraph P [Pipeline]
direction LR
D[Decode] --> DET[Detect face] --> C[Crop] --> Q[Quality check] --> E[Embed] --> M[Compare]
end
M --> R([VerificationResult<br/>match · similarity])
DET -. interface .-> DETP[PigoDetector / CenterDetector]
E -. interface .-> EMB[ONNXEmbedder / MockEmbedder]
The detector and embedder are interfaces injected into the pipeline, so the real
implementations (Pigo, ONNX) drop in without touching the public API. See
docs/architecture.md for the full layout and dependency
graph.
Component status
| Component |
Status |
Notes |
Pigo detector (PigoDetector) |
✅ Implemented |
Real pure-Go face detection via pigo. Requires a binary cascade file (facefinder) — set Config.CascadePath. Not committed; see models/README.md. |
Center detector (CenterDetector) |
⚠️ Demo fallback |
Non-ML; returns a centered box. Used only when CascadePath is empty and AllowInsecureFallbacks is set. Not real detection. |
Mock embedder (MockEmbedder) |
⚠️ Demo fallback |
Deterministic, no notion of identity. Used only when ModelPath is empty and AllowInsecureFallbacks is set. |
ONNX embedder (ONNXEmbedder) |
✅ Implemented (opt-in) |
Real inference behind the onnx build tag, via onnxruntime_go. Excluded from the default build so no native library is needed. Set ModelPath + build with -tags onnx. See models/README.md. |
Config.ModelInput lets you match your model (defaults are ArcFace-style):
v, err := gofacekit.NewVerifier(gofacekit.Config{
CascadePath: "./models/facefinder",
ModelPath: "./models/arcface.onnx",
Threshold: 0.65,
ModelInput: gofacekit.ModelInput{ // optional; ArcFace defaults if omitted
Width: 112, Height: 112,
ChannelOrder: gofacekit.ChannelRGB,
InputName: "data", OutputName: "fc1", EmbeddingSize: 512,
},
})
Errors (matchable with errors.Is)
- Configuration safety:
ErrDetectorNotConfigured, ErrEmbedderNotConfigured,
ErrInsecureFallbackDisabled.
- Detection:
ErrCascadeNotFound, ErrInvalidCascade, ErrNoFaceDetected.
- Recognition (ONNX):
ErrModelNotFound, ErrInvalidInputShape,
ErrInferenceFailed.
Full setup (model input config, installing the runtime):
models/README.md.
Privacy & consent
This project is intentionally limited to consent-based 1:1 verification. Get
explicit consent, minimize and encrypt biometric data, allow deletion, and keep
humans in the loop for important decisions. Full guidance:
docs/privacy.md.
Model files
No model weights ship with this repository. Bring your own ONNX model and point
Config.ModelPath at it. See models/README.md for details
and for how to wire up the ONNX runtime.
Roadmap
- v0.1 — foundation ✅
- Image compare (
VerifyImages / VerifyBytes)
- CLI (
compare, version)
- Mock embedder + clean injected interfaces
- Cosine matcher and quality checks
- v0.2 — real models 🚧
- Real Pigo face detector
- ONNX embedder (opt-in
onnx build tag)
- Face alignment from landmarks
- Benchmarks
- v0.3 — liveness & demos
- Active liveness challenge interfaces
- Live camera demo (separate repo)
Details: docs/roadmap.md.
Development
make test # go test -race ./...
make vet # go vet ./...
make lint # gofmt check (+ golangci-lint if installed)
make build # build the CLI into ./bin
make run-example
Run make help to list all targets.
Contributing
Contributions are welcome! Please read CONTRIBUTING.md for the
workflow and coding standards, and note the project's
ethical scope. Security issues: see
SECURITY.md. Release notes live in CHANGELOG.md.
License
MIT © gofacekit authors