Spaces:
Running
Running
Download detect.js from CyberMax-tools/sightfern: direct link, hf CLI and curl.
- Browser
- Download file 2.34 kB
-
https://huggingface.co/spaces/CyberMax-tools/sightfern/resolve/main/detect.js
- Command line
-
hf download hf://spaces/CyberMax-tools/sightfern/detect.js
-
curl -L -o detect.js https://huggingface.co/spaces/CyberMax-tools/sightfern/resolve/main/detect.js
2.34 kB
| // Sightfern on-device detector: Google MediaPipe Object Detector (EfficientDet-Lite0, COCO classes, Apache-2.0), | |
| // loaded only when the player opens the camera or picks a photo. The library and model files are downloaded once | |
| // (then cached for offline use by sw.js); every image is analysed inside the browser and never uploaded. | |
| // (c) 2026 CyberMax. All rights reserved. MediaPipe (c) Google LLC, Apache License 2.0. | |
| import { SPECIES } from './core.js'; | |
| export const MP_VERSION = '0.10.14'; | |
| export const MP_BASE = `https://cdn.jsdelivr.net/npm/@mediapipe/tasks-vision@${MP_VERSION}`; | |
| export const MODEL = 'https://storage.googleapis.com/mediapipe-models/object_detector/efficientdet_lite0/int8/1/efficientdet_lite0.tflite'; | |
| export const MIN_SCORE = 0.4; | |
| let pending = null; | |
| /** Load once. Returns { detect(source) -> { ms, items }, delegate }. Rejects when the device cannot run it. */ | |
| export function loadDetector(prefer = 'CPU') { // CPU (WASM) by default: measured fast and exact (tests/detect-speed.mjs); GPU is opt-in | |
| if (pending) return pending; | |
| pending = (async () => { | |
| const vision = await import(/* @vite-ignore */ `${MP_BASE}/vision_bundle.mjs`); | |
| const files = await vision.FilesetResolver.forVisionTasks(`${MP_BASE}/wasm`); | |
| const opts = (delegate) => ({ baseOptions: { modelAssetPath: MODEL, delegate }, runningMode: 'IMAGE', scoreThreshold: 0.3, maxResults: 5, categoryAllowlist: Object.keys(SPECIES) }); | |
| let det, delegate = prefer; | |
| try { det = await vision.ObjectDetector.createFromOptions(files, opts(prefer)); } catch { delegate = 'CPU'; det = await vision.ObjectDetector.createFromOptions(files, opts('CPU')); } | |
| return { | |
| delegate, | |
| /** source: <canvas>, <img> or ImageBitmap. Boxes are in the source's pixel space. */ | |
| detect(source) { | |
| const t = performance.now(); | |
| const r = det.detect(source); | |
| const items = (r.detections || []).map((d) => ({ species: d.categories[0].categoryName, score: d.categories[0].score, box: { x: d.boundingBox.originX, y: d.boundingBox.originY, w: d.boundingBox.width, h: d.boundingBox.height } })) | |
| .filter((d) => d.species in SPECIES).sort((a, b) => b.score - a.score); | |
| return { ms: performance.now() - t, items }; | |
| }, | |
| }; | |
| })(); | |
| pending.catch(() => { pending = null; }); | |
| return pending; | |
| } | |