mirror of
https://github.com/koush/scrypted.git
synced 2026-07-10 08:50:31 +01:00
videoanalysis: better object timeout. fix motion zones.
This commit is contained in:
4
plugins/objectdetector/package-lock.json
generated
4
plugins/objectdetector/package-lock.json
generated
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "@scrypted/objectdetector",
|
||||
"version": "0.0.46",
|
||||
"version": "0.0.47",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@scrypted/objectdetector",
|
||||
"version": "0.0.46",
|
||||
"version": "0.0.47",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@scrypted/common": "file:../../common",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@scrypted/objectdetector",
|
||||
"version": "0.0.46",
|
||||
"version": "0.0.47",
|
||||
"description": "Scrypted Video Analysis Plugin. Installed alongside a detection service like OpenCV or TensorFlow.",
|
||||
"author": "Scrypted",
|
||||
"license": "Apache-2.0",
|
||||
|
||||
@@ -2,7 +2,7 @@ export class DenoisedDetectionEntry<T> {
|
||||
id: string;
|
||||
name: string;
|
||||
detection: T;
|
||||
timeout?: NodeJS.Timeout;
|
||||
lastSeen: number;
|
||||
}
|
||||
|
||||
export interface DenoisedDetectionOptions<T> {
|
||||
@@ -15,6 +15,7 @@ export function denoiseDetections<T>(previousDetections: DenoisedDetectionEntry<
|
||||
currentDetections: DenoisedDetectionEntry<T>[],
|
||||
options?: DenoisedDetectionOptions<T>
|
||||
) {
|
||||
const now = Date.now();
|
||||
const newAndExisting: DenoisedDetectionEntry<T>[] = [];
|
||||
for (const cd of currentDetections) {
|
||||
let index = -1;
|
||||
@@ -28,24 +29,20 @@ export function denoiseDetections<T>(previousDetections: DenoisedDetectionEntry<
|
||||
}
|
||||
else {
|
||||
const [found] = previousDetections.splice(index, 1);
|
||||
if (found.timeout) {
|
||||
clearTimeout(found.timeout);
|
||||
found.timeout = undefined;
|
||||
}
|
||||
found.lastSeen = now;
|
||||
newAndExisting.push(cd);
|
||||
}
|
||||
}
|
||||
|
||||
const purgeTime = options?.timeout || 10000;
|
||||
// anything remaining in previousDetections at this point has possibly left the scene.
|
||||
for (const cd of previousDetections) {
|
||||
if (!cd.timeout) {
|
||||
cd.timeout = setTimeout(() => {
|
||||
const index = previousDetections.findIndex(check => check === cd);
|
||||
if (index !== -1)
|
||||
previousDetections.splice(index, 1);
|
||||
options?.removed?.(cd);
|
||||
}, options?.timeout || 10000);
|
||||
}
|
||||
for (const cd of previousDetections.slice()) {
|
||||
if (now - cd.lastSeen < purgeTime)
|
||||
continue;
|
||||
const index = previousDetections.findIndex(check => check === cd);
|
||||
if (index !== -1)
|
||||
previousDetections.splice(index, 1);
|
||||
options?.removed?.(cd);
|
||||
}
|
||||
|
||||
// add all the detections that are pending removal
|
||||
|
||||
@@ -220,6 +220,8 @@ class ObjectDetectionMixin extends SettingsMixinDeviceBase<VideoCamera & Camera
|
||||
if (!this.internal) {
|
||||
stream = await this.cameraDevice.getVideoStream({
|
||||
destination: 'low-resolution',
|
||||
// request no prebuffer because it will throw off detection timestamps.
|
||||
prebuffer: 0,
|
||||
});
|
||||
}
|
||||
else {
|
||||
@@ -250,6 +252,34 @@ class ObjectDetectionMixin extends SettingsMixinDeviceBase<VideoCamera & Camera
|
||||
if (detectionInput)
|
||||
this.setDetection(this.detectionId, detectionInput);
|
||||
|
||||
// determine zones of the objects, if configured.
|
||||
if (detection.detections && Object.keys(this.zones).length) {
|
||||
for (const o of detection.detections) {
|
||||
if (!o.boundingBox)
|
||||
continue;
|
||||
o.zones = []
|
||||
let [x, y, width, height] = o.boundingBox;
|
||||
let x2 = x + width;
|
||||
let y2 = y + height;
|
||||
// the zones are point paths in percentage format
|
||||
x = x * 100 / detection.inputDimensions[0];
|
||||
y = y * 100 / detection.inputDimensions[1];
|
||||
x2 = x2 * 100 / detection.inputDimensions[0];
|
||||
y2 = y2 * 100 / detection.inputDimensions[1];
|
||||
const box = [[x, y], [x2, y], [x2, y2], [x, y2]];
|
||||
for (const [zone, zoneValue] of Object.entries(this.zones)) {
|
||||
if (polygonOverlap(box, zoneValue)) {
|
||||
this.console.log(o.className, 'inside', zone);
|
||||
o.zones.push(zone);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if this detector supports bounding boxes, and there are zones configured,
|
||||
// filter the detections to the zones.
|
||||
detection.detections = detection.detections.filter(o => !o.boundingBox || o?.zones?.length);
|
||||
|
||||
if (this.hasMotionType) {
|
||||
const found = detection.detections?.find(d => d.className === 'motion');
|
||||
if (found) {
|
||||
@@ -263,35 +293,8 @@ class ObjectDetectionMixin extends SettingsMixinDeviceBase<VideoCamera & Camera
|
||||
}
|
||||
}
|
||||
|
||||
if (!this.hasMotionType || this.motionAsObjects) {
|
||||
if (detection.detections && Object.keys(this.zones).length) {
|
||||
for (const o of detection.detections) {
|
||||
if (!o.boundingBox)
|
||||
continue;
|
||||
o.zones = []
|
||||
let [x, y, width, height] = o.boundingBox;
|
||||
let x2 = x + width;
|
||||
let y2 = y + height;
|
||||
// the zones are point paths in percentage format
|
||||
x = x * 100 / detection.inputDimensions[0];
|
||||
y = y * 100 / detection.inputDimensions[1];
|
||||
x2 = x2 * 100 / detection.inputDimensions[0];
|
||||
y2 = y2 * 100 / detection.inputDimensions[1];
|
||||
const box = [[x, y], [x2, y], [x2, y2], [x, y2]];
|
||||
for (const [zone, zoneValue] of Object.entries(this.zones)) {
|
||||
if (polygonOverlap(box, zoneValue)) {
|
||||
this.console.log(o.className, 'inside', zone);
|
||||
o.zones.push(zone);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if this detector supports bounding boxes, and there are zones configured,
|
||||
// filter the detections to the zones.
|
||||
detection.detections = detection.detections.filter(o => !o.boundingBox || o?.zones?.length);
|
||||
}
|
||||
if (!this.hasMotionType || this.motionAsObjects)
|
||||
this.onDeviceEvent(ScryptedInterface.ObjectDetector, detection);
|
||||
}
|
||||
}
|
||||
|
||||
async extendedObjectDetect() {
|
||||
@@ -324,6 +327,7 @@ class ObjectDetectionMixin extends SettingsMixinDeviceBase<VideoCamera & Camera
|
||||
id: detection.id,
|
||||
name: detection.className,
|
||||
detection,
|
||||
lastSeen: detectionResult.timestamp,
|
||||
})), {
|
||||
timeout: this.detectionTimeout * 1000,
|
||||
added: d => found.push(d),
|
||||
|
||||
Reference in New Issue
Block a user