zorya-classifier 0.2.1 → 0.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +31 -17
- package/dist/app/classifier-config.d.ts +30 -0
- package/dist/app/classifier-config.js +46 -0
- package/dist/app/classifier-contracts.d.ts +32 -0
- package/dist/app/classifier-contracts.js +1 -0
- package/dist/app/classifier-runtime.d.ts +7 -0
- package/dist/app/classifier-runtime.js +71 -0
- package/dist/app/classifier-spatial.d.ts +31 -0
- package/dist/app/classifier-spatial.js +78 -0
- package/dist/app/cli-arguments.d.ts +2 -2
- package/dist/app/composed-classifier.d.ts +17 -0
- package/dist/app/composed-classifier.js +1 -0
- package/dist/app/create-classifier.d.ts +9 -33
- package/dist/app/create-classifier.js +53 -245
- package/dist/cli.js +1 -1
- package/dist/entities/classification.d.ts +83 -0
- package/dist/entities/classification.js +28 -0
- package/dist/entities/contracts.d.ts +6 -475
- package/dist/entities/contracts.js +6 -97
- package/dist/entities/decision.d.ts +211 -0
- package/dist/entities/decision.js +33 -0
- package/dist/entities/geometry.d.ts +37 -0
- package/dist/entities/geometry.js +26 -0
- package/dist/entities/image.d.ts +30 -0
- package/dist/entities/image.js +12 -0
- package/dist/entities/localization.d.ts +110 -0
- package/dist/entities/localization.js +13 -0
- package/dist/entities/object-proposals.d.ts +1 -1
- package/dist/entities/representation.d.ts +0 -183
- package/dist/entities/representation.js +1 -33
- package/dist/entities/segmentation-metadata.d.ts +70 -0
- package/dist/entities/segmentation-metadata.js +21 -1
- package/dist/entities/segmentation-verification.d.ts +1 -1
- package/dist/entities/segmentation.d.ts +5 -20
- package/dist/entities/validation.d.ts +2 -0
- package/dist/entities/validation.js +9 -0
- package/dist/entities/whole-object.d.ts +6 -21
- package/dist/features/choice-beam-layout.js +2 -7
- package/dist/features/proposals/presentation.d.ts +21 -0
- package/dist/features/proposals/presentation.js +122 -0
- package/dist/features/proposals/validation.d.ts +138 -0
- package/dist/features/proposals/validation.js +125 -0
- package/dist/features/segmentation/box-check.js +10 -23
- package/dist/features/segmentation/mask.js +2 -7
- package/dist/features/segmentation/region-result.d.ts +18 -0
- package/dist/features/segmentation/region-result.js +171 -0
- package/dist/features/segmentation/source-mask.d.ts +6 -0
- package/dist/features/segmentation/source-mask.js +32 -0
- package/dist/features/segmentation/validation.d.ts +9 -0
- package/dist/features/segmentation/validation.js +94 -0
- package/dist/infrastructure/decision-transport/errors.d.ts +8 -0
- package/dist/infrastructure/decision-transport/errors.js +34 -0
- package/dist/infrastructure/decision-transport/images.d.ts +1 -0
- package/dist/infrastructure/decision-transport/images.js +52 -0
- package/dist/infrastructure/{openrouter-common.d.ts → decision-transport/request.d.ts} +6 -15
- package/dist/infrastructure/decision-transport/request.js +162 -0
- package/dist/infrastructure/decision-transport/response.d.ts +1 -0
- package/dist/infrastructure/decision-transport/response.js +72 -0
- package/dist/infrastructure/decision-transport/route-identity.d.ts +11 -0
- package/dist/infrastructure/decision-transport/route-identity.js +23 -0
- package/dist/infrastructure/openrouter-vision.js +1 -1
- package/dist/infrastructure/openrouter.js +7 -19
- package/dist/infrastructure/raster.js +3 -8
- package/dist/infrastructure/segmentation/grabcut/index.d.ts +2 -2
- package/dist/infrastructure/segmentation/grabcut/index.js +3 -5
- package/dist/infrastructure/segmentation/grabcut/masks.d.ts +49 -0
- package/dist/infrastructure/segmentation/grabcut/masks.js +89 -0
- package/dist/infrastructure/segmentation/grabcut/model-asset.d.ts +4 -0
- package/dist/infrastructure/segmentation/grabcut/model-asset.js +4 -0
- package/dist/infrastructure/segmentation/grabcut/runtime.d.ts +70 -0
- package/dist/infrastructure/segmentation/grabcut/runtime.js +96 -0
- package/dist/infrastructure/segmentation/grabcut/worker-inference.d.ts +4 -43
- package/dist/infrastructure/segmentation/grabcut/worker-inference.js +4 -187
- package/dist/infrastructure/segmentation/mobile-sam/index.d.ts +3 -66
- package/dist/infrastructure/segmentation/mobile-sam/index.js +2 -478
- package/dist/infrastructure/segmentation/mobile-sam/input.d.ts +46 -0
- package/dist/infrastructure/segmentation/mobile-sam/input.js +83 -0
- package/dist/infrastructure/segmentation/mobile-sam/model-assets.d.ts +8 -0
- package/dist/infrastructure/segmentation/mobile-sam/model-assets.js +8 -0
- package/dist/infrastructure/segmentation/mobile-sam/object-proposals.d.ts +7 -0
- package/dist/infrastructure/segmentation/mobile-sam/object-proposals.js +124 -0
- package/dist/infrastructure/segmentation/mobile-sam/options.d.ts +43 -0
- package/dist/infrastructure/segmentation/mobile-sam/options.js +19 -0
- package/dist/infrastructure/segmentation/mobile-sam/proposal-masks.d.ts +26 -0
- package/dist/infrastructure/segmentation/mobile-sam/proposal-masks.js +71 -0
- package/dist/infrastructure/segmentation/mobile-sam/segmentation-masks.d.ts +112 -0
- package/dist/infrastructure/segmentation/mobile-sam/segmentation-masks.js +230 -0
- package/dist/infrastructure/segmentation/mobile-sam/segmenter.d.ts +22 -0
- package/dist/infrastructure/segmentation/mobile-sam/segmenter.js +268 -0
- package/dist/infrastructure/segmentation/mobile-sam/worker-expand.d.ts +7 -0
- package/dist/infrastructure/segmentation/mobile-sam/worker-expand.js +188 -0
- package/dist/infrastructure/segmentation/mobile-sam/worker-inference.d.ts +6 -149
- package/dist/infrastructure/segmentation/mobile-sam/worker-inference.js +6 -845
- package/dist/infrastructure/segmentation/mobile-sam/worker-models.d.ts +14 -0
- package/dist/infrastructure/segmentation/mobile-sam/worker-models.js +72 -0
- package/dist/infrastructure/segmentation/mobile-sam/worker-proposals.d.ts +7 -0
- package/dist/infrastructure/segmentation/mobile-sam/worker-proposals.js +159 -0
- package/dist/infrastructure/segmentation/mobile-sam/worker-segment.d.ts +4 -0
- package/dist/infrastructure/segmentation/mobile-sam/worker-segment.js +126 -0
- package/dist/infrastructure/segmentation/native-protocol.d.ts +59 -34
- package/dist/infrastructure/segmentation/native-protocol.js +26 -16
- package/dist/infrastructure/segmentation/proposal-presentation-input.d.ts +20 -0
- package/dist/infrastructure/segmentation/proposal-presentation-input.js +107 -0
- package/dist/infrastructure/segmentation/proposal-presentation-pixels.d.ts +8 -0
- package/dist/infrastructure/segmentation/proposal-presentation-pixels.js +93 -0
- package/dist/infrastructure/segmentation/proposal-presentation.js +10 -201
- package/dist/infrastructure/vision-chat/options.d.ts +62 -0
- package/dist/infrastructure/vision-chat/options.js +46 -0
- package/dist/infrastructure/vision-chat/request.d.ts +23 -0
- package/dist/infrastructure/vision-chat/request.js +109 -0
- package/dist/infrastructure/vision-chat/response.d.ts +3 -0
- package/dist/infrastructure/vision-chat/response.js +105 -0
- package/dist/infrastructure/vision-chat.d.ts +4 -61
- package/dist/infrastructure/vision-chat.js +8 -271
- package/dist/openai-compatible.js +1 -1
- package/dist/processes/extract-from-region.js +11 -216
- package/dist/processes/extract.d.ts +2 -8
- package/dist/processes/extract.js +12 -128
- package/dist/processes/proposal-location.js +5 -251
- package/docs/README.ru.md +50 -33
- package/docs/acceptance.md +6 -4
- package/docs/agents.ru.md +97 -0
- package/docs/api.md +4 -4
- package/docs/architecture.md +33 -7
- package/docs/architecture.ru.md +146 -0
- package/docs/benchmarks.md +3 -1
- package/docs/development.ru.md +141 -0
- package/docs/migrations/experimental-text-image-removal.ru.md +9 -0
- package/docs/provenance.json +288 -1
- package/docs/publishing.md +5 -3
- package/docs/refactoring-plan.ru.md +183 -0
- package/docs/v02-usage.md +8 -8
- package/docs/vision-results.md +1 -1
- package/package.json +5 -3
- package/dist/infrastructure/boundary-view.d.ts +0 -2
- package/dist/infrastructure/boundary-view.js +0 -263
- package/dist/infrastructure/openrouter-common.js +0 -317
- package/dist/infrastructure/text-representation.d.ts +0 -23
- package/dist/infrastructure/text-representation.js +0 -226
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
declare const cvSchema: z.ZodObject<{
|
|
3
|
+
Mat: z.ZodType<(...args: unknown[]) => unknown, z.ZodTypeDef, (...args: unknown[]) => unknown>;
|
|
4
|
+
Rect: z.ZodType<(...args: unknown[]) => unknown, z.ZodTypeDef, (...args: unknown[]) => unknown>;
|
|
5
|
+
cvtColor: z.ZodType<(...args: unknown[]) => unknown, z.ZodTypeDef, (...args: unknown[]) => unknown>;
|
|
6
|
+
grabCut: z.ZodType<(...args: unknown[]) => unknown, z.ZodTypeDef, (...args: unknown[]) => unknown>;
|
|
7
|
+
COLOR_RGBA2RGB: z.ZodNumber;
|
|
8
|
+
CV_8UC4: z.ZodNumber;
|
|
9
|
+
CV_8UC3: z.ZodNumber;
|
|
10
|
+
CV_8UC1: z.ZodNumber;
|
|
11
|
+
GC_BGD: z.ZodNumber;
|
|
12
|
+
GC_FGD: z.ZodNumber;
|
|
13
|
+
GC_PR_BGD: z.ZodNumber;
|
|
14
|
+
GC_PR_FGD: z.ZodNumber;
|
|
15
|
+
GC_INIT_WITH_MASK: z.ZodNumber;
|
|
16
|
+
GC_INIT_WITH_RECT: z.ZodNumber;
|
|
17
|
+
}, "strip", z.ZodTypeAny, {
|
|
18
|
+
Mat: (...args: unknown[]) => unknown;
|
|
19
|
+
Rect: (...args: unknown[]) => unknown;
|
|
20
|
+
cvtColor: (...args: unknown[]) => unknown;
|
|
21
|
+
grabCut: (...args: unknown[]) => unknown;
|
|
22
|
+
COLOR_RGBA2RGB: number;
|
|
23
|
+
CV_8UC4: number;
|
|
24
|
+
CV_8UC3: number;
|
|
25
|
+
CV_8UC1: number;
|
|
26
|
+
GC_BGD: number;
|
|
27
|
+
GC_FGD: number;
|
|
28
|
+
GC_PR_BGD: number;
|
|
29
|
+
GC_PR_FGD: number;
|
|
30
|
+
GC_INIT_WITH_MASK: number;
|
|
31
|
+
GC_INIT_WITH_RECT: number;
|
|
32
|
+
}, {
|
|
33
|
+
Mat: (...args: unknown[]) => unknown;
|
|
34
|
+
Rect: (...args: unknown[]) => unknown;
|
|
35
|
+
cvtColor: (...args: unknown[]) => unknown;
|
|
36
|
+
grabCut: (...args: unknown[]) => unknown;
|
|
37
|
+
COLOR_RGBA2RGB: number;
|
|
38
|
+
CV_8UC4: number;
|
|
39
|
+
CV_8UC3: number;
|
|
40
|
+
CV_8UC1: number;
|
|
41
|
+
GC_BGD: number;
|
|
42
|
+
GC_FGD: number;
|
|
43
|
+
GC_PR_BGD: number;
|
|
44
|
+
GC_PR_FGD: number;
|
|
45
|
+
GC_INIT_WITH_MASK: number;
|
|
46
|
+
GC_INIT_WITH_RECT: number;
|
|
47
|
+
}>;
|
|
48
|
+
export declare function loadOpenCv(path: string): Promise<{
|
|
49
|
+
Mat: (...args: unknown[]) => unknown;
|
|
50
|
+
Rect: (...args: unknown[]) => unknown;
|
|
51
|
+
cvtColor: (...args: unknown[]) => unknown;
|
|
52
|
+
grabCut: (...args: unknown[]) => unknown;
|
|
53
|
+
COLOR_RGBA2RGB: number;
|
|
54
|
+
CV_8UC4: number;
|
|
55
|
+
CV_8UC3: number;
|
|
56
|
+
CV_8UC1: number;
|
|
57
|
+
GC_BGD: number;
|
|
58
|
+
GC_FGD: number;
|
|
59
|
+
GC_PR_BGD: number;
|
|
60
|
+
GC_PR_FGD: number;
|
|
61
|
+
GC_INIT_WITH_MASK: number;
|
|
62
|
+
GC_INIT_WITH_RECT: number;
|
|
63
|
+
}>;
|
|
64
|
+
export declare function probeGrabCut(assetPath: string): Promise<void>;
|
|
65
|
+
interface CvMat {
|
|
66
|
+
data?: unknown;
|
|
67
|
+
delete(): void;
|
|
68
|
+
}
|
|
69
|
+
export declare function matrix(cv: z.infer<typeof cvSchema>, args?: number[]): CvMat;
|
|
70
|
+
export {};
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
import { open } from 'node:fs/promises';
|
|
3
|
+
import { createRequire } from 'node:module';
|
|
4
|
+
import { dirname, resolve } from 'node:path';
|
|
5
|
+
import { Script } from 'node:vm';
|
|
6
|
+
import { z } from 'zod';
|
|
7
|
+
import { grabcutOpenCvArtifact } from './model-asset.js';
|
|
8
|
+
const cvSchema = z.object({
|
|
9
|
+
Mat: z.custom((value) => typeof value === 'function'),
|
|
10
|
+
Rect: z.custom((value) => typeof value === 'function'),
|
|
11
|
+
cvtColor: z.custom((value) => typeof value === 'function'),
|
|
12
|
+
grabCut: z.custom((value) => typeof value === 'function'),
|
|
13
|
+
COLOR_RGBA2RGB: z.number().int(),
|
|
14
|
+
CV_8UC4: z.number().int(),
|
|
15
|
+
CV_8UC3: z.number().int(),
|
|
16
|
+
CV_8UC1: z.number().int(),
|
|
17
|
+
GC_BGD: z.number().int(),
|
|
18
|
+
GC_FGD: z.number().int(),
|
|
19
|
+
GC_PR_BGD: z.number().int(),
|
|
20
|
+
GC_PR_FGD: z.number().int(),
|
|
21
|
+
GC_INIT_WITH_MASK: z.number().int(),
|
|
22
|
+
GC_INIT_WITH_RECT: z.number().int(),
|
|
23
|
+
});
|
|
24
|
+
async function readVerifiedAsset(path) {
|
|
25
|
+
const handle = await open(path, 'r');
|
|
26
|
+
try {
|
|
27
|
+
const stat = await handle.stat();
|
|
28
|
+
if (!stat.isFile() || stat.size !== grabcutOpenCvArtifact.bytes)
|
|
29
|
+
throw new Error('Pinned OpenCV size mismatch');
|
|
30
|
+
const source = Buffer.alloc(grabcutOpenCvArtifact.bytes);
|
|
31
|
+
let offset = 0;
|
|
32
|
+
while (offset < source.length) {
|
|
33
|
+
const read = await handle.read(source, offset, source.length - offset, null);
|
|
34
|
+
if (!read.bytesRead)
|
|
35
|
+
throw new Error('Pinned OpenCV asset read was incomplete');
|
|
36
|
+
offset += read.bytesRead;
|
|
37
|
+
}
|
|
38
|
+
if ((await handle.read(Buffer.alloc(1), 0, 1, null)).bytesRead !== 0)
|
|
39
|
+
throw new Error('Pinned OpenCV asset changed while being read');
|
|
40
|
+
if (createHash('sha256').update(source).digest('hex') !== grabcutOpenCvArtifact.sha256)
|
|
41
|
+
throw new Error('Pinned OpenCV SHA256 mismatch');
|
|
42
|
+
return source.toString('utf8');
|
|
43
|
+
}
|
|
44
|
+
finally {
|
|
45
|
+
await handle.close();
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
export async function loadOpenCv(path) {
|
|
49
|
+
path = resolve(path);
|
|
50
|
+
const source = await readVerifiedAsset(path);
|
|
51
|
+
const wrapper = { exports: {} };
|
|
52
|
+
const factory = new Script('(function(exports,require,module,__filename,__dirname){' + source + '\n})', { filename: path }).runInThisContext();
|
|
53
|
+
if (typeof factory !== 'function')
|
|
54
|
+
throw new Error('Pinned OpenCV asset is not a module');
|
|
55
|
+
Reflect.apply(factory, undefined, [
|
|
56
|
+
wrapper.exports,
|
|
57
|
+
createRequire(path),
|
|
58
|
+
wrapper,
|
|
59
|
+
path,
|
|
60
|
+
dirname(path),
|
|
61
|
+
]);
|
|
62
|
+
const exports = wrapper.exports;
|
|
63
|
+
if (typeof exports === 'object' && exports !== null && 'then' in exports) {
|
|
64
|
+
const then = Reflect.get(exports, 'then');
|
|
65
|
+
if (typeof then === 'function') {
|
|
66
|
+
return await new Promise((resolve, reject) => {
|
|
67
|
+
try {
|
|
68
|
+
Reflect.apply(then, exports, [
|
|
69
|
+
(value) => {
|
|
70
|
+
const checked = cvSchema.safeParse(value);
|
|
71
|
+
if (checked.success)
|
|
72
|
+
resolve(checked.data);
|
|
73
|
+
else
|
|
74
|
+
reject(new Error('Pinned OpenCV namespace is invalid'));
|
|
75
|
+
},
|
|
76
|
+
reject,
|
|
77
|
+
]);
|
|
78
|
+
}
|
|
79
|
+
catch (error) {
|
|
80
|
+
reject(error);
|
|
81
|
+
}
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
return cvSchema.parse(exports);
|
|
86
|
+
}
|
|
87
|
+
export async function probeGrabCut(assetPath) {
|
|
88
|
+
await loadOpenCv(assetPath);
|
|
89
|
+
}
|
|
90
|
+
const matShapeSchema = z
|
|
91
|
+
.object({ delete: z.custom((value) => typeof value === 'function') })
|
|
92
|
+
.passthrough();
|
|
93
|
+
const matSchema = z.custom((value) => matShapeSchema.safeParse(value).success);
|
|
94
|
+
export function matrix(cv, args = []) {
|
|
95
|
+
return matSchema.parse(Reflect.construct(cv.Mat, args));
|
|
96
|
+
}
|
|
@@ -1,47 +1,8 @@
|
|
|
1
1
|
import type { NativeSegmentationReply, NativeSegmentationRequest } from '../native-protocol.js';
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
height: number;
|
|
7
|
-
seedRegion: {
|
|
8
|
-
left: number;
|
|
9
|
-
top: number;
|
|
10
|
-
width: number;
|
|
11
|
-
height: number;
|
|
12
|
-
};
|
|
13
|
-
wholeRegion: {
|
|
14
|
-
left: number;
|
|
15
|
-
top: number;
|
|
16
|
-
width: number;
|
|
17
|
-
height: number;
|
|
18
|
-
};
|
|
19
|
-
roi: {
|
|
20
|
-
left: number;
|
|
21
|
-
top: number;
|
|
22
|
-
width: number;
|
|
23
|
-
height: number;
|
|
24
|
-
};
|
|
25
|
-
prompt: 'whole-region' | 'seed-region';
|
|
26
|
-
labels: {
|
|
27
|
-
background: number;
|
|
28
|
-
foreground: number;
|
|
29
|
-
probableBackground: number;
|
|
30
|
-
probableForeground: number;
|
|
31
|
-
};
|
|
32
|
-
}): void;
|
|
33
|
-
/** Run native GrabCut, then reacquire Mat.data before copying its post-call flags. */
|
|
34
|
-
export declare function runGrabCutAndCopyMask(mat: {
|
|
35
|
-
data?: unknown;
|
|
36
|
-
}, width: number, height: number, roi: {
|
|
37
|
-
left: number;
|
|
38
|
-
top: number;
|
|
39
|
-
width: number;
|
|
40
|
-
height: number;
|
|
41
|
-
}, runNative: () => void, labels: {
|
|
42
|
-
foreground: number;
|
|
43
|
-
probableForeground: number;
|
|
44
|
-
}): Uint8Array;
|
|
2
|
+
import { initializeGrabCutMask, runGrabCutAndCopyMask } from './masks.js';
|
|
3
|
+
import { probeGrabCut } from './runtime.js';
|
|
4
|
+
export { initializeGrabCutMask, runGrabCutAndCopyMask };
|
|
5
|
+
export { probeGrabCut };
|
|
45
6
|
export declare function runGrabCutTask(request: Extract<NativeSegmentationRequest, {
|
|
46
7
|
kind: 'grabcut';
|
|
47
8
|
}>): Promise<NativeSegmentationReply>;
|
|
@@ -1,190 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
import { Script } from 'node:vm';
|
|
6
|
-
import { z } from 'zod';
|
|
7
|
-
const artifact = {
|
|
8
|
-
bytes: 10_964_323,
|
|
9
|
-
sha256: '63366510248adf3a7eddf3e793dd825404efb7df3749f4d6f8557c7fa4ca8aa0',
|
|
10
|
-
};
|
|
11
|
-
const cvSchema = z.object({
|
|
12
|
-
Mat: z.custom((value) => typeof value === 'function'),
|
|
13
|
-
Rect: z.custom((value) => typeof value === 'function'),
|
|
14
|
-
cvtColor: z.custom((value) => typeof value === 'function'),
|
|
15
|
-
grabCut: z.custom((value) => typeof value === 'function'),
|
|
16
|
-
COLOR_RGBA2RGB: z.number().int(),
|
|
17
|
-
CV_8UC4: z.number().int(),
|
|
18
|
-
CV_8UC3: z.number().int(),
|
|
19
|
-
CV_8UC1: z.number().int(),
|
|
20
|
-
GC_BGD: z.number().int(),
|
|
21
|
-
GC_FGD: z.number().int(),
|
|
22
|
-
GC_PR_BGD: z.number().int(),
|
|
23
|
-
GC_PR_FGD: z.number().int(),
|
|
24
|
-
GC_INIT_WITH_MASK: z.number().int(),
|
|
25
|
-
GC_INIT_WITH_RECT: z.number().int(),
|
|
26
|
-
});
|
|
27
|
-
async function readVerifiedAsset(path) {
|
|
28
|
-
const handle = await open(path, 'r');
|
|
29
|
-
try {
|
|
30
|
-
const stat = await handle.stat();
|
|
31
|
-
if (!stat.isFile() || stat.size !== artifact.bytes)
|
|
32
|
-
throw new Error('Pinned OpenCV size mismatch');
|
|
33
|
-
const source = Buffer.alloc(artifact.bytes);
|
|
34
|
-
let offset = 0;
|
|
35
|
-
while (offset < source.length) {
|
|
36
|
-
const read = await handle.read(source, offset, source.length - offset, null);
|
|
37
|
-
if (!read.bytesRead)
|
|
38
|
-
throw new Error('Pinned OpenCV asset read was incomplete');
|
|
39
|
-
offset += read.bytesRead;
|
|
40
|
-
}
|
|
41
|
-
if ((await handle.read(Buffer.alloc(1), 0, 1, null)).bytesRead !== 0)
|
|
42
|
-
throw new Error('Pinned OpenCV asset changed while being read');
|
|
43
|
-
if (createHash('sha256').update(source).digest('hex') !== artifact.sha256)
|
|
44
|
-
throw new Error('Pinned OpenCV SHA256 mismatch');
|
|
45
|
-
return source.toString('utf8');
|
|
46
|
-
}
|
|
47
|
-
finally {
|
|
48
|
-
await handle.close();
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
async function loadOpenCv(path) {
|
|
52
|
-
path = resolve(path);
|
|
53
|
-
const source = await readVerifiedAsset(path);
|
|
54
|
-
const wrapper = { exports: {} };
|
|
55
|
-
const factory = new Script('(function(exports,require,module,__filename,__dirname){' + source + '\n})', { filename: path }).runInThisContext();
|
|
56
|
-
if (typeof factory !== 'function')
|
|
57
|
-
throw new Error('Pinned OpenCV asset is not a module');
|
|
58
|
-
Reflect.apply(factory, undefined, [
|
|
59
|
-
wrapper.exports,
|
|
60
|
-
createRequire(path),
|
|
61
|
-
wrapper,
|
|
62
|
-
path,
|
|
63
|
-
dirname(path),
|
|
64
|
-
]);
|
|
65
|
-
const exports = wrapper.exports;
|
|
66
|
-
if (typeof exports === 'object' && exports !== null && 'then' in exports) {
|
|
67
|
-
const then = Reflect.get(exports, 'then');
|
|
68
|
-
if (typeof then === 'function') {
|
|
69
|
-
return await new Promise((resolve, reject) => {
|
|
70
|
-
try {
|
|
71
|
-
Reflect.apply(then, exports, [
|
|
72
|
-
(value) => {
|
|
73
|
-
const checked = cvSchema.safeParse(value);
|
|
74
|
-
if (checked.success)
|
|
75
|
-
resolve(checked.data);
|
|
76
|
-
else
|
|
77
|
-
reject(new Error('Pinned OpenCV namespace is invalid'));
|
|
78
|
-
},
|
|
79
|
-
reject,
|
|
80
|
-
]);
|
|
81
|
-
}
|
|
82
|
-
catch (error) {
|
|
83
|
-
reject(error);
|
|
84
|
-
}
|
|
85
|
-
});
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
return cvSchema.parse(exports);
|
|
89
|
-
}
|
|
90
|
-
export async function probeGrabCut(assetPath) {
|
|
91
|
-
await loadOpenCv(assetPath);
|
|
92
|
-
}
|
|
93
|
-
const matShapeSchema = z
|
|
94
|
-
.object({ delete: z.custom((value) => typeof value === 'function') })
|
|
95
|
-
.passthrough();
|
|
96
|
-
const matSchema = z.custom((value) => matShapeSchema.safeParse(value).success);
|
|
97
|
-
function matrix(cv, args = []) {
|
|
98
|
-
return matSchema.parse(Reflect.construct(cv.Mat, args));
|
|
99
|
-
}
|
|
100
|
-
function getBytes(mat, length) {
|
|
101
|
-
const bytes = z.instanceof(Uint8Array).parse(mat.data);
|
|
102
|
-
if (bytes.length !== length)
|
|
103
|
-
throw new Error('OpenCV matrix dimensions do not match');
|
|
104
|
-
return bytes;
|
|
105
|
-
}
|
|
106
|
-
export function initializeGrabCutMask(input) {
|
|
107
|
-
if (input.flags.length !== input.width * input.height)
|
|
108
|
-
throw new Error('GrabCut mask dimensions do not match source');
|
|
109
|
-
input.flags.fill(input.labels.background);
|
|
110
|
-
if (input.prompt === 'whole-region') {
|
|
111
|
-
for (let y = input.wholeRegion.top; y < input.wholeRegion.top + input.wholeRegion.height; y++)
|
|
112
|
-
for (let x = input.wholeRegion.left; x < input.wholeRegion.left + input.wholeRegion.width; x++)
|
|
113
|
-
input.flags[y * input.width + x] = input.labels.probableForeground;
|
|
114
|
-
}
|
|
115
|
-
else {
|
|
116
|
-
for (let y = input.roi.top; y < input.roi.top + input.roi.height; y++)
|
|
117
|
-
for (let x = input.roi.left; x < input.roi.left + input.roi.width; x++)
|
|
118
|
-
input.flags[y * input.width + x] = input.labels.probableBackground;
|
|
119
|
-
}
|
|
120
|
-
const seedLeft = Math.max(input.seedRegion.left, input.roi.left);
|
|
121
|
-
const seedTop = Math.max(input.seedRegion.top, input.roi.top);
|
|
122
|
-
const seedRight = Math.min(input.seedRegion.left + input.seedRegion.width, input.roi.left + input.roi.width);
|
|
123
|
-
const seedBottom = Math.min(input.seedRegion.top + input.seedRegion.height, input.roi.top + input.roi.height);
|
|
124
|
-
if (seedLeft >= seedRight || seedTop >= seedBottom)
|
|
125
|
-
throw new Error('GrabCut seed region does not intersect hard ROI');
|
|
126
|
-
for (let y = seedTop; y < seedBottom; y++)
|
|
127
|
-
for (let x = seedLeft; x < seedRight; x++)
|
|
128
|
-
input.flags[y * input.width + x] = input.labels.foreground;
|
|
129
|
-
}
|
|
130
|
-
/** Run native GrabCut, then reacquire Mat.data before copying its post-call flags. */
|
|
131
|
-
export function runGrabCutAndCopyMask(mat, width, height, roi, runNative, labels) {
|
|
132
|
-
runNative();
|
|
133
|
-
const flags = getBytes(mat, width * height);
|
|
134
|
-
const output = new Uint8Array(width * height);
|
|
135
|
-
for (let y = roi.top; y < roi.top + roi.height; y++) {
|
|
136
|
-
for (let x = roi.left; x < roi.left + roi.width; x++) {
|
|
137
|
-
const at = y * width + x;
|
|
138
|
-
const flag = flags[at];
|
|
139
|
-
if (flag === labels.foreground || flag === labels.probableForeground)
|
|
140
|
-
output[at] = 1;
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
return output;
|
|
144
|
-
}
|
|
145
|
-
function seededComponents(mask, width, height, input) {
|
|
146
|
-
const visited = new Uint8Array(mask.length);
|
|
147
|
-
const output = new Uint8Array(mask.length);
|
|
148
|
-
const stack = [];
|
|
149
|
-
for (let start = 0; start < mask.length; start++) {
|
|
150
|
-
if (mask[start] !== 1 || visited[start] === 1)
|
|
151
|
-
continue;
|
|
152
|
-
stack.push(start);
|
|
153
|
-
visited[start] = 1;
|
|
154
|
-
const component = [];
|
|
155
|
-
let hitsSeed = false;
|
|
156
|
-
while (stack.length) {
|
|
157
|
-
const at = stack.pop();
|
|
158
|
-
if (at === undefined)
|
|
159
|
-
continue;
|
|
160
|
-
component.push(at);
|
|
161
|
-
const x = at % width;
|
|
162
|
-
const y = Math.floor(at / width);
|
|
163
|
-
if (x >= input.seedRegion.left &&
|
|
164
|
-
y >= input.seedRegion.top &&
|
|
165
|
-
x < input.seedRegion.left + input.seedRegion.width &&
|
|
166
|
-
y < input.seedRegion.top + input.seedRegion.height)
|
|
167
|
-
hitsSeed = true;
|
|
168
|
-
const neighbors = [at - 1, at + 1, at - width, at + width];
|
|
169
|
-
for (const neighbor of neighbors) {
|
|
170
|
-
if (neighbor < 0 ||
|
|
171
|
-
neighbor >= mask.length ||
|
|
172
|
-
visited[neighbor] === 1 ||
|
|
173
|
-
mask[neighbor] !== 1)
|
|
174
|
-
continue;
|
|
175
|
-
const nx = neighbor % width;
|
|
176
|
-
if (Math.abs(nx - x) + Math.abs(Math.floor(neighbor / width) - y) !== 1)
|
|
177
|
-
continue;
|
|
178
|
-
visited[neighbor] = 1;
|
|
179
|
-
stack.push(neighbor);
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
if (hitsSeed)
|
|
183
|
-
for (const index of component)
|
|
184
|
-
output[index] = 1;
|
|
185
|
-
}
|
|
186
|
-
return output;
|
|
187
|
-
}
|
|
1
|
+
import { getBytes, initializeGrabCutMask, runGrabCutAndCopyMask, seededComponents, } from './masks.js';
|
|
2
|
+
import { loadOpenCv, matrix, probeGrabCut } from './runtime.js';
|
|
3
|
+
export { initializeGrabCutMask, runGrabCutAndCopyMask };
|
|
4
|
+
export { probeGrabCut };
|
|
188
5
|
export async function runGrabCutTask(request) {
|
|
189
6
|
const cv = await loadOpenCv(request.assetPath);
|
|
190
7
|
const pixels = request.width * request.height;
|
|
@@ -1,66 +1,3 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
import { NativeChildPool } from '../native-child.js';
|
|
5
|
-
import { type NativeSegmentationRequest } from '../native-protocol.js';
|
|
6
|
-
declare const optionsSchema: z.ZodObject<{
|
|
7
|
-
encoderPath: z.ZodString;
|
|
8
|
-
decoderPath: z.ZodString;
|
|
9
|
-
executionProvider: z.ZodDefault<z.ZodEnum<["cpu", "dml"]>>;
|
|
10
|
-
deviceId: z.ZodOptional<z.ZodNumber>;
|
|
11
|
-
threads: z.ZodDefault<z.ZodNumber>;
|
|
12
|
-
}, "strict", z.ZodTypeAny, {
|
|
13
|
-
encoderPath: string;
|
|
14
|
-
decoderPath: string;
|
|
15
|
-
executionProvider: "cpu" | "dml";
|
|
16
|
-
threads: number;
|
|
17
|
-
deviceId?: number | undefined;
|
|
18
|
-
}, {
|
|
19
|
-
encoderPath: string;
|
|
20
|
-
decoderPath: string;
|
|
21
|
-
executionProvider?: "cpu" | "dml" | undefined;
|
|
22
|
-
deviceId?: number | undefined;
|
|
23
|
-
threads?: number | undefined;
|
|
24
|
-
}>;
|
|
25
|
-
/** @experimental Options for the unqualified MobileSAM segmentation factory. */
|
|
26
|
-
export type MobileSamSegmenterOptions = z.input<typeof optionsSchema>;
|
|
27
|
-
declare const proposalOptionsSchema: z.ZodObject<{
|
|
28
|
-
encoderPath: z.ZodString;
|
|
29
|
-
decoderPath: z.ZodString;
|
|
30
|
-
executionProvider: z.ZodDefault<z.ZodLiteral<"cpu">>;
|
|
31
|
-
threads: z.ZodDefault<z.ZodNumber>;
|
|
32
|
-
}, "strict", z.ZodTypeAny, {
|
|
33
|
-
encoderPath: string;
|
|
34
|
-
decoderPath: string;
|
|
35
|
-
executionProvider: "cpu";
|
|
36
|
-
threads: number;
|
|
37
|
-
}, {
|
|
38
|
-
encoderPath: string;
|
|
39
|
-
decoderPath: string;
|
|
40
|
-
executionProvider?: "cpu" | undefined;
|
|
41
|
-
threads?: number | undefined;
|
|
42
|
-
}>;
|
|
43
|
-
/** @experimental Options for the unqualified MobileSAM object-proposal factory. */
|
|
44
|
-
export type MobileSamObjectProposalsOptions = z.input<typeof proposalOptionsSchema>;
|
|
45
|
-
type SerializedTask = (Omit<Extract<NativeSegmentationRequest, {
|
|
46
|
-
kind: 'mobile-sam';
|
|
47
|
-
}>, 'id' | 'rgba'> & {
|
|
48
|
-
rgba: string;
|
|
49
|
-
}) | (Omit<Extract<NativeSegmentationRequest, {
|
|
50
|
-
kind: 'mobile-sam-expand';
|
|
51
|
-
}>, 'id' | 'rgba'> & {
|
|
52
|
-
rgba: string;
|
|
53
|
-
});
|
|
54
|
-
/**
|
|
55
|
-
* Explicit pinned MobileSAM inference in a separately owned Node child process.
|
|
56
|
-
* @experimental Native segmentation adapter; unqualified for general mask or object accuracy.
|
|
57
|
-
*/
|
|
58
|
-
export declare function createMobileSamSegmenter(options: MobileSamSegmenterOptions): Promise<SegmentationPort>;
|
|
59
|
-
/** Internal adapter seam: pool ownership stays with the caller. */
|
|
60
|
-
export declare function createMobileSamPortForPool(pool: Pick<NativeChildPool<SerializedTask>, 'runLazy' | 'settle' | 'dispose'>, parsed: z.output<typeof optionsSchema>): SegmentationPort & Required<Pick<SegmentationPort, 'expand'>>;
|
|
61
|
-
/**
|
|
62
|
-
* Explicit CPU-only, caller-owned one-shot 3x3-point / 36-mask proposal adapter.
|
|
63
|
-
* @experimental Native proposal adapter; unqualified for general spatial or mask accuracy.
|
|
64
|
-
*/
|
|
65
|
-
export declare function createMobileSamObjectProposals(options: MobileSamObjectProposalsOptions): Promise<ObjectProposalPort>;
|
|
66
|
-
export {};
|
|
1
|
+
export type { MobileSamSegmenterOptions, MobileSamObjectProposalsOptions } from './options.js';
|
|
2
|
+
export { createMobileSamSegmenter, createMobileSamPortForPool } from './segmenter.js';
|
|
3
|
+
export { createMobileSamObjectProposals } from './object-proposals.js';
|