Skip to content

Commit 2bf4406

Browse files
committed
feat(mqtt & api): total count for person, match, miss, and unknown (#223)
also refactored how the values are calculated
1 parent 759659c commit 2bf4406

File tree

3 files changed

+87
-80
lines changed

3 files changed

+87
-80
lines changed

api/src/controllers/recognize.controller.js

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ module.exports.start = async (req, res) => {
148148
);
149149
}
150150

151-
const { best, misses, unknown, results, attempts } = recognize.normalize(
151+
const { best, misses, unknowns, results, attempts, counts } = recognize.normalize(
152152
await Promise.all(promises)
153153
);
154154

@@ -160,28 +160,28 @@ module.exports.start = async (req, res) => {
160160
attempts,
161161
camera,
162162
zones,
163+
counts,
163164
matches: best,
164165
misses,
166+
unknowns,
165167
};
166-
if (unknown && Object.keys(unknown).length) output.unknown = unknown;
167168
if (AUTH) output.token = jwt.sign({ route: 'storage', expiresIn: TOKEN.IMAGE });
168169

169170
if (resultsOutput === 'all') output.results = results;
170171

171172
console.log(`done processing ${camera}: ${id} in ${duration} sec`);
172173

173174
const loggedOutput = JSON.parse(JSON.stringify(output));
174-
['matches', 'misses'].forEach((type) =>
175+
['matches', 'misses', 'unknowns'].forEach((type) =>
175176
loggedOutput[type].forEach((result) => delete result.base64)
176177
);
177-
if (loggedOutput.unknown) delete loggedOutput.unknown.base64;
178178
console.log(loggedOutput);
179179

180180
PROCESSING = false;
181181

182182
res.send(output);
183183

184-
recognize.save.latest(camera, best, misses, unknown);
184+
recognize.save.latest(camera, best, misses, unknowns[0]);
185185
mqtt.recognize(output);
186186
notify.publish(output, camera, results);
187187
if (event.type === 'frigate') frigate.subLabel(event.topic, id, best);

api/src/util/mqtt.util.js

Lines changed: 43 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ const { v4: uuidv4 } = require('uuid');
33
const axios = require('axios');
44
const mqtt = require('mqtt');
55
const fs = require('./fs.util');
6-
const { contains } = require('./helpers.util');
76
const { jwt } = require('./auth.util');
87
const { AUTH, SERVER, MQTT, FRIGATE, CAMERAS, STORAGE, UI } = require('../constants')();
98
const config = require('../constants/config');
@@ -156,47 +155,51 @@ module.exports.subscribe = () => {
156155
module.exports.recognize = (data) => {
157156
try {
158157
if (!MQTT || !MQTT.HOST) return;
159-
const { matches, misses, unknown } = data;
160-
const camera = data.camera.toLowerCase();
161-
const hasUnknown = unknown && Object.keys(unknown).length;
162-
163-
const configData = JSON.parse(JSON.stringify(data));
164-
delete configData.matches;
165-
delete configData.unknown;
166-
delete configData.results;
158+
const baseData = JSON.parse(JSON.stringify(data));
159+
const { id, duration, timestamp, attempts, zones, matches, misses, unknowns, counts } =
160+
baseData;
161+
const camera = baseData.camera.toLowerCase();
162+
163+
const payload = {
164+
base: {
165+
id,
166+
duration,
167+
timestamp,
168+
attempts,
169+
camera,
170+
zones,
171+
},
172+
};
173+
payload.unknown = { ...payload.base, unknown: unknowns[0], unknowns };
174+
payload.match = { ...payload.base };
175+
payload.camera = {
176+
...payload.base,
177+
matches,
178+
misses,
179+
unknowns,
180+
counts,
181+
};
182+
payload.cameraReset = {
183+
...payload.camera,
184+
counts: {
185+
person: 0,
186+
match: 0,
187+
miss: 0,
188+
unknown: 0,
189+
},
190+
};
167191

168192
const messages = [];
169-
const persons = [...new Set([...matches, ...misses].map(({ name }) => name))];
170-
let personCount = persons.length ? persons.length : hasUnknown ? 1 : 0;
171-
// check to see if unknown bounding box is contained within or contains any of the match bounding boxes
172-
// if false, then add 1 to the person count
173-
if (persons.length && hasUnknown) {
174-
let unknownFoundInMatch = false;
175-
matches.forEach((match) => {
176-
if (contains(match.box, unknown.box) || contains(unknown.box, match.box))
177-
unknownFoundInMatch = true;
178-
});
179-
180-
let unknownFoundInMiss = false;
181-
misses.forEach((miss) => {
182-
if (contains(miss.box, unknown.box) || contains(unknown.box, miss.box))
183-
unknownFoundInMiss = true;
184-
});
185-
if (!unknownFoundInMatch && !unknownFoundInMiss) personCount += 1;
186-
}
187193

188194
messages.push({
189195
topic: `${MQTT.TOPICS.CAMERAS}/${camera}/person`,
190-
message: personCount.toString(),
196+
message: counts.person.toString(),
191197
});
192198

193-
if (hasUnknown) {
199+
if (unknowns.length) {
194200
messages.push({
195201
topic: `${MQTT.TOPICS.MATCHES}/unknown`,
196-
message: JSON.stringify({
197-
...configData,
198-
unknown,
199-
}),
202+
message: JSON.stringify(payload.unknown),
200203
});
201204

202205
if (MQTT.TOPICS.HOMEASSISTANT) {
@@ -215,10 +218,7 @@ module.exports.recognize = (data) => {
215218

216219
messages.push({
217220
topic: `${MQTT.TOPICS.HOMEASSISTANT}/sensor/double-take/unknown/state`,
218-
message: JSON.stringify({
219-
...configData,
220-
unknown,
221-
}),
221+
message: JSON.stringify(payload.unknown),
222222
});
223223
}
224224
}
@@ -230,7 +230,7 @@ module.exports.recognize = (data) => {
230230
messages.push({
231231
topic: `${MQTT.TOPICS.MATCHES}/${topic}`,
232232
message: JSON.stringify({
233-
...configData,
233+
...payload.match,
234234
match,
235235
}),
236236
});
@@ -252,22 +252,17 @@ module.exports.recognize = (data) => {
252252
messages.push({
253253
topic: `${MQTT.TOPICS.HOMEASSISTANT}/sensor/double-take/${topic}/state`,
254254
message: JSON.stringify({
255-
...configData,
255+
...payload.match,
256256
match,
257257
}),
258258
});
259259
}
260260
});
261261

262-
if (matches.length || misses.length || hasUnknown) {
262+
if (matches.length || misses.length || unknowns.length) {
263263
messages.push({
264264
topic: `${MQTT.TOPICS.CAMERAS}/${camera}`,
265-
message: JSON.stringify({
266-
...configData,
267-
matches,
268-
misses,
269-
unknown,
270-
}),
265+
message: JSON.stringify(payload.camera),
271266
});
272267

273268
if (MQTT.TOPICS.HOMEASSISTANT) {
@@ -286,13 +281,7 @@ module.exports.recognize = (data) => {
286281

287282
messages.push({
288283
topic: `${MQTT.TOPICS.HOMEASSISTANT}/sensor/double-take/${camera}/state`,
289-
message: JSON.stringify({
290-
...configData,
291-
matches,
292-
misses,
293-
unknown,
294-
personCount,
295-
}),
284+
message: JSON.stringify(payload.camera),
296285
});
297286
}
298287
}
@@ -305,12 +294,7 @@ module.exports.recognize = (data) => {
305294
if (MQTT.TOPICS.HOMEASSISTANT) {
306295
this.publish({
307296
topic: `${MQTT.TOPICS.HOMEASSISTANT}/sensor/double-take/${camera}/state`,
308-
message: JSON.stringify({
309-
...configData,
310-
matches,
311-
unknown,
312-
personCount: 0,
313-
}),
297+
message: JSON.stringify(payload.cameraReset),
314298
});
315299
}
316300
}, 30000);

api/src/util/recognize.util.js

Lines changed: 39 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -39,28 +39,33 @@ module.exports.save = {
3939

4040
module.exports.normalize = (results = []) => {
4141
const best = { matches: [], misses: [] };
42-
const tmp = { matches: {}, misses: {} };
43-
let unknown = {};
42+
const tmp = { matches: {}, misses: {}, counts: {} };
43+
const unknowns = [];
4444

4545
let attempts = 0;
4646
results.forEach((group) => {
4747
attempts += group.attempts;
4848
group.results.forEach((attempt) => {
49+
const face = tmp.counts[attempt.detector];
50+
if (face)
51+
tmp.counts[attempt.detector] = {
52+
count: face.count + attempt.results.length,
53+
attempts: (face.attempts += 1),
54+
};
55+
else tmp.counts[attempt.detector] = { count: attempt.results.length, attempts: 1 };
56+
4957
const matches = attempt.results.filter((obj) => obj.match);
5058
const misses = attempt.results.filter((obj) => !obj.match && obj.name !== 'unknown');
51-
const unknowns = attempt.results.filter((obj) => obj.name === 'unknown');
52-
53-
unknowns.forEach((obj) => {
54-
if (unknown.confidence === undefined || unknown.confidence < obj.confidence) {
55-
unknown = {
56-
...obj,
57-
type: group.type,
58-
duration: attempt.duration,
59-
detector: attempt.detector,
60-
filename: attempt.filename,
61-
base64: attempt.base64 || null,
62-
};
63-
}
59+
const tmpUnknowns = attempt.results.filter((obj) => obj.name === 'unknown');
60+
tmpUnknowns.forEach((obj) => {
61+
unknowns.push({
62+
...obj,
63+
type: group.type,
64+
duration: attempt.duration,
65+
detector: attempt.detector,
66+
filename: attempt.filename,
67+
base64: attempt.base64 || null,
68+
});
6469
});
6570

6671
matches.forEach((match) => {
@@ -100,5 +105,23 @@ module.exports.normalize = (results = []) => {
100105
for (const value of Object.values(tmp.matches)) best.matches.push(value);
101106
for (const value of Object.values(tmp.misses)) best.misses.push(value);
102107

103-
return { best: best.matches, misses: best.misses, results, attempts, unknown };
108+
let personCount = 0;
109+
for (const [, value] of Object.entries(tmp.counts))
110+
personCount += Math.round(value.count / value.attempts);
111+
112+
const counts = {
113+
person: personCount ? Math.round(personCount / Object.keys(tmp.counts).length) : 0,
114+
match: best.matches.length,
115+
miss: best.misses.length,
116+
};
117+
counts.unknown = counts.person - counts.match - counts.miss;
118+
119+
return {
120+
best: best.matches,
121+
misses: best.misses,
122+
results,
123+
attempts,
124+
unknowns: unknowns.sort((a, b) => b.confidence - a.confidence),
125+
counts,
126+
};
104127
};

0 commit comments

Comments
 (0)