@eyepop.ai/eyepop-render-2d 3.17.3 → 3.19.0

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 CHANGED
@@ -141,7 +141,7 @@ Most prebuild render classes provide a reasonable defaults, as shown below.
141
141
  Render2d.renderBox({
142
142
  showClass: true,
143
143
  showConfidence: false,
144
- showTraceId: false,
144
+ showTrackId: false,
145
145
  showNestedClasses: false,
146
146
  target: '$..objects.*',
147
147
  })
@@ -180,6 +180,29 @@ Render2d.renderText({
180
180
  })
181
181
  ```
182
182
 
183
+ #### Render Classification Labels
184
+
185
+ Renders whole-image classification labels. Defaults shown:
186
+
187
+ ```typescript
188
+ Render2d.renderClasses({
189
+ showConfidence: false,
190
+ labelSizePercentage: 0.05,
191
+ target: '$',
192
+ })
193
+ ```
194
+
195
+ #### Render Key Points
196
+
197
+ Renders key points for any object that carries them. Defaults shown:
198
+
199
+ ```typescript
200
+ Render2d.renderKeypoints({
201
+ showLabels: false,
202
+ target: '$..objects[?(@.keyPoints)]',
203
+ })
204
+ ```
205
+
183
206
  #### Render Segmentation Masks
184
207
 
185
208
  ```typescript
@@ -196,7 +219,21 @@ Render2d.renderContour({
196
219
  })
197
220
  ```
198
221
 
199
- #### Blur an Object (TODO does black-put instead of blur)
222
+ #### Render Depth Maps
223
+
224
+ Renders the frame-level depth map produced by depth estimation abilities (e.g. `eyepop.depth.*`)
225
+ as a turbo-colormap heatmap blended over the frame: near = warm (red/yellow), far = cool (blue).
226
+ Sky pixels (+Infinity) leave the frame untouched unless `renderSky` is set.
227
+
228
+ ```typescript
229
+ Render2d.renderDepth({
230
+ target: '$',
231
+ opacity: 0.5, // overlay opacity over the underlying frame
232
+ renderSky: false, // also paint sky pixels
233
+ })
234
+ ```
235
+
236
+ #### Blur an Object
200
237
 
201
238
  ```typescript
