first commit

This commit is contained in:
2026-07-18 01:34:52 +05:30
commit d1308bf149
113 changed files with 20593 additions and 0 deletions
+66
View File
@@ -0,0 +1,66 @@
import type { AIProvider, DetectedObject, MediaItem } from '@photo-gallery/sdk';
/**
* Free, in-browser AI provider using TensorFlow.js + COCO-SSD object detection.
* No API key, no server — the model (~6 MB) downloads from the public TF model
* CDN on first use and runs on the GPU via the WebGL backend.
*
* Detects 80 COCO classes (person, dog, cat, car, laptop, chair, dining table,
* tv, bottle, cup, …) which power search, find-similar and the Objects browser.
*/
export function createTensorflowProvider(): AIProvider {
// Loaded lazily and memoized so the heavy bundle/model is fetched only once.
let modelPromise: Promise<CocoModel> | null = null;
async function getModel(): Promise<CocoModel> {
if (!modelPromise) {
modelPromise = (async () => {
const tf = await import('@tensorflow/tfjs');
try {
await tf.setBackend('webgl');
} catch {
// Fall back to the default backend if WebGL is unavailable.
}
await tf.ready();
const cocoSsd = await import('@tensorflow-models/coco-ssd');
return cocoSsd.load({ base: 'lite_mobilenet_v2' }) as unknown as CocoModel;
})();
}
return modelPromise;
}
return {
name: 'tensorflow-coco-ssd',
async detectObjects(item: MediaItem, image): Promise<DetectedObject[]> {
const model = await getModel();
const el = image as HTMLImageElement;
const w = el.naturalWidth || el.width || item.width || 1;
const h = el.naturalHeight || el.height || item.height || 1;
const predictions = await model.detect(el, 20, 0.4);
return predictions.map((p) => ({
label: p.class,
confidence: p.score,
box: {
x: p.bbox[0] / w,
y: p.bbox[1] / h,
width: p.bbox[2] / w,
height: p.bbox[3] / h,
},
}));
},
};
}
interface CocoPrediction {
bbox: [number, number, number, number];
class: string;
score: number;
}
interface CocoModel {
detect(
img: HTMLImageElement | HTMLCanvasElement | HTMLVideoElement,
maxNumBoxes?: number,
minScore?: number,
): Promise<CocoPrediction[]>;
}