@camstack/addon-post-analysis 1.2.210 → 1.2.211
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/dist/pipeline-analytics/index.js +119 -25
- package/dist/pipeline-analytics/index.mjs +119 -25
- package/package.json +1 -1
|
@@ -34569,6 +34569,37 @@ var TWO_WHEELERS = new Set([
|
|
|
34569
34569
|
function intersection(a, b) {
|
|
34570
34570
|
return Math.max(0, Math.min(a.x + a.w, b.x + b.w) - Math.max(a.x, b.x)) * Math.max(0, Math.min(a.y + a.h, b.y + b.h) - Math.max(a.y, b.y));
|
|
34571
34571
|
}
|
|
34572
|
+
/**
|
|
34573
|
+
* The FOLDED subject's box: the union of the rider and the machine.
|
|
34574
|
+
*
|
|
34575
|
+
* The fold's whole claim is that the two halves are ONE subject. Until
|
|
34576
|
+
* 2026-09-08 the box that survived the fold was the MACHINE's alone, so every
|
|
34577
|
+
* consumer that cuts pixels from `TrackedDetectionOut.bbox` — the best-shot
|
|
34578
|
+
* thumbnail, `wideCentralSquareLayout`'s central square, the close-time
|
|
34579
|
+
* keyFrame→thumbnail derive — framed a motorcycle with its rider's head cut
|
|
34580
|
+
* off. Operator, device 617, tracks `7f50622b` and `9cbc4791`, three minutes
|
|
34581
|
+
* apart: "motocicli e veicoli a due ruote devono includere il conducente nel
|
|
34582
|
+
* keyframe" (D407).
|
|
34583
|
+
*
|
|
34584
|
+
* This is the ONE place the folded subject's rectangle is formed, and it is
|
|
34585
|
+
* formed BEFORE the tracker — so no crop path derives a second rectangle
|
|
34586
|
+
* (D52 stays intact: `deriveDetailCropRect` is still the only detail-crop
|
|
34587
|
+
* derivation, and it now receives a subject box that already holds the rider).
|
|
34588
|
+
* Pure geometry: a strict union, never a pad — the fold widens the subject, it
|
|
34589
|
+
* never moves it.
|
|
34590
|
+
*/
|
|
34591
|
+
function riderSubjectBox(person, vehicle) {
|
|
34592
|
+
const x = Math.min(person.x, vehicle.x);
|
|
34593
|
+
const y = Math.min(person.y, vehicle.y);
|
|
34594
|
+
const right = Math.max(person.x + person.w, vehicle.x + vehicle.w);
|
|
34595
|
+
const bottom = Math.max(person.y + person.h, vehicle.y + vehicle.h);
|
|
34596
|
+
return {
|
|
34597
|
+
x,
|
|
34598
|
+
y,
|
|
34599
|
+
w: right - x,
|
|
34600
|
+
h: bottom - y
|
|
34601
|
+
};
|
|
34602
|
+
}
|
|
34572
34603
|
/** True when `vehicle` is a two-wheeler that `person` is riding. */
|
|
34573
34604
|
function isRiderPair(person, vehicle) {
|
|
34574
34605
|
if (person.macroClass !== "person") return false;
|
|
@@ -36335,17 +36366,64 @@ var FrameProcessor = class {
|
|
|
36335
36366
|
const foldByVehicleBbox = /* @__PURE__ */ new Map();
|
|
36336
36367
|
if (riderPairs.length > 0) {
|
|
36337
36368
|
const riderIdx = new Set(riderPairs.map((p) => Number(p.personId)));
|
|
36369
|
+
/**
|
|
36370
|
+
* Move every bbox-OBJECT-keyed side table from the machine's box to the
|
|
36371
|
+
* folded subject's box (D407).
|
|
36372
|
+
*
|
|
36373
|
+
* This file carries frame-local facts across the tracker by bbox-object
|
|
36374
|
+
* REFERENCE (`labelsByBbox`, `embeddingByBbox`, `maskByBbox`, …); the
|
|
36375
|
+
* tracker then assigns `track.bbox = det.bbox`, and the emit block below
|
|
36376
|
+
* reads every one of those maps with `td.bbox`. Widening the subject
|
|
36377
|
+
* therefore means the widened box must inherit the machine's entries —
|
|
36378
|
+
* otherwise a folded rider silently loses its vehicle-classifier label
|
|
36379
|
+
* ("Motorcycle"), its mask, its plate read and its source id. One place,
|
|
36380
|
+
* exhaustive, next to the maps it moves.
|
|
36381
|
+
*/
|
|
36382
|
+
const adoptSubjectBox = (from, to) => {
|
|
36383
|
+
const labels = labelsByBbox.get(from);
|
|
36384
|
+
if (labels !== void 0) labelsByBbox.set(to, labels);
|
|
36385
|
+
const tier = originalClassTierByBbox.get(from);
|
|
36386
|
+
if (tier !== void 0) originalClassTierByBbox.set(to, tier);
|
|
36387
|
+
const embedding = embeddingByBbox.get(from);
|
|
36388
|
+
if (embedding !== void 0) embeddingByBbox.set(to, embedding);
|
|
36389
|
+
const mask = maskByBbox.get(from);
|
|
36390
|
+
if (mask !== void 0) maskByBbox.set(to, mask);
|
|
36391
|
+
const plate = plateByBbox.get(from);
|
|
36392
|
+
if (plate !== void 0) plateByBbox.set(to, plate);
|
|
36393
|
+
const faceBbox = faceBboxByBbox.get(from);
|
|
36394
|
+
if (faceBbox !== void 0) faceBboxByBbox.set(to, faceBbox);
|
|
36395
|
+
const faceSize = nativeFaceSizeByBbox.get(from);
|
|
36396
|
+
if (faceSize !== void 0) nativeFaceSizeByBbox.set(to, faceSize);
|
|
36397
|
+
const alignedCrop = faceAlignedCropByBbox.get(from);
|
|
36398
|
+
if (alignedCrop !== void 0) faceAlignedCropByBbox.set(to, alignedCrop);
|
|
36399
|
+
const sourceId = sourceIdByBbox.get(from);
|
|
36400
|
+
if (sourceId !== void 0) {
|
|
36401
|
+
sourceIdByBbox.set(to, sourceId);
|
|
36402
|
+
firstLevelBboxById.set(sourceId, to);
|
|
36403
|
+
}
|
|
36404
|
+
};
|
|
36405
|
+
/** Folded vehicles, by their index in `filteredDetections`. */
|
|
36406
|
+
const foldedVehicles = /* @__PURE__ */ new Map();
|
|
36338
36407
|
for (const p of riderPairs) {
|
|
36339
|
-
const
|
|
36340
|
-
|
|
36341
|
-
|
|
36408
|
+
const vehicleIdx = Number(p.vehicleId);
|
|
36409
|
+
const vehicle = filteredDetections[vehicleIdx];
|
|
36410
|
+
const person = filteredDetections[Number(p.personId)];
|
|
36411
|
+
if (vehicle === void 0 || person === void 0) continue;
|
|
36412
|
+
const subjectBox = riderSubjectBox(person.bbox, vehicle.bbox);
|
|
36413
|
+
adoptSubjectBox(vehicle.bbox, subjectBox);
|
|
36414
|
+
const folded = {
|
|
36415
|
+
...vehicle,
|
|
36416
|
+
bbox: subjectBox
|
|
36417
|
+
};
|
|
36418
|
+
foldedVehicles.set(vehicleIdx, folded);
|
|
36419
|
+
foldByVehicleBbox.set(subjectBox, {
|
|
36342
36420
|
overlap: p.overlap,
|
|
36343
|
-
personScore:
|
|
36421
|
+
personScore: person.score,
|
|
36344
36422
|
vehicleScore: vehicle.score,
|
|
36345
36423
|
vehicleClass: vehicle.originalClass ?? "two-wheeler"
|
|
36346
36424
|
});
|
|
36347
36425
|
}
|
|
36348
|
-
filteredDetections = filteredDetections.filter((_, i) => !riderIdx.has(i));
|
|
36426
|
+
filteredDetections = filteredDetections.map((d, i) => foldedVehicles.get(i) ?? d).filter((_, i) => !riderIdx.has(i));
|
|
36349
36427
|
}
|
|
36350
36428
|
const gate = this.stationaryGate ? this.stationaryGate.filter({
|
|
36351
36429
|
detections: filteredDetections,
|
|
@@ -49068,10 +49146,9 @@ var FaceRecognizer = class {
|
|
|
49068
49146
|
margin: settings.margin,
|
|
49069
49147
|
minIdentitySamples: settings.minIdentitySamples
|
|
49070
49148
|
}) : /* @__PURE__ */ new Map();
|
|
49071
|
-
if (this.deps.
|
|
49149
|
+
if (this.deps.onSemanticFace !== void 0) for (const c of matchCandidates) {
|
|
49072
49150
|
const match = matches.get(c.trackId);
|
|
49073
|
-
|
|
49074
|
-
this.deps.onSemanticMatch({
|
|
49151
|
+
this.deps.onSemanticFace({
|
|
49075
49152
|
deviceId: input.deviceId,
|
|
49076
49153
|
trackId: c.trackId,
|
|
49077
49154
|
timestamp: input.timestamp,
|
|
@@ -49079,8 +49156,10 @@ var FaceRecognizer = class {
|
|
|
49079
49156
|
frameHeight: input.frameHeight,
|
|
49080
49157
|
bbox: c.bbox,
|
|
49081
49158
|
confidence: c.confidence,
|
|
49082
|
-
|
|
49083
|
-
|
|
49159
|
+
...match !== void 0 ? {
|
|
49160
|
+
matchScore: match.score,
|
|
49161
|
+
identityId: match.identityId
|
|
49162
|
+
} : {},
|
|
49084
49163
|
...input.frameHandle !== void 0 ? { frameHandle: input.frameHandle } : {}
|
|
49085
49164
|
});
|
|
49086
49165
|
}
|
|
@@ -53427,6 +53506,19 @@ var DeferredBirthRegistry = class {
|
|
|
53427
53506
|
}
|
|
53428
53507
|
};
|
|
53429
53508
|
//#endregion
|
|
53509
|
+
//#region src/pipeline-analytics/pipeline/detail-semantic-gate.ts
|
|
53510
|
+
/** The detail `className` whose result IS the recognition. */
|
|
53511
|
+
var PLATE_CLASS = "plate";
|
|
53512
|
+
/**
|
|
53513
|
+
* The moment `className`'s detail result earns the semantic tier.
|
|
53514
|
+
*
|
|
53515
|
+
* `recognition` — promote as soon as the result exists (the plate read).
|
|
53516
|
+
* `label-write` — promote only once the track ACCEPTED the label.
|
|
53517
|
+
*/
|
|
53518
|
+
function detailSemanticTrigger(className) {
|
|
53519
|
+
return className === PLATE_CLASS ? "recognition" : "label-write";
|
|
53520
|
+
}
|
|
53521
|
+
//#endregion
|
|
53430
53522
|
//#region src/pipeline-analytics/pipeline/dropout-skip.ts
|
|
53431
53523
|
function shouldSkipDropoutFrame(activeTrackCount, detectionCount, consecutiveSkips, cfg) {
|
|
53432
53524
|
if (!cfg.enabled) return false;
|
|
@@ -71126,18 +71218,18 @@ var PipelineAnalyticsAddon = class PipelineAnalyticsAddon extends require_dist.B
|
|
|
71126
71218
|
},
|
|
71127
71219
|
getKeyFrameMediaKey: (trackId) => this.residents.keyFrameKey(trackId),
|
|
71128
71220
|
emitFaceGalleryChanged: (payload) => this.emitFaceGalleryChanged(payload),
|
|
71129
|
-
|
|
71130
|
-
deviceId:
|
|
71131
|
-
trackId:
|
|
71132
|
-
timestamp:
|
|
71133
|
-
bbox:
|
|
71134
|
-
frameWidth:
|
|
71135
|
-
frameHeight:
|
|
71136
|
-
kind: "face",
|
|
71137
|
-
score:
|
|
71138
|
-
confidence:
|
|
71139
|
-
...
|
|
71140
|
-
}),
|
|
71221
|
+
onSemanticFace: (face) => this.promoteSemanticRecognition({
|
|
71222
|
+
deviceId: face.deviceId,
|
|
71223
|
+
trackId: face.trackId,
|
|
71224
|
+
timestamp: face.timestamp,
|
|
71225
|
+
bbox: face.bbox,
|
|
71226
|
+
frameWidth: face.frameWidth,
|
|
71227
|
+
frameHeight: face.frameHeight,
|
|
71228
|
+
kind: face.identityId !== void 0 ? "face" : "face-visible",
|
|
71229
|
+
score: face.matchScore ?? face.confidence,
|
|
71230
|
+
confidence: face.confidence,
|
|
71231
|
+
...face.frameHandle !== void 0 ? { frameHandle: face.frameHandle } : {}
|
|
71232
|
+
}, face.identityId !== void 0 ? "identified" : "evidence"),
|
|
71141
71233
|
onLiveHierarchy: (input) => this.requestTrackHierarchy(input),
|
|
71142
71234
|
logger: logger.child("FaceRecognizer")
|
|
71143
71235
|
});
|
|
@@ -74153,10 +74245,12 @@ var PipelineAnalyticsAddon = class PipelineAnalyticsAddon extends require_dist.B
|
|
|
74153
74245
|
} } : {}
|
|
74154
74246
|
});
|
|
74155
74247
|
}
|
|
74248
|
+
if (detailSemanticTrigger(d.className) === "recognition") this.promoteSemanticRecognition(semanticFrameForDetailAttribution(deviceId, trackId, d, frame), "identified");
|
|
74156
74249
|
}
|
|
74157
74250
|
const resolved = d.className === "plate" ? this.plateRecognizer?.resolveLabelWithVehicle(d.label, d.score) ?? null : { text: d.label };
|
|
74158
74251
|
if (resolved !== null && resolved.text !== void 0) {
|
|
74159
|
-
|
|
74252
|
+
const applied = await this.applyTrackEnrichmentLabel(deviceId, trackId, resolved.text, d, frame.timestamp, resolved.vehicleId);
|
|
74253
|
+
if (detailSemanticTrigger(d.className) === "label-write" && applied.trackWritten) this.promoteSemanticRecognition(semanticFrameForDetailAttribution(deviceId, trackId, d, frame), "identified");
|
|
74160
74254
|
}
|
|
74161
74255
|
} else if (d.className === "plate") this.failureReport.notePlateRead(deviceId, d.bbox === void 0 ? REASON_NO_BBOX : REASON_EMPTY_READ);
|
|
74162
74256
|
} catch (err) {
|
|
@@ -74597,8 +74691,8 @@ var PipelineAnalyticsAddon = class PipelineAnalyticsAddon extends require_dist.B
|
|
|
74597
74691
|
* when it wins and the frame's pixels are still reachable. Callers: the
|
|
74598
74692
|
* FaceRecognizer's per-frame auto-match, and `routeDetailResults`' plate /
|
|
74599
74693
|
* fine-classification attribution. */
|
|
74600
|
-
promoteSemanticRecognition(input) {
|
|
74601
|
-
this.recognizedTrackIds.add(input.trackId);
|
|
74694
|
+
promoteSemanticRecognition(input, origin) {
|
|
74695
|
+
if (origin === "identified") this.recognizedTrackIds.add(input.trackId);
|
|
74602
74696
|
const ctx = this.ctxIfReady;
|
|
74603
74697
|
if (ctx === null) return;
|
|
74604
74698
|
promoteSemanticBestFrame({
|
|
@@ -34544,6 +34544,37 @@ var TWO_WHEELERS = new Set([
|
|
|
34544
34544
|
function intersection(a, b) {
|
|
34545
34545
|
return Math.max(0, Math.min(a.x + a.w, b.x + b.w) - Math.max(a.x, b.x)) * Math.max(0, Math.min(a.y + a.h, b.y + b.h) - Math.max(a.y, b.y));
|
|
34546
34546
|
}
|
|
34547
|
+
/**
|
|
34548
|
+
* The FOLDED subject's box: the union of the rider and the machine.
|
|
34549
|
+
*
|
|
34550
|
+
* The fold's whole claim is that the two halves are ONE subject. Until
|
|
34551
|
+
* 2026-09-08 the box that survived the fold was the MACHINE's alone, so every
|
|
34552
|
+
* consumer that cuts pixels from `TrackedDetectionOut.bbox` — the best-shot
|
|
34553
|
+
* thumbnail, `wideCentralSquareLayout`'s central square, the close-time
|
|
34554
|
+
* keyFrame→thumbnail derive — framed a motorcycle with its rider's head cut
|
|
34555
|
+
* off. Operator, device 617, tracks `7f50622b` and `9cbc4791`, three minutes
|
|
34556
|
+
* apart: "motocicli e veicoli a due ruote devono includere il conducente nel
|
|
34557
|
+
* keyframe" (D407).
|
|
34558
|
+
*
|
|
34559
|
+
* This is the ONE place the folded subject's rectangle is formed, and it is
|
|
34560
|
+
* formed BEFORE the tracker — so no crop path derives a second rectangle
|
|
34561
|
+
* (D52 stays intact: `deriveDetailCropRect` is still the only detail-crop
|
|
34562
|
+
* derivation, and it now receives a subject box that already holds the rider).
|
|
34563
|
+
* Pure geometry: a strict union, never a pad — the fold widens the subject, it
|
|
34564
|
+
* never moves it.
|
|
34565
|
+
*/
|
|
34566
|
+
function riderSubjectBox(person, vehicle) {
|
|
34567
|
+
const x = Math.min(person.x, vehicle.x);
|
|
34568
|
+
const y = Math.min(person.y, vehicle.y);
|
|
34569
|
+
const right = Math.max(person.x + person.w, vehicle.x + vehicle.w);
|
|
34570
|
+
const bottom = Math.max(person.y + person.h, vehicle.y + vehicle.h);
|
|
34571
|
+
return {
|
|
34572
|
+
x,
|
|
34573
|
+
y,
|
|
34574
|
+
w: right - x,
|
|
34575
|
+
h: bottom - y
|
|
34576
|
+
};
|
|
34577
|
+
}
|
|
34547
34578
|
/** True when `vehicle` is a two-wheeler that `person` is riding. */
|
|
34548
34579
|
function isRiderPair(person, vehicle) {
|
|
34549
34580
|
if (person.macroClass !== "person") return false;
|
|
@@ -36310,17 +36341,64 @@ var FrameProcessor = class {
|
|
|
36310
36341
|
const foldByVehicleBbox = /* @__PURE__ */ new Map();
|
|
36311
36342
|
if (riderPairs.length > 0) {
|
|
36312
36343
|
const riderIdx = new Set(riderPairs.map((p) => Number(p.personId)));
|
|
36344
|
+
/**
|
|
36345
|
+
* Move every bbox-OBJECT-keyed side table from the machine's box to the
|
|
36346
|
+
* folded subject's box (D407).
|
|
36347
|
+
*
|
|
36348
|
+
* This file carries frame-local facts across the tracker by bbox-object
|
|
36349
|
+
* REFERENCE (`labelsByBbox`, `embeddingByBbox`, `maskByBbox`, …); the
|
|
36350
|
+
* tracker then assigns `track.bbox = det.bbox`, and the emit block below
|
|
36351
|
+
* reads every one of those maps with `td.bbox`. Widening the subject
|
|
36352
|
+
* therefore means the widened box must inherit the machine's entries —
|
|
36353
|
+
* otherwise a folded rider silently loses its vehicle-classifier label
|
|
36354
|
+
* ("Motorcycle"), its mask, its plate read and its source id. One place,
|
|
36355
|
+
* exhaustive, next to the maps it moves.
|
|
36356
|
+
*/
|
|
36357
|
+
const adoptSubjectBox = (from, to) => {
|
|
36358
|
+
const labels = labelsByBbox.get(from);
|
|
36359
|
+
if (labels !== void 0) labelsByBbox.set(to, labels);
|
|
36360
|
+
const tier = originalClassTierByBbox.get(from);
|
|
36361
|
+
if (tier !== void 0) originalClassTierByBbox.set(to, tier);
|
|
36362
|
+
const embedding = embeddingByBbox.get(from);
|
|
36363
|
+
if (embedding !== void 0) embeddingByBbox.set(to, embedding);
|
|
36364
|
+
const mask = maskByBbox.get(from);
|
|
36365
|
+
if (mask !== void 0) maskByBbox.set(to, mask);
|
|
36366
|
+
const plate = plateByBbox.get(from);
|
|
36367
|
+
if (plate !== void 0) plateByBbox.set(to, plate);
|
|
36368
|
+
const faceBbox = faceBboxByBbox.get(from);
|
|
36369
|
+
if (faceBbox !== void 0) faceBboxByBbox.set(to, faceBbox);
|
|
36370
|
+
const faceSize = nativeFaceSizeByBbox.get(from);
|
|
36371
|
+
if (faceSize !== void 0) nativeFaceSizeByBbox.set(to, faceSize);
|
|
36372
|
+
const alignedCrop = faceAlignedCropByBbox.get(from);
|
|
36373
|
+
if (alignedCrop !== void 0) faceAlignedCropByBbox.set(to, alignedCrop);
|
|
36374
|
+
const sourceId = sourceIdByBbox.get(from);
|
|
36375
|
+
if (sourceId !== void 0) {
|
|
36376
|
+
sourceIdByBbox.set(to, sourceId);
|
|
36377
|
+
firstLevelBboxById.set(sourceId, to);
|
|
36378
|
+
}
|
|
36379
|
+
};
|
|
36380
|
+
/** Folded vehicles, by their index in `filteredDetections`. */
|
|
36381
|
+
const foldedVehicles = /* @__PURE__ */ new Map();
|
|
36313
36382
|
for (const p of riderPairs) {
|
|
36314
|
-
const
|
|
36315
|
-
|
|
36316
|
-
|
|
36383
|
+
const vehicleIdx = Number(p.vehicleId);
|
|
36384
|
+
const vehicle = filteredDetections[vehicleIdx];
|
|
36385
|
+
const person = filteredDetections[Number(p.personId)];
|
|
36386
|
+
if (vehicle === void 0 || person === void 0) continue;
|
|
36387
|
+
const subjectBox = riderSubjectBox(person.bbox, vehicle.bbox);
|
|
36388
|
+
adoptSubjectBox(vehicle.bbox, subjectBox);
|
|
36389
|
+
const folded = {
|
|
36390
|
+
...vehicle,
|
|
36391
|
+
bbox: subjectBox
|
|
36392
|
+
};
|
|
36393
|
+
foldedVehicles.set(vehicleIdx, folded);
|
|
36394
|
+
foldByVehicleBbox.set(subjectBox, {
|
|
36317
36395
|
overlap: p.overlap,
|
|
36318
|
-
personScore:
|
|
36396
|
+
personScore: person.score,
|
|
36319
36397
|
vehicleScore: vehicle.score,
|
|
36320
36398
|
vehicleClass: vehicle.originalClass ?? "two-wheeler"
|
|
36321
36399
|
});
|
|
36322
36400
|
}
|
|
36323
|
-
filteredDetections = filteredDetections.filter((_, i) => !riderIdx.has(i));
|
|
36401
|
+
filteredDetections = filteredDetections.map((d, i) => foldedVehicles.get(i) ?? d).filter((_, i) => !riderIdx.has(i));
|
|
36324
36402
|
}
|
|
36325
36403
|
const gate = this.stationaryGate ? this.stationaryGate.filter({
|
|
36326
36404
|
detections: filteredDetections,
|
|
@@ -48994,10 +49072,9 @@ var FaceRecognizer = class {
|
|
|
48994
49072
|
margin: settings.margin,
|
|
48995
49073
|
minIdentitySamples: settings.minIdentitySamples
|
|
48996
49074
|
}) : /* @__PURE__ */ new Map();
|
|
48997
|
-
if (this.deps.
|
|
49075
|
+
if (this.deps.onSemanticFace !== void 0) for (const c of matchCandidates) {
|
|
48998
49076
|
const match = matches.get(c.trackId);
|
|
48999
|
-
|
|
49000
|
-
this.deps.onSemanticMatch({
|
|
49077
|
+
this.deps.onSemanticFace({
|
|
49001
49078
|
deviceId: input.deviceId,
|
|
49002
49079
|
trackId: c.trackId,
|
|
49003
49080
|
timestamp: input.timestamp,
|
|
@@ -49005,8 +49082,10 @@ var FaceRecognizer = class {
|
|
|
49005
49082
|
frameHeight: input.frameHeight,
|
|
49006
49083
|
bbox: c.bbox,
|
|
49007
49084
|
confidence: c.confidence,
|
|
49008
|
-
|
|
49009
|
-
|
|
49085
|
+
...match !== void 0 ? {
|
|
49086
|
+
matchScore: match.score,
|
|
49087
|
+
identityId: match.identityId
|
|
49088
|
+
} : {},
|
|
49010
49089
|
...input.frameHandle !== void 0 ? { frameHandle: input.frameHandle } : {}
|
|
49011
49090
|
});
|
|
49012
49091
|
}
|
|
@@ -53353,6 +53432,19 @@ var DeferredBirthRegistry = class {
|
|
|
53353
53432
|
}
|
|
53354
53433
|
};
|
|
53355
53434
|
//#endregion
|
|
53435
|
+
//#region src/pipeline-analytics/pipeline/detail-semantic-gate.ts
|
|
53436
|
+
/** The detail `className` whose result IS the recognition. */
|
|
53437
|
+
var PLATE_CLASS = "plate";
|
|
53438
|
+
/**
|
|
53439
|
+
* The moment `className`'s detail result earns the semantic tier.
|
|
53440
|
+
*
|
|
53441
|
+
* `recognition` — promote as soon as the result exists (the plate read).
|
|
53442
|
+
* `label-write` — promote only once the track ACCEPTED the label.
|
|
53443
|
+
*/
|
|
53444
|
+
function detailSemanticTrigger(className) {
|
|
53445
|
+
return className === PLATE_CLASS ? "recognition" : "label-write";
|
|
53446
|
+
}
|
|
53447
|
+
//#endregion
|
|
53356
53448
|
//#region src/pipeline-analytics/pipeline/dropout-skip.ts
|
|
53357
53449
|
function shouldSkipDropoutFrame(activeTrackCount, detectionCount, consecutiveSkips, cfg) {
|
|
53358
53450
|
if (!cfg.enabled) return false;
|
|
@@ -71052,18 +71144,18 @@ var PipelineAnalyticsAddon = class PipelineAnalyticsAddon extends BaseAddon {
|
|
|
71052
71144
|
},
|
|
71053
71145
|
getKeyFrameMediaKey: (trackId) => this.residents.keyFrameKey(trackId),
|
|
71054
71146
|
emitFaceGalleryChanged: (payload) => this.emitFaceGalleryChanged(payload),
|
|
71055
|
-
|
|
71056
|
-
deviceId:
|
|
71057
|
-
trackId:
|
|
71058
|
-
timestamp:
|
|
71059
|
-
bbox:
|
|
71060
|
-
frameWidth:
|
|
71061
|
-
frameHeight:
|
|
71062
|
-
kind: "face",
|
|
71063
|
-
score:
|
|
71064
|
-
confidence:
|
|
71065
|
-
...
|
|
71066
|
-
}),
|
|
71147
|
+
onSemanticFace: (face) => this.promoteSemanticRecognition({
|
|
71148
|
+
deviceId: face.deviceId,
|
|
71149
|
+
trackId: face.trackId,
|
|
71150
|
+
timestamp: face.timestamp,
|
|
71151
|
+
bbox: face.bbox,
|
|
71152
|
+
frameWidth: face.frameWidth,
|
|
71153
|
+
frameHeight: face.frameHeight,
|
|
71154
|
+
kind: face.identityId !== void 0 ? "face" : "face-visible",
|
|
71155
|
+
score: face.matchScore ?? face.confidence,
|
|
71156
|
+
confidence: face.confidence,
|
|
71157
|
+
...face.frameHandle !== void 0 ? { frameHandle: face.frameHandle } : {}
|
|
71158
|
+
}, face.identityId !== void 0 ? "identified" : "evidence"),
|
|
71067
71159
|
onLiveHierarchy: (input) => this.requestTrackHierarchy(input),
|
|
71068
71160
|
logger: logger.child("FaceRecognizer")
|
|
71069
71161
|
});
|
|
@@ -74079,10 +74171,12 @@ var PipelineAnalyticsAddon = class PipelineAnalyticsAddon extends BaseAddon {
|
|
|
74079
74171
|
} } : {}
|
|
74080
74172
|
});
|
|
74081
74173
|
}
|
|
74174
|
+
if (detailSemanticTrigger(d.className) === "recognition") this.promoteSemanticRecognition(semanticFrameForDetailAttribution(deviceId, trackId, d, frame), "identified");
|
|
74082
74175
|
}
|
|
74083
74176
|
const resolved = d.className === "plate" ? this.plateRecognizer?.resolveLabelWithVehicle(d.label, d.score) ?? null : { text: d.label };
|
|
74084
74177
|
if (resolved !== null && resolved.text !== void 0) {
|
|
74085
|
-
|
|
74178
|
+
const applied = await this.applyTrackEnrichmentLabel(deviceId, trackId, resolved.text, d, frame.timestamp, resolved.vehicleId);
|
|
74179
|
+
if (detailSemanticTrigger(d.className) === "label-write" && applied.trackWritten) this.promoteSemanticRecognition(semanticFrameForDetailAttribution(deviceId, trackId, d, frame), "identified");
|
|
74086
74180
|
}
|
|
74087
74181
|
} else if (d.className === "plate") this.failureReport.notePlateRead(deviceId, d.bbox === void 0 ? REASON_NO_BBOX : REASON_EMPTY_READ);
|
|
74088
74182
|
} catch (err) {
|
|
@@ -74523,8 +74617,8 @@ var PipelineAnalyticsAddon = class PipelineAnalyticsAddon extends BaseAddon {
|
|
|
74523
74617
|
* when it wins and the frame's pixels are still reachable. Callers: the
|
|
74524
74618
|
* FaceRecognizer's per-frame auto-match, and `routeDetailResults`' plate /
|
|
74525
74619
|
* fine-classification attribution. */
|
|
74526
|
-
promoteSemanticRecognition(input) {
|
|
74527
|
-
this.recognizedTrackIds.add(input.trackId);
|
|
74620
|
+
promoteSemanticRecognition(input, origin) {
|
|
74621
|
+
if (origin === "identified") this.recognizedTrackIds.add(input.trackId);
|
|
74528
74622
|
const ctx = this.ctxIfReady;
|
|
74529
74623
|
if (ctx === null) return;
|
|
74530
74624
|
promoteSemanticBestFrame({
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@camstack/addon-post-analysis",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.211",
|
|
4
4
|
"description": "Post-Analysis bundle — enrichment, embedding-encoder, pipeline-analytics. Multi-entry npm package shipping addons that consume pipeline output.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"camstack",
|