MaskDetector
ONNX-based three-way face-mask classifier for browser and Node.
MaskDetector (from @framefind/core) is the underlying class that useMaskDetector wraps. Use it when you need to run mask detection outside React — in a vanilla JS app, a canvas pipeline, or a web worker.
The model is a three-class classifier:
with_mask— face covering correctly wornwithout_mask— no face coveringincorrect_mask— mask present but worn improperly (nose exposed, chin only, etc.)
Browser usage
import { MaskDetector } from "@framefind/core";
const detector = new MaskDetector({});
await detector.load();
// on each frame:
const result = await detector.detectFromVideoFrame(videoEl, offscreenCanvas);
console.log(result.label, result.probabilities);
// when done:
detector.dispose();detectFromVideoFrame copies the frame into the supplied canvas, crops the face bounding box (with asymmetric vertical padding for mouth/chin context), resizes to 112×112, normalizes with ImageNet statistics, and runs ONNX inference. The same canvas can be reused across calls.
Detect from a canvas directly
const result = await detector.detectFromCanvas(canvas);Use this for static images — draw your image onto a canvas first, then pass it in.
Node.js
Import from the node subpath:
import { MaskDetectorNode } from "@framefind/core/node";
const detector = new MaskDetectorNode({
modelPath: "./models/mask.onnx",
});
await detector.load();
const result = await detector.detectFromImagePath("./photo.jpg");MaskDetectorNode uses onnxruntime-node instead of onnxruntime-web. The model path can be a local file or an HTTP(S) URL — remote models are cached in the OS temp directory on first use.
detectFromImagePath requires the optional sharp peer dependency:
npm i sharpIf @tensorflow/tfjs-node and @tensorflow-models/face-landmarks-detection are installed, the detector automatically crops the face bounding box from landmarks. Otherwise it falls back to a center crop.
Options
new MaskDetector({
// ONNX model URL. Defaults to the FrameFind CDN.
modelUrl: "https://cdn.framefind.moraxh.dev/models/mask/v1/mask.onnx",
// ONNX Runtime WASM directory. Defaults to the FrameFind CDN.
wasmPaths: "https://cdn.framefind.moraxh.dev/onnxruntime-web/1.25.1/dist/",
// Threshold applied to the smoothed `with_mask` probability for the `mask` boolean.
// Default: 0.5
threshold: 0.5,
// Frames to average. Default: 8
smoothingWindow: 8,
// Auto-run MediaPipe face landmarker for face-bbox crop. Default: true
autoLandmarks: true,
faceLandmarkerModelUrl: "...",
mediapipeWasmPath: "...",
minFaceDetectionConfidence: 0.5,
minFacePresenceConfidence: 0.5,
// Minimum ms between inferences in a frame loop. Default: 0
inferenceIntervalMs: 0,
// Prefer GPU delegate. Default: true, falls back to CPU
preferGpu: true,
});Result type
type MaskClass = "with_mask" | "without_mask" | "incorrect_mask";
type MaskDetectionResult = {
label: MaskClass;
probability: number;
probabilities: [number, number, number];
mask: boolean;
faceDetected: boolean;
};The probabilities tuple is ordered [with_mask, without_mask, incorrect_mask]. label is the argmax of the smoothed tuple. probability is the smoothed probability of the predicted class.
Cleanup
Always call dispose() when finished. It releases the ONNX session and the MediaPipe face landmarker:
detector.dispose();