202
239
  Render2d.renderBlur({
@@ -204,6 +241,8 @@ Render2d.renderBlur({
204
241
  })
205
242
  ```
206
243
 
244
+ Note: this currently paints a solid fill over the object rather than applying a true blur.
245
+
207
246
  #### Render a Trail of a traced object over time
208
247
 
209
248
  ```typescript
@@ -220,6 +220,29 @@ declare class RenderClasses implements Render {
220
220
  drawLabel(label: string, context: CanvasRenderingContext2D, xOffset: number, yOffset: number, style: Style, drawDisabled: boolean, xPadding: number, yPadding: number, labelWidth: number, labelHeight: number, borderRadius: number): void;
221
221
  }
222
222
 
223
+ type RenderDepthOptions = {
224
+ opacity?: number;
225
+ renderSky?: boolean;
226
+ } & RenderTarget;
227
+ /**
228
+ * Renders a frame-level depth map (Prediction.depth) as a turbo-colormap
229
+ * heatmap blended over the frame: near = warm (red/yellow), far = cool (blue).
230
+ * Sky pixels (+Infinity) leave the frame untouched unless renderSky is set.
231
+ *
232
+ * Uses getImageData/putImageData only, so it works with node-canvas as well
233
+ * as browser and react-native canvases.
234
+ */
235
+ declare class RenderDepth implements Render {
236
+ target: string;
237
+ private context;
238
+ private style;
239
+ private readonly opacity;
240
+ private readonly renderSky;
241
+ constructor(options?: Partial<RenderDepthOptions>);
242
+ start(context: CanvasRenderingContext2D, style: Style): void;
243
+ draw(element: Prediction, xOffset: number, yOffset: number, xScale: number, yScale: number, streamTime: StreamTime, color?: string): void;
244
+ }
245
+
223
246
  type Renderer2dOptions = {
224
247
  context: CanvasRenderingContext2D;
225
248
  rules?: Render[] | Render | undefined;
@@ -244,6 +267,7 @@ declare namespace Render2d {
244
267
  function renderClasses(options?: Partial<RenderClassesOptions>): Render;
245
268
  function renderMask(options?: Partial<RenderMaskOptions>): Render;
246
269
  function renderContour(options?: Partial<RenderContourOptions>): Render;
270
+ function renderDepth(options?: Partial<RenderDepthOptions>): Render;
247
271
  function renderFace(options?: Partial<RenderFaceOptions>): Render;
248
272
  function renderKeypoints(options?: Partial<RenderKeyPointsOptions>): Render;
249
273
  function renderHand(options?: Partial<RenderHandOptions>): Render;
@@ -252,4 +276,4 @@ declare namespace Render2d {
252
276
  function renderTrail(options?: Partial<RenderTrailOptions>): Render;
253
277
  }
254
278
 
255
- export { BoxType, type ClassificationProperties, DEFAULT_TARGET, type Render, Render2d, RenderBlur, type RenderBlurOptions, RenderBox, type RenderBoxOptions, RenderClasses, type RenderClassesOptions, RenderContour, type RenderContourOptions, RenderFace, type RenderFaceOptions, RenderHand, type RenderHandOptions, RenderKeyPoints, type RenderKeyPointsOptions, RenderMask, type RenderMaskOptions, RenderPose, type RenderPoseOptions, type RenderTarget, RenderText, type RenderTextOptions, RenderTrail, type RenderTrailOptions, type Renderer, Renderer2d, type Renderer2dOptions, Render2d as default };
279
+ export { BoxType, type ClassificationProperties, DEFAULT_TARGET, type Render, Render2d, RenderBlur, type RenderBlurOptions, RenderBox, type RenderBoxOptions, RenderClasses, type RenderClassesOptions, RenderContour, type RenderContourOptions, RenderDepth, type RenderDepthOptions, RenderFace, type RenderFaceOptions, RenderHand, type RenderHandOptions, RenderKeyPoints, type RenderKeyPointsOptions, RenderMask, type RenderMaskOptions, RenderPose, type RenderPoseOptions, type RenderTarget, RenderText, type RenderTextOptions, RenderTrail, type RenderTrailOptions, type Renderer, Renderer2d, type Renderer2dOptions, Render2d as default };
@@ -220,6 +220,29 @@ declare class RenderClasses implements Render {
220
220
  drawLabel(label: string, context: CanvasRenderingContext2D, xOffset: number, yOffset: number, style: Style, drawDisabled: boolean, xPadding: number, yPadding: number, labelWidth: number, labelHeight: number, borderRadius: number): void;
221
221
  }
222
222
 
223
+ type RenderDepthOptions = {
224
+ opacity?: number;
225
+ renderSky?: boolean;
226
+ } & RenderTarget;
227
+ /**
228
+ * Renders a frame-level depth map (Prediction.depth) as a turbo-colormap
229
+ * heatmap blended over the frame: near = warm (red/yellow), far = cool (blue).
230
+ * Sky pixels (+Infinity) leave the frame untouched unless renderSky is set.
231
+ *
232
+ * Uses getImageData/putImageData only, so it works with node-canvas as well
233
+ * as browser and react-native canvases.
234
+ */
235
+ declare class RenderDepth implements Render {
236
+ target: string;
237
+ private context;
238
+ private style;
239
+ private readonly opacity;
240
+ private readonly renderSky;
241
+ constructor(options?: Partial<RenderDepthOptions>);
242
+ start(context: CanvasRenderingContext2D, style: Style): void;
243
+ draw(element: Prediction, xOffset: number, yOffset: number, xScale: number, yScale: number, streamTime: StreamTime, color?: string): void;
244
+ }
245
+
223
246
  type Renderer2dOptions = {
224
247
  context: CanvasRenderingContext2D;
225
248
  rules?: Render[] | Render | undefined;
@@ -244,6 +267,7 @@ declare namespace Render2d {
244
267
  function renderClasses(options?: Partial<RenderClassesOptions>): Render;
245
268
  function renderMask(options?: Partial<RenderMaskOptions>): Render;
246
269
  function renderContour(options?: Partial<RenderContourOptions>): Render;
270
+ function renderDepth(options?: Partial<RenderDepthOptions>): Render;
247
271
  function renderFace(options?: Partial<RenderFaceOptions>): Render;
248
272
  function renderKeypoints(options?: Partial<RenderKeyPointsOptions>): Render;
249
273
  function renderHand(options?: Partial<RenderHandOptions>): Render;
@@ -252,4 +276,4 @@ declare namespace Render2d {
252
276
  function renderTrail(options?: Partial<RenderTrailOptions>): Render;
253
277
  }
254
278
 
255
- export { BoxType, type ClassificationProperties, DEFAULT_TARGET, type Render, Render2d, RenderBlur, type RenderBlurOptions, RenderBox, type RenderBoxOptions, RenderClasses, type RenderClassesOptions, RenderContour, type RenderContourOptions, RenderFace, type RenderFaceOptions, RenderHand, type RenderHandOptions, RenderKeyPoints, type RenderKeyPointsOptions, RenderMask, type RenderMaskOptions, RenderPose, type RenderPoseOptions, type RenderTarget, RenderText, type RenderTextOptions, RenderTrail, type RenderTrailOptions, type Renderer, Renderer2d, type Renderer2dOptions, Render2d as default };
279
+ export { BoxType, type ClassificationProperties, DEFAULT_TARGET, type Render, Render2d, RenderBlur, type RenderBlurOptions, RenderBox, type RenderBoxOptions, RenderClasses, type RenderClassesOptions, RenderContour, type RenderContourOptions, RenderDepth, type RenderDepthOptions, RenderFace, type RenderFaceOptions, RenderHand, type RenderHandOptions, RenderKeyPoints, type RenderKeyPointsOptions, RenderMask, type RenderMaskOptions, RenderPose, type RenderPoseOptions, type RenderTarget, RenderText, type RenderTextOptions, RenderTrail, type RenderTrailOptions, type Renderer, Renderer2d, type Renderer2dOptions, Render2d as default };
@@ -37,6 +37,7 @@ __export(index_exports, {
37
37
  RenderBox: () => RenderBox,
38
38
  RenderClasses: () => RenderClasses,
39
39
  RenderContour: () => RenderContour,
40
+ RenderDepth: () => RenderDepth,
40
41
  RenderFace: () => RenderFace,
41
42
  RenderHand: () => RenderHand,
42
43
  RenderKeyPoints: () => RenderKeyPoints,
@@ -4201,6 +4202,121 @@ var RenderClasses = class {
4201
4202
  }
4202
4203
  };
4203
4204
 
4205
+ // render-depth.ts
4206
+ var TURBO_ANCHORS = [
4207
+ [48, 18, 59],
4208
+ [62, 86, 196],
4209
+ [33, 145, 237],
4210
+ [26, 192, 181],
4211
+ [94, 223, 105],
4212
+ [181, 229, 54],
4213
+ [243, 192, 52],
4214
+ [246, 117, 26],
4215
+ [122, 4, 3]
4216
+ ];
4217
+ var SKY_COLOR = [48, 18, 59];
4218
+ var isLittleEndianPlatform = new Uint8Array(new Uint16Array([1]).buffer)[0] === 1;
4219
+ function decodeDepthValues(base64, width, height) {
4220
+ if (!Number.isSafeInteger(width) || width <= 0 || !Number.isSafeInteger(height) || height <= 0 || !Number.isSafeInteger(width * height * 4)) {
4221
+ throw new Error(`invalid depth dimensions: ${width}x${height}`);
4222
+ }
4223
+ const count = width * height;
4224
+ const buffer = Buffer.from(base64, "base64");
4225
+ if (buffer.byteLength !== count * 4) {
4226
+ throw new Error(`depth values hold ${buffer.byteLength} bytes, expected ${count * 4} float32 bytes`);
4227
+ }
4228
+ if (isLittleEndianPlatform) {
4229
+ const aligned = new Uint8Array(buffer);
4230
+ return new Float32Array(aligned.buffer, 0, count);
4231
+ }
4232
+ const view = new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength);
4233
+ const values = new Float32Array(count);
4234
+ for (let i = 0; i < count; i++) {
4235
+ values[i] = view.getFloat32(i * 4, true);
4236
+ }
4237
+ return values;
4238
+ }
4239
+ function turboColor(position) {
4240
+ const scaled = Math.min(Math.max(position, 0), 1) * (TURBO_ANCHORS.length - 1);
4241
+ const lower = Math.floor(scaled);
4242
+ const upper = Math.min(lower + 1, TURBO_ANCHORS.length - 1);
4243
+ const fraction = scaled - lower;
4244
+ return [
4245
+ TURBO_ANCHORS[lower][0] * (1 - fraction) + TURBO_ANCHORS[upper][0] * fraction,
4246
+ TURBO_ANCHORS[lower][1] * (1 - fraction) + TURBO_ANCHORS[upper][1] * fraction,
4247
+ TURBO_ANCHORS[lower][2] * (1 - fraction) + TURBO_ANCHORS[upper][2] * fraction
4248
+ ];
4249
+ }
4250
+ var RenderDepth = class {
4251
+ constructor(options = {}) {
4252
+ this.target = "$";
4253
+ const { target = "$", opacity = 0.5, renderSky = false } = options;
4254
+ this.target = target;
4255
+ this.opacity = Math.min(Math.max(opacity, 0), 1);
4256
+ this.renderSky = renderSky;
4257
+ }
4258
+ start(context, style) {
4259
+ this.context = context;
4260
+ this.style = style;
4261
+ }
4262
+ draw(element, xOffset, yOffset, xScale, yScale, streamTime, color) {
4263
+ const context = this.context;
4264
+ if (!context || !this.style) {
4265
+ throw new Error("render() called before start()");
4266
+ }
4267
+ if (!element.depth) {
4268
+ return;
4269
+ }
4270
+ const depthWidth = element.depth.width;
4271
+ const depthHeight = element.depth.height;
4272
+ const values = decodeDepthValues(element.depth.values, depthWidth, depthHeight);
4273
+ const destWidth = Math.round(element.source_width * xScale);
4274
+ const destHeight = Math.round(element.source_height * yScale);
4275
+ if (destWidth <= 0 || destHeight <= 0) {
4276
+ return;
4277
+ }
4278
+ let finiteMin = Number.POSITIVE_INFINITY;
4279
+ let finiteMax = Number.NEGATIVE_INFINITY;
4280
+ for (let i = 0; i < values.length; i++) {
4281
+ const value = values[i];
4282
+ if (Number.isFinite(value)) {
4283
+ if (value < finiteMin) finiteMin = value;
4284
+ if (value > finiteMax) finiteMax = value;
4285
+ }
4286
+ }
4287
+ const span = finiteMax > finiteMin ? finiteMax - finiteMin : 1;
4288
+ const dest = context.getImageData(xOffset, yOffset, destWidth, destHeight);
4289
+ const pixels = dest.data;
4290
+ for (let y = 0; y < destHeight; y++) {
4291
+ const mapY = Math.min(Math.floor(y * depthHeight / destHeight), depthHeight - 1);
4292
+ const mapRow = mapY * depthWidth;
4293
+ for (let x = 0; x < destWidth; x++) {
4294
+ const mapX = Math.min(Math.floor(x * depthWidth / destWidth), depthWidth - 1);
4295
+ const value = values[mapRow + mapX];
4296
+ let heat;
4297
+ if (Number.isFinite(value)) {
4298
+ const normalized = Number.isFinite(finiteMin) ? (value - finiteMin) / span : 0;
4299
+ heat = turboColor(1 - normalized);
4300
+ } else if (this.renderSky) {
4301
+ heat = SKY_COLOR;
4302
+ } else {
4303
+ continue;
4304
+ }
4305
+ const index = (y * destWidth + x) * 4;
4306
+ const destinationAlpha = pixels[index + 3] / 255 * (1 - this.opacity);
4307
+ const outAlpha = this.opacity + destinationAlpha;
4308
+ if (outAlpha > 0) {
4309
+ pixels[index] = Math.round((heat[0] * this.opacity + pixels[index] * destinationAlpha) / outAlpha);
4310
+ pixels[index + 1] = Math.round((heat[1] * this.opacity + pixels[index + 1] * destinationAlpha) / outAlpha);
4311
+ pixels[index + 2] = Math.round((heat[2] * this.opacity + pixels[index + 2] * destinationAlpha) / outAlpha);
4312
+ }
4313
+ pixels[index + 3] = Math.round(outAlpha * 255);
4314
+ }
4315
+ }
4316
+ context.putImageData(dest, xOffset, yOffset);
4317
+ }
4318
+ };
4319
+
4204
4320
  // index.ts
4205
4321
  var Render2d;
4206
4322
  ((Render2d2) => {
@@ -4228,6 +4344,10 @@ var Render2d;
4228
4344
  return new RenderContour(options);
4229
4345
  }
4230
4346
  Render2d2.renderContour = renderContour;
4347
+ function renderDepth(options = {}) {
4348
+ return new RenderDepth(options);
4349
+ }
4350
+ Render2d2.renderDepth = renderDepth;
4231
4351
  function renderFace(options = {}) {
4232
4352
  return new RenderFace(options);
4233
4353
  }
@@ -4263,6 +4383,7 @@ var index_default = Render2d;
4263
4383
  RenderBox,
4264
4384
  RenderClasses,
4265
4385
  RenderContour,
4386
+ RenderDepth,
4266
4387
  RenderFace,
4267
4388
  RenderHand,
4268
4389
  RenderKeyPoints,