@eyepop.ai/eyepop-render-2d 0.20.0 → 0.20.1
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 +38 -30
- package/dist/eyepop.render2d.index.d.mts +48 -9
- package/dist/eyepop.render2d.index.d.ts +48 -9
- package/dist/eyepop.render2d.index.js +155 -59
- package/dist/eyepop.render2d.index.js.map +1 -1
- package/dist/eyepop.render2d.index.mjs +155 -59
- package/dist/eyepop.render2d.index.mjs.map +1 -1
- package/dist/eyepop.render2d.min.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -97,69 +97,77 @@ Change this rendering behaviour by passing in rendering rule(s), e.g.:
|
|
|
97
97
|
Render2d.renderer(context,[Render2.renderFace()]).draw(result);
|
|
98
98
|
// ...
|
|
99
99
|
```
|
|
100
|
-
Each rule has a `render` object and a `target` attribute. All prebuild render classes accept a
|
|
101
|
-
JSONPath expression as `target` parameter to select which elements should be rendered from predictions.
|
|
100
|
+
Each rule has a `render` object and a `target` attribute. All prebuild render classes accept a JSONPath expression as `target` parameter to select which elements should be rendered from predictions.
|
|
102
101
|
See [JSONPath expression](https://www.npmjs.com/package/jsonpath)
|
|
103
102
|
|
|
104
|
-
Most prebuild render classes provide a reasonable
|
|
103
|
+
Most prebuild render classes provide a reasonable defaults, as shown below.
|
|
105
104
|
#### Rendering Bounding Boxes and Class Labels
|
|
105
|
+
|
|
106
106
|
```typescript
|
|
107
|
-
Render2d.renderBox({
|
|
108
|
-
|
|
109
|
-
|
|
107
|
+
Render2d.renderBox({
|
|
108
|
+
showClass = true,
|
|
109
|
+
showConfidence = false,
|
|
110
|
+
showTraceId = false,
|
|
111
|
+
showNestedClasses = false,
|
|
112
|
+
target = '$..objects.*'
|
|
113
|
+
})
|
|
110
114
|
```
|
|
111
115
|
#### Render Human Body Poses (2d or 3d)
|
|
112
116
|
```typescript
|
|
113
|
-
Render2d.renderPose({
|
|
114
|
-
|
|
115
|
-
|
|
117
|
+
Render2d.renderPose({
|
|
118
|
+
target: '$..objects[?(@.category=="person")]'
|
|
119
|
+
})
|
|
116
120
|
```
|
|
117
121
|
#### Render Human Hand Details
|
|
118
122
|
```typescript
|
|
119
|
-
Render2d.renderHand({
|
|
120
|
-
|
|
121
|
-
|
|
123
|
+
Render2d.renderHand({
|
|
124
|
+
target: '$..objects[?(@.classLabel=="hand circumference")]'
|
|
125
|
+
})
|
|
122
126
|
```
|
|
123
127
|
#### Render Human Faces
|
|
124
128
|
```typescript
|
|
125
|
-
Render2d.renderFace({
|
|
126
|
-
|
|
127
|
-
|
|
129
|
+
Render2d.renderFace({
|
|
130
|
+
showLabels = false,
|
|
131
|
+
target = '$..objects[?(@.classLabel=="face")]'
|
|
132
|
+
})
|
|
128
133
|
```
|
|
129
134
|
#### Render Segmentation Masks
|
|
130
135
|
```typescript
|
|
131
|
-
Render2d.renderMask({
|
|
132
|
-
|
|
133
|
-
|
|
136
|
+
Render2d.renderMask({
|
|
137
|
+
target: '$..objects[?(@.mask)]'
|
|
138
|
+
})
|
|
134
139
|
```
|
|
135
140
|
#### Render Segmentation Contours
|
|
136
141
|
```typescript
|
|
137
|
-
Render2d.renderContour({
|
|
138
|
-
|
|
139
|
-
|
|
142
|
+
Render2d.renderContour({
|
|
143
|
+
target: '$..objects[?(@.contours)]'
|
|
144
|
+
})
|
|
140
145
|
```
|
|
141
146
|
#### Blur an Object (TODO does black-put instead of blur)
|
|
142
147
|
```typescript
|
|
143
|
-
Render2d.renderBlur({
|
|
148
|
+
Render2d.renderBlur({
|
|
149
|
+
target: '$..objects[?(@.classLabel=="face")]'
|
|
150
|
+
})
|
|
144
151
|
```
|
|
145
152
|
#### Render a Trail of a traced object over time
|
|
146
153
|
```typescript
|
|
147
|
-
Render2d.renderTrail({
|
|
148
|
-
|
|
149
|
-
|
|
154
|
+
Render2d.renderTrail({
|
|
155
|
+
target: '$..objects[?(@.traceId)]',
|
|
156
|
+
trailLengthSeconds:1,
|
|
157
|
+
})
|
|
150
158
|
```
|
|
151
|
-
By default, this traces the mid-point of the object's bounding box. Instead, one can also draw trails of
|
|
152
|
-
sub-objects or key points of the traced object. Use the optional parameter `traceDetails` for this purpose.
|
|
159
|
+
By default, this traces the mid-point of the object's bounding box. Instead, one can also draw trails of sub-objects or key points of the traced object. Use the optional parameter `traceDetails` for this purpose.
|
|
153
160
|
E.g. trail the nose of every traced person:
|
|
154
161
|
```typescript
|
|
155
162
|
Render2d.renderTrail({
|
|
156
|
-
target: '$..objects[?(@.traceId)]',
|
|
157
|
-
trailLengthSeconds:1,
|
|
163
|
+
target: '$..objects[?(@.traceId)]',
|
|
164
|
+
trailLengthSeconds:1,
|
|
158
165
|
traceDetails:'$..keyPoints[?(@.category=="3d-body-points")].points[?(@.classLabel.includes("nose"))]'
|
|
159
166
|
})
|
|
160
167
|
```
|
|
161
168
|
#### Custom render implementation
|
|
162
|
-
To implement custom rendering rules,
|
|
169
|
+
To implement custom rendering rules,
|
|
170
|
+
create a custom class as follows:
|
|
163
171
|
```typescript
|
|
164
172
|
import { PredictedObject, StreamTime } from '@eyepop.ai/eyepop'
|
|
165
173
|
|
|
@@ -15,6 +15,8 @@ declare class Style {
|
|
|
15
15
|
font: string;
|
|
16
16
|
colors: Colors;
|
|
17
17
|
scale: number;
|
|
18
|
+
cornerWidth: number;
|
|
19
|
+
cornerPadding: number;
|
|
18
20
|
private static defaultColors;
|
|
19
21
|
constructor(context: CanvasRenderingContext2D);
|
|
20
22
|
private calculateFont;
|
|
@@ -29,20 +31,57 @@ interface Render extends RenderTarget {
|
|
|
29
31
|
draw(element: any, xOffset: number, yOffset: number, xScale: number, yScale: number, streamTime: StreamTime): void;
|
|
30
32
|
}
|
|
31
33
|
|
|
34
|
+
type RenderBlurOptions = {} & RenderTarget;
|
|
35
|
+
|
|
36
|
+
type RenderBoxOptions = {
|
|
37
|
+
showText: boolean;
|
|
38
|
+
showClass: boolean;
|
|
39
|
+
showNestedClasses: boolean;
|
|
40
|
+
showConfidence: boolean;
|
|
41
|
+
showTraceId: boolean;
|
|
42
|
+
} & RenderTarget;
|
|
43
|
+
|
|
44
|
+
type RenderFaceOptions = {
|
|
45
|
+
showLabels: boolean;
|
|
46
|
+
} & RenderTarget;
|
|
47
|
+
|
|
48
|
+
type RenderHandOptions = {} & RenderTarget;
|
|
49
|
+
|
|
50
|
+
type RenderPoseOptions = {} & RenderTarget;
|
|
51
|
+
|
|
52
|
+
type RenderTrailOptions = {
|
|
53
|
+
trailLengthSeconds: number;
|
|
54
|
+
traceDetails?: string | undefined;
|
|
55
|
+
} & RenderTarget;
|
|
56
|
+
|
|
57
|
+
type RenderMaskOptions = {} & RenderTarget;
|
|
58
|
+
|
|
59
|
+
type RenderContourOptions = {} & RenderTarget;
|
|
60
|
+
|
|
61
|
+
type RenderKeyPointsOptions = {
|
|
62
|
+
showLabels: boolean;
|
|
63
|
+
} & RenderTarget;
|
|
64
|
+
|
|
65
|
+
type RenderTextOptions = {
|
|
66
|
+
showText: boolean;
|
|
67
|
+
fitToBounds: boolean;
|
|
68
|
+
} & RenderTarget;
|
|
69
|
+
|
|
32
70
|
interface Renderer extends RenderTarget {
|
|
33
71
|
draw(p: Prediction): void;
|
|
34
72
|
}
|
|
35
73
|
declare namespace Render2d {
|
|
36
74
|
function renderer(context: CanvasRenderingContext2D, rules?: Render[] | undefined): Renderer;
|
|
37
|
-
function renderBlur(
|
|
38
|
-
function renderBox(
|
|
39
|
-
function renderMask(
|
|
40
|
-
function renderContour(
|
|
41
|
-
function renderFace(
|
|
42
|
-
function renderKeypoints(
|
|
43
|
-
function renderHand(
|
|
44
|
-
function renderPose(
|
|
45
|
-
function
|
|
75
|
+
function renderBlur(options?: Partial<RenderBlurOptions>): Render;
|
|
76
|
+
function renderBox(options?: Partial<RenderBoxOptions>): Render;
|
|
77
|
+
function renderMask(options?: Partial<RenderMaskOptions>): Render;
|
|
78
|
+
function renderContour(options?: Partial<RenderContourOptions>): Render;
|
|
79
|
+
function renderFace(options?: Partial<RenderFaceOptions>): Render;
|
|
80
|
+
function renderKeypoints(options?: Partial<RenderKeyPointsOptions>): Render;
|
|
81
|
+
function renderHand(options?: Partial<RenderHandOptions>): Render;
|
|
82
|
+
function renderPose(options?: Partial<RenderPoseOptions>): Render;
|
|
83
|
+
function renderText(options?: Partial<RenderTextOptions>): Render;
|
|
84
|
+
function renderTrail(options?: Partial<RenderTrailOptions>): Render;
|
|
46
85
|
}
|
|
47
86
|
|
|
48
87
|
export { Render2d, type Renderer, Render2d as default };
|
|
@@ -15,6 +15,8 @@ declare class Style {
|
|
|
15
15
|
font: string;
|
|
16
16
|
colors: Colors;
|
|
17
17
|
scale: number;
|
|
18
|
+
cornerWidth: number;
|
|
19
|
+
cornerPadding: number;
|
|
18
20
|
private static defaultColors;
|
|
19
21
|
constructor(context: CanvasRenderingContext2D);
|
|
20
22
|
private calculateFont;
|
|
@@ -29,20 +31,57 @@ interface Render extends RenderTarget {
|
|
|
29
31
|
draw(element: any, xOffset: number, yOffset: number, xScale: number, yScale: number, streamTime: StreamTime): void;
|
|
30
32
|
}
|
|
31
33
|
|
|
34
|
+
type RenderBlurOptions = {} & RenderTarget;
|
|
35
|
+
|
|
36
|
+
type RenderBoxOptions = {
|
|
37
|
+
showText: boolean;
|
|
38
|
+
showClass: boolean;
|
|
39
|
+
showNestedClasses: boolean;
|
|
40
|
+
showConfidence: boolean;
|
|
41
|
+
showTraceId: boolean;
|
|
42
|
+
} & RenderTarget;
|
|
43
|
+
|
|
44
|
+
type RenderFaceOptions = {
|
|
45
|
+
showLabels: boolean;
|
|
46
|
+
} & RenderTarget;
|
|
47
|
+
|
|
48
|
+
type RenderHandOptions = {} & RenderTarget;
|
|
49
|
+
|
|
50
|
+
type RenderPoseOptions = {} & RenderTarget;
|
|
51
|
+
|
|
52
|
+
type RenderTrailOptions = {
|
|
53
|
+
trailLengthSeconds: number;
|
|
54
|
+
traceDetails?: string | undefined;
|
|
55
|
+
} & RenderTarget;
|
|
56
|
+
|
|
57
|
+
type RenderMaskOptions = {} & RenderTarget;
|
|
58
|
+
|
|
59
|
+
type RenderContourOptions = {} & RenderTarget;
|
|
60
|
+
|
|
61
|
+
type RenderKeyPointsOptions = {
|
|
62
|
+
showLabels: boolean;
|
|
63
|
+
} & RenderTarget;
|
|
64
|
+
|
|
65
|
+
type RenderTextOptions = {
|
|
66
|
+
showText: boolean;
|
|
67
|
+
fitToBounds: boolean;
|
|
68
|
+
} & RenderTarget;
|
|
69
|
+
|
|
32
70
|
interface Renderer extends RenderTarget {
|
|
33
71
|
draw(p: Prediction): void;
|
|
34
72
|
}
|
|
35
73
|
declare namespace Render2d {
|
|
36
74
|
function renderer(context: CanvasRenderingContext2D, rules?: Render[] | undefined): Renderer;
|
|
37
|
-
function renderBlur(
|
|
38
|
-
function renderBox(
|
|
39
|
-
function renderMask(
|
|
40
|
-
function renderContour(
|
|
41
|
-
function renderFace(
|
|
42
|
-
function renderKeypoints(
|
|
43
|
-
function renderHand(
|
|
44
|
-
function renderPose(
|
|
45
|
-
function
|
|
75
|
+
function renderBlur(options?: Partial<RenderBlurOptions>): Render;
|
|
76
|
+
function renderBox(options?: Partial<RenderBoxOptions>): Render;
|
|
77
|
+
function renderMask(options?: Partial<RenderMaskOptions>): Render;
|
|
78
|
+
function renderContour(options?: Partial<RenderContourOptions>): Render;
|
|
79
|
+
function renderFace(options?: Partial<RenderFaceOptions>): Render;
|
|
80
|
+
function renderKeypoints(options?: Partial<RenderKeyPointsOptions>): Render;
|
|
81
|
+
function renderHand(options?: Partial<RenderHandOptions>): Render;
|
|
82
|
+
function renderPose(options?: Partial<RenderPoseOptions>): Render;
|
|
83
|
+
function renderText(options?: Partial<RenderTextOptions>): Render;
|
|
84
|
+
function renderTrail(options?: Partial<RenderTrailOptions>): Render;
|
|
46
85
|
}
|
|
47
86
|
|
|
48
87
|
export { Render2d, type Renderer, Render2d as default };
|
|
@@ -40,6 +40,8 @@ var import_resize_observer = require("@juggle/resize-observer");
|
|
|
40
40
|
var _Style = class _Style {
|
|
41
41
|
constructor(context) {
|
|
42
42
|
this.scale = 1;
|
|
43
|
+
this.cornerWidth = 0.2;
|
|
44
|
+
this.cornerPadding = 0.05;
|
|
43
45
|
this.colors = _Style.defaultColors;
|
|
44
46
|
if ("document" in globalThis && "implementation" in globalThis.document) {
|
|
45
47
|
const resizeObserver = new import_resize_observer.ResizeObserver((entries) => {
|
|
@@ -82,11 +84,10 @@ var DEFAULT_TARGET = "$..objects[?(@.category=='person')]";
|
|
|
82
84
|
var RenderBox = class _RenderBox {
|
|
83
85
|
constructor(options = {}) {
|
|
84
86
|
this.target = DEFAULT_TARGET;
|
|
85
|
-
const { showClass = true,
|
|
87
|
+
const { showClass = true, showConfidence = false, showTraceId = false, showNestedClasses = false, target = "$..objects.*" } = options;
|
|
86
88
|
this.target = target;
|
|
87
89
|
this.showClass = showClass;
|
|
88
90
|
this.showNestedClasses = showNestedClasses;
|
|
89
|
-
this.showText = showText;
|
|
90
91
|
this.showConfidence = showConfidence;
|
|
91
92
|
this.showTraceId = showTraceId;
|
|
92
93
|
}
|
|
@@ -104,15 +105,21 @@ var RenderBox = class _RenderBox {
|
|
|
104
105
|
const y = yOffset + element.y * yScale;
|
|
105
106
|
const w = element.width * xScale;
|
|
106
107
|
const h = element.height * yScale;
|
|
108
|
+
if (element.objects) {
|
|
109
|
+
element.objects.sort((a, b) => {
|
|
110
|
+
if (!a.category || !b.category) return 0;
|
|
111
|
+
return a.category.localeCompare(b.category);
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
const scale = style.scale;
|
|
107
115
|
context.beginPath();
|
|
108
116
|
context.rect(x, y, w, h);
|
|
109
|
-
context.lineWidth =
|
|
117
|
+
context.lineWidth = scale * 2;
|
|
110
118
|
context.strokeStyle = style.colors.opacity_color;
|
|
111
119
|
context.fillStyle = style.colors.opacity_color;
|
|
112
120
|
context.fill();
|
|
113
121
|
context.stroke();
|
|
114
|
-
const
|
|
115
|
-
const desiredPercentage = 0.25;
|
|
122
|
+
const desiredPercentage = style.cornerPadding;
|
|
116
123
|
let canvasDimension = Math.min(context.canvas.width, context.canvas.height);
|
|
117
124
|
let cornerSize = Math.min(w / 4, canvasDimension * desiredPercentage);
|
|
118
125
|
var corners = [
|
|
@@ -131,10 +138,10 @@ var RenderBox = class _RenderBox {
|
|
|
131
138
|
context.lineTo(corner[1].x, corner[1].y);
|
|
132
139
|
context.lineTo(corner[2].x, corner[2].y);
|
|
133
140
|
context.strokeStyle = style.colors.primary_color;
|
|
134
|
-
context.lineWidth =
|
|
141
|
+
context.lineWidth = scale * 2;
|
|
135
142
|
context.stroke();
|
|
136
143
|
});
|
|
137
|
-
const padding = Math.max(Math.min(w / 25, canvasDimension *
|
|
144
|
+
const padding = Math.max(Math.min(w / 25, canvasDimension * style.cornerWidth), scale * 2);
|
|
138
145
|
cornerSize = cornerSize - padding;
|
|
139
146
|
var corners2 = [
|
|
140
147
|
//2nd top left corner
|
|
@@ -164,7 +171,7 @@ var RenderBox = class _RenderBox {
|
|
|
164
171
|
context.lineTo(corner[1].x, corner[1].y);
|
|
165
172
|
context.lineTo(corner[2].x, corner[2].y);
|
|
166
173
|
context.strokeStyle = style.colors.secondary_color;
|
|
167
|
-
context.lineWidth =
|
|
174
|
+
context.lineWidth = scale * 2;
|
|
168
175
|
context.stroke();
|
|
169
176
|
});
|
|
170
177
|
const boundingBoxWidth = element.width * xScale - 3 * padding;
|
|
@@ -175,14 +182,6 @@ var RenderBox = class _RenderBox {
|
|
|
175
182
|
label = _RenderBox.toTitleCase(label);
|
|
176
183
|
yOffset += this.drawLabel(label, context, element, yScale, xScale, yOffset, xOffset, style, boundingBoxWidth, padding, false, fontSize);
|
|
177
184
|
}
|
|
178
|
-
if (this.showText && element.labels) {
|
|
179
|
-
fontSize = this.getMinFontSize(context, element, boundingBoxWidth, style, true);
|
|
180
|
-
for (let i = 0; i < element.labels.length; i++) {
|
|
181
|
-
label = element.labels[i]?.label;
|
|
182
|
-
if (!label) continue;
|
|
183
|
-
yOffset += this.drawLabel(label, context, element, yScale, xScale, yOffset, xOffset, style, boundingBoxWidth, padding, true, fontSize);
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
185
|
if (this.showNestedClasses && element?.classes) {
|
|
187
186
|
for (let i = 0; i < element.classes.length; i++) {
|
|
188
187
|
label = element.classes[i]?.classLabel;
|
|
@@ -192,7 +191,7 @@ var RenderBox = class _RenderBox {
|
|
|
192
191
|
}
|
|
193
192
|
}
|
|
194
193
|
if (this.showTraceId && element.traceId) {
|
|
195
|
-
label = "
|
|
194
|
+
label = "ID: " + element.traceId;
|
|
196
195
|
label = _RenderBox.toTitleCase(label);
|
|
197
196
|
yOffset += this.drawLabel(label, context, element, yScale, xScale, yOffset, xOffset, style, boundingBoxWidth, padding, false, fontSize);
|
|
198
197
|
}
|
|
@@ -239,16 +238,6 @@ var RenderBox = class _RenderBox {
|
|
|
239
238
|
// Gets the largest label from all the labels to be displayed
|
|
240
239
|
getMinFontSize(context, element, width, style, scaleToWidth = false) {
|
|
241
240
|
let largestLabel = "";
|
|
242
|
-
if (this.showText && element.labels) {
|
|
243
|
-
for (let i = 0; i < element.labels.length; i++) {
|
|
244
|
-
const label = element.labels[i].label;
|
|
245
|
-
if (!label) continue;
|
|
246
|
-
const formattedLabel = `${_RenderBox.toTitleCase(label)}`;
|
|
247
|
-
if (formattedLabel.length > largestLabel.length) {
|
|
248
|
-
largestLabel = formattedLabel;
|
|
249
|
-
}
|
|
250
|
-
}
|
|
251
|
-
}
|
|
252
241
|
if (this.showClass && element.classLabel) {
|
|
253
242
|
const label = element.classLabel;
|
|
254
243
|
const formattedLabel = `${_RenderBox.toTitleCase(label)}`;
|
|
@@ -374,8 +363,10 @@ var RenderBlur = class {
|
|
|
374
363
|
var RenderFace = class {
|
|
375
364
|
constructor(options = {}) {
|
|
376
365
|
this.target = DEFAULT_TARGET;
|
|
377
|
-
|
|
366
|
+
this.showLabels = false;
|
|
367
|
+
const { showLabels = false, target = '$..objects[?(@.classLabel=="face")]' } = options;
|
|
378
368
|
this.target = target;
|
|
369
|
+
this.showLabels = showLabels;
|
|
379
370
|
}
|
|
380
371
|
start(context, style) {
|
|
381
372
|
this.context = context;
|
|
@@ -427,12 +418,14 @@ var RenderFace = class {
|
|
|
427
418
|
context.fillRect(x, y, tw.width + padding * 2, 24);
|
|
428
419
|
}
|
|
429
420
|
context.fill();
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
421
|
+
if (this.showLabels) {
|
|
422
|
+
context.fillStyle = style.colors.secondary_color;
|
|
423
|
+
context.fillText(
|
|
424
|
+
label,
|
|
425
|
+
Math.max(0, x) + padding,
|
|
426
|
+
Math.max(0, y)
|
|
427
|
+
);
|
|
428
|
+
}
|
|
436
429
|
context.closePath();
|
|
437
430
|
}
|
|
438
431
|
}
|
|
@@ -501,7 +494,7 @@ var FACE_LANDMARKS_TESSELATION = [[127, 34], [34, 139], [139, 127], [11, 0], [0,
|
|
|
501
494
|
var RenderHand = class {
|
|
502
495
|
constructor(options = {}) {
|
|
503
496
|
this.target = DEFAULT_TARGET;
|
|
504
|
-
const { target =
|
|
497
|
+
const { target = '$..objects[?(@.classLabel=="hand circumference")]' } = options;
|
|
505
498
|
this.target = target;
|
|
506
499
|
}
|
|
507
500
|
start(context, style) {
|
|
@@ -628,7 +621,7 @@ var HAND_CONNECTIONS = [
|
|
|
628
621
|
var RenderPose = class {
|
|
629
622
|
constructor(options = {}) {
|
|
630
623
|
this.target = DEFAULT_TARGET;
|
|
631
|
-
const { target =
|
|
624
|
+
const { target = '$..objects[?(@.category=="person")]' } = options;
|
|
632
625
|
this.target = target;
|
|
633
626
|
}
|
|
634
627
|
start(context, style) {
|
|
@@ -679,7 +672,7 @@ var RenderPose = class {
|
|
|
679
672
|
const x2 = xOffset + point2.x * xScale;
|
|
680
673
|
const y2 = yOffset + point2.y * yScale;
|
|
681
674
|
context.beginPath();
|
|
682
|
-
context.lineWidth = style.scale;
|
|
675
|
+
context.lineWidth = style.scale * 3;
|
|
683
676
|
context.strokeStyle = style.colors.primary_color;
|
|
684
677
|
context.fillStyle = style.colors.primary_color;
|
|
685
678
|
context.moveTo(x1, y1);
|
|
@@ -770,7 +763,7 @@ var TRIM_INTERVAL = 1e3 * 1e3 * 1e3 * 10;
|
|
|
770
763
|
var RenderTrail = class {
|
|
771
764
|
constructor(options = {}) {
|
|
772
765
|
this.target = DEFAULT_TARGET;
|
|
773
|
-
const { target =
|
|
766
|
+
const { target = "$..objects[?(@.traceId)]", trailLengthSeconds = 1, traceDetails } = options;
|
|
774
767
|
this.target = target;
|
|
775
768
|
this.trailLengthNanos = trailLengthSeconds * 1e3 * 1e3 * 1e3;
|
|
776
769
|
this.traceDetails = traceDetails;
|
|
@@ -863,7 +856,7 @@ var RenderTrail = class {
|
|
|
863
856
|
var RenderMask = class {
|
|
864
857
|
constructor(options = {}) {
|
|
865
858
|
this.target = DEFAULT_TARGET;
|
|
866
|
-
const { target =
|
|
859
|
+
const { target = "$..objects[?(@.mask)]" } = options;
|
|
867
860
|
this.target = target;
|
|
868
861
|
}
|
|
869
862
|
start(context, style) {
|
|
@@ -923,7 +916,7 @@ var RenderMask = class {
|
|
|
923
916
|
var RenderContour = class {
|
|
924
917
|
constructor(options = {}) {
|
|
925
918
|
this.target = DEFAULT_TARGET;
|
|
926
|
-
const { target =
|
|
919
|
+
const { target = "$..objects[?(@.contours)]" } = options;
|
|
927
920
|
this.target = target;
|
|
928
921
|
}
|
|
929
922
|
start(context, style) {
|
|
@@ -982,8 +975,10 @@ var RenderContour = class {
|
|
|
982
975
|
var RenderKeyPoints = class {
|
|
983
976
|
constructor(options = {}) {
|
|
984
977
|
this.target = DEFAULT_TARGET;
|
|
985
|
-
|
|
978
|
+
this.showLabels = false;
|
|
979
|
+
const { showLabels = false, target = "$..objects[?(@.keyPoints)]" } = options;
|
|
986
980
|
this.target = target;
|
|
981
|
+
this.showLabels = showLabels;
|
|
987
982
|
}
|
|
988
983
|
start(context, style) {
|
|
989
984
|
this.context = context;
|
|
@@ -1035,6 +1030,7 @@ var RenderKeyPoints = class {
|
|
|
1035
1030
|
context.fill();
|
|
1036
1031
|
context.strokeStyle = style.colors.secondary_color;
|
|
1037
1032
|
context.stroke();
|
|
1033
|
+
if (!this.showLabels) continue;
|
|
1038
1034
|
let label;
|
|
1039
1035
|
if (typeof p.visible == "undefined") {
|
|
1040
1036
|
label = p.classLabel;
|
|
@@ -1053,6 +1049,102 @@ var RenderKeyPoints = class {
|
|
|
1053
1049
|
}
|
|
1054
1050
|
};
|
|
1055
1051
|
|
|
1052
|
+
// render-text.ts
|
|
1053
|
+
var RenderText = class {
|
|
1054
|
+
constructor(options = {}) {
|
|
1055
|
+
this.target = DEFAULT_TARGET;
|
|
1056
|
+
this.fitToBounds = true;
|
|
1057
|
+
const { target = '$..objects[?(@.classLabel=="text")]', fitToBounds = true } = options;
|
|
1058
|
+
this.target = target;
|
|
1059
|
+
this.fitToBounds = fitToBounds;
|
|
1060
|
+
}
|
|
1061
|
+
start(context, style) {
|
|
1062
|
+
this.context = context;
|
|
1063
|
+
this.style = style;
|
|
1064
|
+
}
|
|
1065
|
+
draw(element, xOffset, yOffset, xScale, yScale, streamTime) {
|
|
1066
|
+
const context = this.context;
|
|
1067
|
+
const style = this.style;
|
|
1068
|
+
if (!context || !style) {
|
|
1069
|
+
throw new Error("render() called before start()");
|
|
1070
|
+
}
|
|
1071
|
+
const scale = style.scale;
|
|
1072
|
+
const w = element.width * xScale;
|
|
1073
|
+
let canvasDimension = Math.min(context.canvas.width, context.canvas.height);
|
|
1074
|
+
const padding = Math.max(Math.min(w / 25, canvasDimension * style.cornerWidth), scale * 2);
|
|
1075
|
+
const boundingBoxWidth = element.width * xScale - 3 * padding;
|
|
1076
|
+
if (!element.labels) return;
|
|
1077
|
+
let fontSize = this.getMinFontSize(context, element, boundingBoxWidth, style, true);
|
|
1078
|
+
let label = "";
|
|
1079
|
+
for (let i = 0; i < element.labels.length; i++) {
|
|
1080
|
+
label = element.labels[i]?.label;
|
|
1081
|
+
if (!label) continue;
|
|
1082
|
+
yOffset += this.drawLabel(label, context, element, yScale, xScale, yOffset, xOffset, style, boundingBoxWidth, padding, this.fitToBounds, fontSize);
|
|
1083
|
+
}
|
|
1084
|
+
}
|
|
1085
|
+
// Draw a label on the canvas, scaling the font size to fit the bounding box
|
|
1086
|
+
drawLabel(label, context, element, yScale, xScale, yOffset, xOffset, style, boundingBoxWidth, padding, scaleToBounds = false, fontSize) {
|
|
1087
|
+
context.fillStyle = "#ffffff";
|
|
1088
|
+
context.textAlign = "left";
|
|
1089
|
+
context.textBaseline = "top";
|
|
1090
|
+
context.font = style.font;
|
|
1091
|
+
let textDetails = context.measureText(label);
|
|
1092
|
+
let scaleFactor = boundingBoxWidth / textDetails.width;
|
|
1093
|
+
let fontType = style.font.split(" ")[1];
|
|
1094
|
+
if (fontSize) {
|
|
1095
|
+
context.font = `${fontSize}px ` + fontType;
|
|
1096
|
+
} else {
|
|
1097
|
+
let fontSize2 = parseInt(style.font.split(" ")[0]);
|
|
1098
|
+
if (scaleToBounds) {
|
|
1099
|
+
fontSize2 *= scaleFactor;
|
|
1100
|
+
} else {
|
|
1101
|
+
fontSize2 = Math.min(fontSize2, fontSize2 * scaleFactor);
|
|
1102
|
+
}
|
|
1103
|
+
context.font = `${fontSize2}px ${fontType}`;
|
|
1104
|
+
}
|
|
1105
|
+
textDetails = context.measureText(label);
|
|
1106
|
+
let xPos = element.x * xScale + xOffset + 1.5 * padding;
|
|
1107
|
+
let yPos = element.y * yScale + yOffset + 1.5 * padding;
|
|
1108
|
+
context.fillText(label, xPos, yPos);
|
|
1109
|
+
const boxSize = padding + textDetails.actualBoundingBoxAscent + textDetails.actualBoundingBoxDescent;
|
|
1110
|
+
yPos += boxSize;
|
|
1111
|
+
return padding + textDetails.actualBoundingBoxDescent;
|
|
1112
|
+
}
|
|
1113
|
+
static toTitleCase(str) {
|
|
1114
|
+
if (!str) return "";
|
|
1115
|
+
return str.replace(/\w\S*/g, function(txt) {
|
|
1116
|
+
return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();
|
|
1117
|
+
});
|
|
1118
|
+
}
|
|
1119
|
+
// Gets the largest label from all the labels to be displayed
|
|
1120
|
+
getMinFontSize(context, element, width, style, scaleToWidth = false) {
|
|
1121
|
+
let largestLabel = "";
|
|
1122
|
+
for (let i = 0; i < element.labels.length; i++) {
|
|
1123
|
+
const label = element.labels[i].label;
|
|
1124
|
+
if (!label) continue;
|
|
1125
|
+
if (label.length > largestLabel.length) {
|
|
1126
|
+
largestLabel = label;
|
|
1127
|
+
}
|
|
1128
|
+
}
|
|
1129
|
+
let fontSize = this.getFontSize(largestLabel, context, style, width, scaleToWidth);
|
|
1130
|
+
return fontSize;
|
|
1131
|
+
}
|
|
1132
|
+
getFontSize(label, context, style, boundingBoxWidth, scaleToWidth = false) {
|
|
1133
|
+
context.textAlign = "left";
|
|
1134
|
+
context.textBaseline = "top";
|
|
1135
|
+
context.font = style.font;
|
|
1136
|
+
let textDetails = context.measureText(label);
|
|
1137
|
+
let scaleFactor = boundingBoxWidth / textDetails.width;
|
|
1138
|
+
let fontSize = parseInt(style.font.split(" ")[0]);
|
|
1139
|
+
if (scaleToWidth) {
|
|
1140
|
+
fontSize *= scaleFactor;
|
|
1141
|
+
} else {
|
|
1142
|
+
fontSize = Math.min(fontSize, fontSize * scaleFactor);
|
|
1143
|
+
}
|
|
1144
|
+
return fontSize;
|
|
1145
|
+
}
|
|
1146
|
+
};
|
|
1147
|
+
|
|
1056
1148
|
// index.ts
|
|
1057
1149
|
var Render2d;
|
|
1058
1150
|
((Render2d2) => {
|
|
@@ -1060,40 +1152,44 @@ var Render2d;
|
|
|
1060
1152
|
return new Renderer2d({ context, rules });
|
|
1061
1153
|
}
|
|
1062
1154
|
Render2d2.renderer = renderer;
|
|
1063
|
-
function renderBlur(
|
|
1064
|
-
return new RenderBlur(
|
|
1155
|
+
function renderBlur(options = {}) {
|
|
1156
|
+
return new RenderBlur(options);
|
|
1065
1157
|
}
|
|
1066
1158
|
Render2d2.renderBlur = renderBlur;
|
|
1067
|
-
function renderBox(
|
|
1068
|
-
return new RenderBox(
|
|
1159
|
+
function renderBox(options = {}) {
|
|
1160
|
+
return new RenderBox(options);
|
|
1069
1161
|
}
|
|
1070
1162
|
Render2d2.renderBox = renderBox;
|
|
1071
|
-
function renderMask(
|
|
1072
|
-
return new RenderMask(
|
|
1163
|
+
function renderMask(options = {}) {
|
|
1164
|
+
return new RenderMask(options);
|
|
1073
1165
|
}
|
|
1074
1166
|
Render2d2.renderMask = renderMask;
|
|
1075
|
-
function renderContour(
|
|
1076
|
-
return new RenderContour(
|
|
1167
|
+
function renderContour(options = {}) {
|
|
1168
|
+
return new RenderContour(options);
|
|
1077
1169
|
}
|
|
1078
1170
|
Render2d2.renderContour = renderContour;
|
|
1079
|
-
function renderFace(
|
|
1080
|
-
return new RenderFace(
|
|
1171
|
+
function renderFace(options = {}) {
|
|
1172
|
+
return new RenderFace(options);
|
|
1081
1173
|
}
|
|
1082
1174
|
Render2d2.renderFace = renderFace;
|
|
1083
|
-
function renderKeypoints(
|
|
1084
|
-
return new RenderKeyPoints(
|
|
1175
|
+
function renderKeypoints(options = {}) {
|
|
1176
|
+
return new RenderKeyPoints(options);
|
|
1085
1177
|
}
|
|
1086
1178
|
Render2d2.renderKeypoints = renderKeypoints;
|
|
1087
|
-
function renderHand(
|
|
1088
|
-
return new RenderHand(
|
|
1179
|
+
function renderHand(options = {}) {
|
|
1180
|
+
return new RenderHand(options);
|
|
1089
1181
|
}
|
|
1090
1182
|
Render2d2.renderHand = renderHand;
|
|
1091
|
-
function renderPose(
|
|
1092
|
-
return new RenderPose(
|
|
1183
|
+
function renderPose(options = {}) {
|
|
1184
|
+
return new RenderPose(options);
|
|
1093
1185
|
}
|
|
1094
1186
|
Render2d2.renderPose = renderPose;
|
|
1095
|
-
function
|
|
1096
|
-
return new
|
|
1187
|
+
function renderText(options = {}) {
|
|
1188
|
+
return new RenderText(options);
|
|
1189
|
+
}
|
|
1190
|
+
Render2d2.renderText = renderText;
|
|
1191
|
+
function renderTrail(options = {}) {
|
|
1192
|
+
return new RenderTrail(options);
|
|
1097
1193
|
}
|
|
1098
1194
|
Render2d2.renderTrail = renderTrail;
|
|
1099
1195
|
})(Render2d || (Render2d = {}));
|