feat: add OpenCV loader, Otsu threshold and margin-aware mask tracing

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
immortaly007andClaude Opus 5.5 committed 2026-10-15 14:43:41 +02:00
1 parent 8d597e856e
commit 5e4eebaaa2
5 files changed
+231

No files matched your search

+35
View File
@@ -0,0 +1,35 @@
import type { Mat } from '@techstark/opencv-js';
import type { CV } from '../../src/lib/opencv-loader';
import type { RasterImage } from '../../src/lib/types';
/** Grayscale RGBA image where `paint(x, y)` returns the brightness 0–255. */
export function grayImage(width: number, height: number, paint: (x: number, y: number) => number): RasterImage {
const data = new Uint8ClampedArray(width * height * 4);
for (let y = 0; y < height; y++) {
for (let x = 0; x < width; x++) {
const i = (y * width + x) * 4;
const v = paint(x, y);
data[i] = data[i + 1] = data[i + 2] = v;
data[i + 3] = 255;
}
}
return { width, height, data };
}
/** CV_8UC1 mask with 255 where `inside(x, y)`. Caller must delete it. */
export function maskFrom(cv: CV, width: number, height: number, inside: (x: number, y: number) => boolean): Mat {
const mask = cv.Mat.zeros(height, width, cv.CV_8UC1) as Mat;
const data = mask.data;
for (let y = 0; y < height; y++) {
for (let x = 0; x < width; x++) {
if (inside(x, y)) data[y * width + x] = 255;
}
}
return mask;
}
export const inRect = (x: number, y: number, x0: number, y0: number, x1: number, y1: number) =>
x >= x0 && x < x1 && y >= y0 && y < y1;
export const inCircle = (x: number, y: number, cx: number, cy: number, r: number) =>
(x - cx) ** 2 + (y - cy) ** 2 <= r * r;