@meta-sam/graphics 0.1.5
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/LICENSE +61 -0
- package/README.md +490 -0
- package/dist/contour.d.ts +34 -0
- package/dist/contour.js +230 -0
- package/dist/errors.d.ts +24 -0
- package/dist/errors.js +45 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +5 -0
- package/dist/renderer.d.ts +111 -0
- package/dist/renderer.js +649 -0
- package/package.json +43 -0
package/dist/contour.js
ADDED
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates. All Rights Reserved.
|
|
3
|
+
*/
|
|
4
|
+
import { SegmentationResourceLimitError } from './errors.js';
|
|
5
|
+
/**
|
|
6
|
+
* A contour this small is a lone pixel or a two-pixel sliver, whose polygon is
|
|
7
|
+
* already smaller than the stroke. Smoothing would shrink it further — the
|
|
8
|
+
* single-pixel diamond loses a quarter of its radius — so it keeps its
|
|
9
|
+
* straight segments and stays a visible mark.
|
|
10
|
+
*/
|
|
11
|
+
const SMALL_CONTOUR_VERTICES = 4;
|
|
12
|
+
/**
|
|
13
|
+
* Doubled lattice coordinate to SVG user units. Vertices sit on half pixels
|
|
14
|
+
* and their midpoints on quarter pixels, so one decimal is exact for a vertex
|
|
15
|
+
* and rounds a midpoint by at most 0.05 source pixels — two orders of
|
|
16
|
+
* magnitude under the stroke width, and it keeps the path string short.
|
|
17
|
+
*/
|
|
18
|
+
function coordinate(doubled) {
|
|
19
|
+
return String(Math.round(doubled * 5) / 10);
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Marching-squares cell cases. A cell spans four pixel centers, so its corners
|
|
23
|
+
* are the centers of pixels (cx, cy), (cx + 1, cy), (cx + 1, cy + 1) and
|
|
24
|
+
* (cx, cy + 1); the grid runs from cx = -1 so that the border of the raster is
|
|
25
|
+
* covered by cells whose outer corners are empty.
|
|
26
|
+
*/
|
|
27
|
+
const TOP_LEFT = 1;
|
|
28
|
+
const TOP_RIGHT = 2;
|
|
29
|
+
const BOTTOM_RIGHT = 4;
|
|
30
|
+
const BOTTOM_LEFT = 8;
|
|
31
|
+
/**
|
|
32
|
+
* Crossing vertices, in doubled coordinates so every lattice point is an
|
|
33
|
+
* integer: a crossing sits at the midpoint of the cell edge it cuts, which is
|
|
34
|
+
* always half a pixel from one pixel center and half a pixel from the next.
|
|
35
|
+
*/
|
|
36
|
+
function topVertex(cx, cy, stride) {
|
|
37
|
+
return (2 * cy + 1) * stride + (2 * cx + 2);
|
|
38
|
+
}
|
|
39
|
+
function rightVertex(cx, cy, stride) {
|
|
40
|
+
return (2 * cy + 2) * stride + (2 * cx + 3);
|
|
41
|
+
}
|
|
42
|
+
function bottomVertex(cx, cy, stride) {
|
|
43
|
+
return (2 * cy + 3) * stride + (2 * cx + 2);
|
|
44
|
+
}
|
|
45
|
+
function leftVertex(cx, cy, stride) {
|
|
46
|
+
return (2 * cy + 2) * stride + (2 * cx + 1);
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Emits a decimated polygon as straight segments, the geometry the tracer
|
|
50
|
+
* produced before any smoothing.
|
|
51
|
+
*/
|
|
52
|
+
function polyline(vx, vy) {
|
|
53
|
+
let part = `M${coordinate(vx[0])} ${coordinate(vy[0])}`;
|
|
54
|
+
for (let index = 1; index < vx.length; index += 1) {
|
|
55
|
+
part += `L${coordinate(vx[index])} ${coordinate(vy[index])}`;
|
|
56
|
+
}
|
|
57
|
+
return `${part}Z`;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Emits a closed polygon as a uniform quadratic B-spline: the curve runs
|
|
61
|
+
* through the midpoint of every edge and takes each vertex as the control
|
|
62
|
+
* point between two midpoints, so `M m₀ Q p₁ m₁ … Q p₀ m₀ Z`.
|
|
63
|
+
*
|
|
64
|
+
* The curve therefore never passes through a vertex: a 1-pixel step becomes a
|
|
65
|
+
* curve instead of a corner, while the middle of a long edge is a knot the
|
|
66
|
+
* curve interpolates with the edge's own tangent, so decimated straight runs
|
|
67
|
+
* stay straight. A vertex is pulled toward the chord of its two midpoints by
|
|
68
|
+
* an eighth of the difference of its edge vectors, which for the 45° bevel
|
|
69
|
+
* marching squares puts on a right-angle corner is under half a source pixel.
|
|
70
|
+
*/
|
|
71
|
+
function spline(vx, vy) {
|
|
72
|
+
const total = vx.length;
|
|
73
|
+
const midX = (index) => (vx[index] + vx[(index + 1) % total]) / 2;
|
|
74
|
+
const midY = (index) => (vy[index] + vy[(index + 1) % total]) / 2;
|
|
75
|
+
const startX = coordinate(midX(0));
|
|
76
|
+
const startY = coordinate(midY(0));
|
|
77
|
+
let part = `M${startX} ${startY}`;
|
|
78
|
+
for (let index = 1; index < total; index += 1) {
|
|
79
|
+
part += `Q${coordinate(vx[index])} ${coordinate(vy[index])} ${coordinate(midX(index))} ${coordinate(midY(index))}`;
|
|
80
|
+
}
|
|
81
|
+
return `${part}Q${coordinate(vx[0])} ${coordinate(vy[0])} ${startX} ${startY}Z`;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Traces the contour of a binary raster as closed polygons with marching
|
|
85
|
+
* squares, then smooths each polygon.
|
|
86
|
+
*
|
|
87
|
+
* Contour vertices are the midpoints of the edges between neighbouring pixel
|
|
88
|
+
* centers, so a boundary that runs straight follows the pixel edge exactly
|
|
89
|
+
* while a corner or a diagonal is cut at 45° instead of stepping. Every
|
|
90
|
+
* segment is emitted with the filled region on its right, which makes outer
|
|
91
|
+
* contours wind opposite to the holes they enclose; the caller fills the
|
|
92
|
+
* result with `evenodd` and strokes the same path.
|
|
93
|
+
*
|
|
94
|
+
* The two saddle cases (a filled diagonal pair) are both resolved as a filled
|
|
95
|
+
* center, matching the eight-connected reading of the raster. That choice is
|
|
96
|
+
* what makes every crossing the endpoint of exactly one segment, so chaining
|
|
97
|
+
* the segments is a walk rather than a search.
|
|
98
|
+
*
|
|
99
|
+
* A polygon is then decimated — a vertex the contour passes straight through
|
|
100
|
+
* is dropped, collapsing a straight run to its two endpoints — and emitted as
|
|
101
|
+
* a quadratic B-spline through the edge midpoints, which turns the 1-pixel
|
|
102
|
+
* staircase of a native-resolution mask into a smooth boundary. Contours of at
|
|
103
|
+
* most `SMALL_CONTOUR_VERTICES` vertices keep their straight segments.
|
|
104
|
+
*/
|
|
105
|
+
export function traceContour(raster, width, height, limit, options = {}) {
|
|
106
|
+
const smooth = options.smooth !== false;
|
|
107
|
+
const stride = 2 * width + 1;
|
|
108
|
+
/** Start vertex to end vertex; each vertex starts at most one segment. */
|
|
109
|
+
const next = new Map();
|
|
110
|
+
for (let cy = -1; cy < height; cy += 1) {
|
|
111
|
+
const topRow = cy >= 0 ? cy * width : -1;
|
|
112
|
+
const bottomRow = cy + 1 < height ? (cy + 1) * width : -1;
|
|
113
|
+
let topLeft = 0;
|
|
114
|
+
let bottomLeft = 0;
|
|
115
|
+
for (let cx = -1; cx < width; cx += 1) {
|
|
116
|
+
const column = cx + 1;
|
|
117
|
+
const inside = column < width;
|
|
118
|
+
const topRight = topRow >= 0 && inside ? raster[topRow + column] : 0;
|
|
119
|
+
const bottomRight = bottomRow >= 0 && inside ? raster[bottomRow + column] : 0;
|
|
120
|
+
const corners = (topLeft === 1 ? TOP_LEFT : 0) |
|
|
121
|
+
(topRight === 1 ? TOP_RIGHT : 0) |
|
|
122
|
+
(bottomRight === 1 ? BOTTOM_RIGHT : 0) |
|
|
123
|
+
(bottomLeft === 1 ? BOTTOM_LEFT : 0);
|
|
124
|
+
topLeft = topRight;
|
|
125
|
+
bottomLeft = bottomRight;
|
|
126
|
+
if (corners === 0 || corners === 15)
|
|
127
|
+
continue;
|
|
128
|
+
switch (corners) {
|
|
129
|
+
case TOP_LEFT:
|
|
130
|
+
next.set(topVertex(cx, cy, stride), leftVertex(cx, cy, stride));
|
|
131
|
+
break;
|
|
132
|
+
case TOP_RIGHT:
|
|
133
|
+
next.set(rightVertex(cx, cy, stride), topVertex(cx, cy, stride));
|
|
134
|
+
break;
|
|
135
|
+
case BOTTOM_RIGHT:
|
|
136
|
+
next.set(bottomVertex(cx, cy, stride), rightVertex(cx, cy, stride));
|
|
137
|
+
break;
|
|
138
|
+
case BOTTOM_LEFT:
|
|
139
|
+
next.set(leftVertex(cx, cy, stride), bottomVertex(cx, cy, stride));
|
|
140
|
+
break;
|
|
141
|
+
case TOP_LEFT | TOP_RIGHT:
|
|
142
|
+
next.set(rightVertex(cx, cy, stride), leftVertex(cx, cy, stride));
|
|
143
|
+
break;
|
|
144
|
+
case TOP_RIGHT | BOTTOM_RIGHT:
|
|
145
|
+
next.set(bottomVertex(cx, cy, stride), topVertex(cx, cy, stride));
|
|
146
|
+
break;
|
|
147
|
+
case BOTTOM_RIGHT | BOTTOM_LEFT:
|
|
148
|
+
next.set(leftVertex(cx, cy, stride), rightVertex(cx, cy, stride));
|
|
149
|
+
break;
|
|
150
|
+
case TOP_LEFT | BOTTOM_LEFT:
|
|
151
|
+
next.set(topVertex(cx, cy, stride), bottomVertex(cx, cy, stride));
|
|
152
|
+
break;
|
|
153
|
+
case TOP_RIGHT | BOTTOM_RIGHT | BOTTOM_LEFT:
|
|
154
|
+
next.set(leftVertex(cx, cy, stride), topVertex(cx, cy, stride));
|
|
155
|
+
break;
|
|
156
|
+
case TOP_LEFT | BOTTOM_RIGHT | BOTTOM_LEFT:
|
|
157
|
+
next.set(topVertex(cx, cy, stride), rightVertex(cx, cy, stride));
|
|
158
|
+
break;
|
|
159
|
+
case TOP_LEFT | TOP_RIGHT | BOTTOM_LEFT:
|
|
160
|
+
next.set(rightVertex(cx, cy, stride), bottomVertex(cx, cy, stride));
|
|
161
|
+
break;
|
|
162
|
+
case TOP_LEFT | TOP_RIGHT | BOTTOM_RIGHT:
|
|
163
|
+
next.set(bottomVertex(cx, cy, stride), leftVertex(cx, cy, stride));
|
|
164
|
+
break;
|
|
165
|
+
case TOP_LEFT | BOTTOM_RIGHT:
|
|
166
|
+
next.set(topVertex(cx, cy, stride), rightVertex(cx, cy, stride));
|
|
167
|
+
next.set(bottomVertex(cx, cy, stride), leftVertex(cx, cy, stride));
|
|
168
|
+
break;
|
|
169
|
+
default:
|
|
170
|
+
// TOP_RIGHT | BOTTOM_LEFT, the other saddle.
|
|
171
|
+
next.set(leftVertex(cx, cy, stride), topVertex(cx, cy, stride));
|
|
172
|
+
next.set(rightVertex(cx, cy, stride), bottomVertex(cx, cy, stride));
|
|
173
|
+
break;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
const parts = [];
|
|
178
|
+
let complexity = 0;
|
|
179
|
+
const points = [];
|
|
180
|
+
const vx = [];
|
|
181
|
+
const vy = [];
|
|
182
|
+
while (next.size > 0) {
|
|
183
|
+
const start = next.keys().next().value;
|
|
184
|
+
points.length = 0;
|
|
185
|
+
let vertex = start;
|
|
186
|
+
for (;;) {
|
|
187
|
+
const following = next.get(vertex);
|
|
188
|
+
if (following === undefined)
|
|
189
|
+
break;
|
|
190
|
+
next.delete(vertex);
|
|
191
|
+
points.push(vertex);
|
|
192
|
+
vertex = following;
|
|
193
|
+
if (vertex === start)
|
|
194
|
+
break;
|
|
195
|
+
}
|
|
196
|
+
const total = points.length;
|
|
197
|
+
if (total < 3)
|
|
198
|
+
continue;
|
|
199
|
+
vx.length = 0;
|
|
200
|
+
vy.length = 0;
|
|
201
|
+
for (let index = 0; index < total; index += 1) {
|
|
202
|
+
const point = points[index];
|
|
203
|
+
const previous = points[(index + total - 1) % total];
|
|
204
|
+
const following = points[(index + 1) % total];
|
|
205
|
+
const x = point % stride;
|
|
206
|
+
const y = (point - x) / stride;
|
|
207
|
+
const previousX = previous % stride;
|
|
208
|
+
const followingX = following % stride;
|
|
209
|
+
// Drop a vertex the contour passes straight through, so a run of cells
|
|
210
|
+
// along one pixel edge — or one 45° diagonal — collapses to its two
|
|
211
|
+
// endpoints. Every step of the walk is one cell wide, so equal steps in
|
|
212
|
+
// and out are exactly the collinear case.
|
|
213
|
+
if (followingX - x === x - previousX &&
|
|
214
|
+
(following - followingX) / stride - y === y - (previous - previousX) / stride) {
|
|
215
|
+
continue;
|
|
216
|
+
}
|
|
217
|
+
vx.push(x);
|
|
218
|
+
vy.push(y);
|
|
219
|
+
}
|
|
220
|
+
if (vx.length < 3)
|
|
221
|
+
continue;
|
|
222
|
+
const part = smooth && vx.length > SMALL_CONTOUR_VERTICES ? spline(vx, vy) : polyline(vx, vy);
|
|
223
|
+
complexity += part.length;
|
|
224
|
+
if (complexity > limit) {
|
|
225
|
+
throw new SegmentationResourceLimitError('maxPathComplexity');
|
|
226
|
+
}
|
|
227
|
+
parts.push(part);
|
|
228
|
+
}
|
|
229
|
+
return { d: parts.join(''), complexity };
|
|
230
|
+
}
|
package/dist/errors.d.ts
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export declare class SegmentationGraphicsError extends Error {
|
|
2
|
+
readonly code: string;
|
|
3
|
+
constructor(message: string, code: string, options?: ErrorOptions);
|
|
4
|
+
}
|
|
5
|
+
export declare class UnsupportedMaskEncodingError extends SegmentationGraphicsError {
|
|
6
|
+
readonly encoding: string;
|
|
7
|
+
constructor(encoding: string);
|
|
8
|
+
}
|
|
9
|
+
export declare class InvalidMaskPayloadError extends SegmentationGraphicsError {
|
|
10
|
+
constructor(message: string);
|
|
11
|
+
}
|
|
12
|
+
export declare class SegmentationResourceLimitError extends SegmentationGraphicsError {
|
|
13
|
+
readonly limit: string;
|
|
14
|
+
constructor(limit: string);
|
|
15
|
+
}
|
|
16
|
+
export declare class InvalidRenderOptionsError extends SegmentationGraphicsError {
|
|
17
|
+
constructor(message: string);
|
|
18
|
+
}
|
|
19
|
+
export declare class RendererDisposedError extends SegmentationGraphicsError {
|
|
20
|
+
constructor();
|
|
21
|
+
}
|
|
22
|
+
export declare class Path2DUnavailableError extends SegmentationGraphicsError {
|
|
23
|
+
constructor();
|
|
24
|
+
}
|
package/dist/errors.js
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates. All Rights Reserved.
|
|
3
|
+
*/
|
|
4
|
+
export class SegmentationGraphicsError extends Error {
|
|
5
|
+
code;
|
|
6
|
+
constructor(message, code, options) {
|
|
7
|
+
super(message, options);
|
|
8
|
+
this.code = code;
|
|
9
|
+
this.name = new.target.name;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
export class UnsupportedMaskEncodingError extends SegmentationGraphicsError {
|
|
13
|
+
encoding;
|
|
14
|
+
constructor(encoding) {
|
|
15
|
+
super(`Unsupported complete mask encoding: ${encoding}.`, 'unsupported_encoding');
|
|
16
|
+
this.encoding = encoding;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
export class InvalidMaskPayloadError extends SegmentationGraphicsError {
|
|
20
|
+
constructor(message) {
|
|
21
|
+
super(message, 'invalid_mask_payload');
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
export class SegmentationResourceLimitError extends SegmentationGraphicsError {
|
|
25
|
+
limit;
|
|
26
|
+
constructor(limit) {
|
|
27
|
+
super(`Segmentation rendering exceeded the ${limit} limit.`, 'resource_limit');
|
|
28
|
+
this.limit = limit;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
export class InvalidRenderOptionsError extends SegmentationGraphicsError {
|
|
32
|
+
constructor(message) {
|
|
33
|
+
super(message, 'invalid_render_options');
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
export class RendererDisposedError extends SegmentationGraphicsError {
|
|
37
|
+
constructor() {
|
|
38
|
+
super('The segmentation renderer has been disposed.', 'renderer_disposed');
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
export class Path2DUnavailableError extends SegmentationGraphicsError {
|
|
42
|
+
constructor() {
|
|
43
|
+
super('Path2D is unavailable in this environment.', 'path2d_unavailable');
|
|
44
|
+
}
|
|
45
|
+
}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export { InvalidMaskPayloadError, InvalidRenderOptionsError, Path2DUnavailableError, RendererDisposedError, SegmentationGraphicsError, SegmentationResourceLimitError, UnsupportedMaskEncodingError, } from './errors.js';
|
|
2
|
+
export { SegmentationRenderer, objectColor } from './renderer.js';
|
|
3
|
+
export type { ImageRenderOptions, MaskOutlineOptions, Rectangle, SegmentationCanvasContext, SegmentationRendererOptions, SegmentationRenderOptions, SegmentationUpdateOptions, VideoFrameCompositionContext, VideoFrameCompositionOptions, VideoFrameFit, VideoRenderOptions, } from './renderer.js';
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates. All Rights Reserved.
|
|
3
|
+
*/
|
|
4
|
+
export { InvalidMaskPayloadError, InvalidRenderOptionsError, Path2DUnavailableError, RendererDisposedError, SegmentationGraphicsError, SegmentationResourceLimitError, UnsupportedMaskEncodingError, } from './errors.js';
|
|
5
|
+
export { SegmentationRenderer, objectColor } from './renderer.js';
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { type SegmentationResult, type SegmentationSnapshot } from '@meta-sam/parser';
|
|
2
|
+
export interface Rectangle {
|
|
3
|
+
readonly x: number;
|
|
4
|
+
readonly y: number;
|
|
5
|
+
readonly width: number;
|
|
6
|
+
readonly height: number;
|
|
7
|
+
}
|
|
8
|
+
export type SegmentationCanvasContext = CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D;
|
|
9
|
+
export type VideoFrameFit = 'contain' | 'cover' | 'fill';
|
|
10
|
+
/**
|
|
11
|
+
* Structural subset of a Canvas media-player render context.
|
|
12
|
+
*
|
|
13
|
+
* This deliberately does not import @meta-sam/video, so graphics and video remain
|
|
14
|
+
* independently usable without a dependency cycle.
|
|
15
|
+
*/
|
|
16
|
+
export interface VideoFrameCompositionContext {
|
|
17
|
+
readonly frame: CanvasImageSource & {
|
|
18
|
+
readonly width: number;
|
|
19
|
+
readonly height: number;
|
|
20
|
+
};
|
|
21
|
+
readonly frameIndex: number;
|
|
22
|
+
readonly canvas: {
|
|
23
|
+
readonly width: number;
|
|
24
|
+
readonly height: number;
|
|
25
|
+
};
|
|
26
|
+
readonly ctx: SegmentationCanvasContext;
|
|
27
|
+
/** Optional bare-frame surface supplied by @meta-sam/video for deadline fallback. */
|
|
28
|
+
readonly fallbackCanvas?: {
|
|
29
|
+
readonly width: number;
|
|
30
|
+
readonly height: number;
|
|
31
|
+
};
|
|
32
|
+
readonly fallbackCtx?: SegmentationCanvasContext;
|
|
33
|
+
readonly signal: AbortSignal;
|
|
34
|
+
}
|
|
35
|
+
export interface VideoFrameCompositionOptions {
|
|
36
|
+
/** Fit the decoded frame into the logical canvas. Defaults to contain. */
|
|
37
|
+
readonly fit?: VideoFrameFit;
|
|
38
|
+
/** Logical-to-backing-store scale. Defaults to 1 and may be read per render. */
|
|
39
|
+
readonly devicePixelRatio?: number | (() => number);
|
|
40
|
+
/** Object IDs, not mask identities, to omit from this composition. */
|
|
41
|
+
readonly hiddenIds?: ReadonlySet<string> | readonly string[];
|
|
42
|
+
}
|
|
43
|
+
export interface MaskOutlineOptions {
|
|
44
|
+
/**
|
|
45
|
+
* Contour width in source pixels — the same space as mask rasters and box
|
|
46
|
+
* edges, so it scales with the source-to-target transform. Defaults to
|
|
47
|
+
* `0.003 × min(source.width, source.height)`.
|
|
48
|
+
*/
|
|
49
|
+
readonly width?: number;
|
|
50
|
+
/** Contour opacity. Defaults to 0.8. */
|
|
51
|
+
readonly opacity?: number;
|
|
52
|
+
}
|
|
53
|
+
export interface SegmentationRendererOptions {
|
|
54
|
+
/** Mask fill opacity. Defaults to 0.35. */
|
|
55
|
+
readonly maskFillOpacity?: number;
|
|
56
|
+
/**
|
|
57
|
+
* Stroke the mask contour in the object color on top of the translucent
|
|
58
|
+
* fill. Defaults to enabled; pass `false` for fill only.
|
|
59
|
+
*/
|
|
60
|
+
readonly maskOutline?: boolean | MaskOutlineOptions;
|
|
61
|
+
/** Traced paths kept in the LRU cache. */
|
|
62
|
+
readonly maxCachedPaths?: number;
|
|
63
|
+
/** Total traced-path characters kept in the LRU cache. */
|
|
64
|
+
readonly maxCachedComplexity?: number;
|
|
65
|
+
readonly maxRecords?: number;
|
|
66
|
+
readonly maxMasks?: number;
|
|
67
|
+
readonly maxBoxes?: number;
|
|
68
|
+
readonly maxMaskArea?: number;
|
|
69
|
+
readonly maxMaskPayloadLength?: number;
|
|
70
|
+
/** Traced characters a single mask may produce before it fails. */
|
|
71
|
+
readonly maxPathComplexity?: number;
|
|
72
|
+
/**
|
|
73
|
+
* Bookkeeping the retained state may hold across every known frame. Masks are
|
|
74
|
+
* retained as identity plus a reference to the parser's own payload and are
|
|
75
|
+
* traced lazily, so this counts per-mask bookkeeping and box geometry rather
|
|
76
|
+
* than payload or traced-path characters.
|
|
77
|
+
*/
|
|
78
|
+
readonly maxRetainedComplexity?: number;
|
|
79
|
+
}
|
|
80
|
+
export interface SegmentationUpdateOptions {
|
|
81
|
+
readonly reset?: boolean;
|
|
82
|
+
}
|
|
83
|
+
interface RenderOptionsBase {
|
|
84
|
+
readonly source: Rectangle;
|
|
85
|
+
readonly target: Rectangle;
|
|
86
|
+
readonly hiddenIds?: ReadonlySet<string> | readonly string[];
|
|
87
|
+
}
|
|
88
|
+
export interface ImageRenderOptions extends RenderOptionsBase {
|
|
89
|
+
readonly media: 'image';
|
|
90
|
+
}
|
|
91
|
+
export interface VideoRenderOptions extends RenderOptionsBase {
|
|
92
|
+
readonly media: 'video';
|
|
93
|
+
readonly frameIndex: number;
|
|
94
|
+
}
|
|
95
|
+
export type SegmentationRenderOptions = ImageRenderOptions | VideoRenderOptions;
|
|
96
|
+
type SegmentationView = SegmentationResult | SegmentationSnapshot;
|
|
97
|
+
/**
|
|
98
|
+
* The fill and stroke color the renderer assigns to an object identifier.
|
|
99
|
+
* Exposed so legends and inspectors can match the composited overlay exactly.
|
|
100
|
+
*/
|
|
101
|
+
export declare function objectColor(objectId: string): string;
|
|
102
|
+
export declare class SegmentationRenderer {
|
|
103
|
+
#private;
|
|
104
|
+
constructor(options?: SegmentationRendererOptions);
|
|
105
|
+
update(result: SegmentationView, options?: SegmentationUpdateOptions): Promise<void>;
|
|
106
|
+
renderVideoFrame(composition: VideoFrameCompositionContext, options?: VideoFrameCompositionOptions): boolean;
|
|
107
|
+
render(context: SegmentationCanvasContext, options: SegmentationRenderOptions): void;
|
|
108
|
+
clear(): void;
|
|
109
|
+
dispose(): void;
|
|
110
|
+
}
|
|
111
|
+
export {};
|