Skip to content
This repository was archived by the owner on May 27, 2025. It is now read-only.

Commit c0066a5

Browse files
author
danecreekphotography
authored
Issue384 (#388)
* Initial (untested) support * Fixed logic, seems to work
1 parent 771e1a9 commit c0066a5

6 files changed

Lines changed: 58 additions & 5 deletions

File tree

.devcontainer/triggers.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,14 @@
3030
"minimum": 50,
3131
"maximum": 100
3232
},
33+
"activateRegions": [
34+
{
35+
"xMinimum": 124,
36+
"xMaximum": 200,
37+
"yMinimum": 30,
38+
"yMaximum": 200
39+
}
40+
],
3341
"handlers": {
3442
"webRequest": {
3543
"triggerUris": ["http://localhost:81/admin?trigger&camera=Dog&memo={{formattedPredictions}}"]

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
# Change Log
22

3+
## 5.4.0
4+
5+
- Triggers can now specify `activateRegions` which have the opposite effect of masks. If activateRegions are specified then the triggering
6+
object's bounding box must overlap with the activate region for the trigger to fire. Resolves [issue 384](https://github.com/danecreekphotography/node-deepstackai-trigger/issues/384).
7+
38
## 5.3.1
49

510
- File watching now works on Macs when the folder of images is a mounted network share. Resolves [issue 362](https://github.com/danecreekphotography/node-deepstackai-trigger/issues/362).

src/Trigger.ts

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ export default class Trigger {
4141
public enabled = true;
4242
public name: string;
4343
public masks: Rect[];
44+
public activateRegions: Rect[];
4445
public receivedDate: Date;
4546
public snapshotUri?: string;
4647
public threshold: {
@@ -214,7 +215,8 @@ export default class Trigger {
214215
const isTriggered =
215216
this.isRegisteredForObject(fileName, label) &&
216217
this.confidenceMeetsThreshold(fileName, scaledConfidence) &&
217-
!this.isMasked(fileName, prediction);
218+
!this.isMasked(fileName, this.masks, true, prediction) &&
219+
this.isMasked(fileName, this.activateRegions, false, prediction);
218220

219221
if (!isTriggered) {
220222
log.verbose(`Trigger ${this.name}`, `${fileName}: Not triggered by ${label} (${scaledConfidence})`);
@@ -227,21 +229,46 @@ export default class Trigger {
227229
/**
228230
* Checks to see if predictions overlap the list of masks defined in the trigger
229231
* @param fileName The filename of the image being evaluated
232+
* @param masks The array of masks to check against
233+
* @param block True if this is a blocking mask.
230234
* @param predictions The list of predictions found in the image
231235
* @returns True if any of the predictions are masked
232236
*/
233-
public isMasked(fileName: string, prediction: IDeepStackPrediction): boolean {
234-
if (!this.masks) {
237+
public isMasked(fileName: string, masks: Rect[], block: boolean, prediction: IDeepStackPrediction): boolean {
238+
// If no masks are specified and this is a blocking mask return false since nothing could possibly be blocked.
239+
if (!masks && block) {
240+
log.verbose(
241+
`Trigger ${this.name}`,
242+
"No blocking masks specified and block is true so skipping blocking masks check.",
243+
);
235244
return false;
236245
}
237246

247+
// If no masks are specified and this is a non-blocking mask return true since everything should get accepted
248+
// to maintain backwards compatibility.
249+
if (!masks && !block) {
250+
log.verbose(
251+
`Trigger ${this.name}`,
252+
"No activate masks specified and block is false so skipping activate masks check.",
253+
);
254+
return true;
255+
}
256+
238257
// Loop through the masks to see if any overlap the prediction
239-
const result = this.masks.some(mask => {
258+
const result = masks.some(mask => {
240259
const predictionRect = new Rect(prediction.x_min, prediction.y_min, prediction.x_max, prediction.y_max);
241260
const doesOverlap = mask.overlaps(predictionRect);
242261

243262
if (doesOverlap) {
244-
log.verbose(`Trigger ${this.name}`, `Prediction region ${predictionRect} blocked by trigger mask ${mask}.`);
263+
log.verbose(
264+
`Trigger ${this.name}`,
265+
`Prediction region ${predictionRect} ${block ? "blocked" : "activated"} by mask ${mask}.`,
266+
);
267+
} else {
268+
log.verbose(
269+
`Trigger ${this.name}`,
270+
`Prediction region ${predictionRect} does not overlap with ${block ? "block" : "activate"} region ${mask}.`,
271+
);
245272
}
246273

247274
return doesOverlap;

src/TriggerManager.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,10 @@ export function loadConfiguration(configFilePaths: string[]): string {
8989
configuredTrigger.masks = triggerJson.masks?.map(
9090
mask => new Rect(mask.xMinimum, mask.yMinimum, mask.xMaximum, mask.yMaximum),
9191
);
92+
// Set up the masks as real objects
93+
configuredTrigger.activateRegions = triggerJson.activateRegions?.map(
94+
mask => new Rect(mask.xMinimum, mask.yMinimum, mask.xMaximum, mask.yMaximum),
95+
);
9296

9397
// Set up the handlers
9498
if (triggerJson.handlers.mqtt) {

src/schemas/triggerConfiguration.schema.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,14 @@
117117
"$ref": "https://raw.githubusercontent.com/danecreekphotography/node-deepstackai-trigger/main/src/schemas/maskConfiguration.schema.json"
118118
}
119119
},
120+
"activateRegions": {
121+
"description": "A list of rectangles that activate the trigger if a detected object overlaps the rectangle.",
122+
"type": "array",
123+
"minItems": 1,
124+
"items": {
125+
"$ref": "https://raw.githubusercontent.com/danecreekphotography/node-deepstackai-trigger/main/src/schemas/maskConfiguration.schema.json"
126+
}
127+
},
120128
"watchObjects": {
121129
"description": "A list of objects the trigger will activate on.",
122130
"type": "array",

src/types/ITriggerJson.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,4 +31,5 @@ export default interface ITriggerJson {
3131
};
3232

3333
masks: Rect[];
34+
activateRegions: Rect[];
3435
}

0 commit comments

Comments
 (0)