|
@@ -1,7 +1,7 @@
|
1
|
1
|
import { setWasmPaths } from '@tensorflow/tfjs-backend-wasm';
|
2
|
2
|
import { Human, Config, FaceResult } from '@vladmandic/human';
|
3
|
3
|
|
4
|
|
-import { DETECTION_TYPES, FACE_EXPRESSIONS_NAMING_MAPPING } from './constants';
|
|
4
|
+import { DETECTION_TYPES, FACE_DETECTION_SCORE_THRESHOLD, FACE_EXPRESSIONS_NAMING_MAPPING } from './constants';
|
5
|
5
|
|
6
|
6
|
type Detection = {
|
7
|
7
|
detections: Array<FaceResult>,
|
|
@@ -130,7 +130,7 @@ export class HumanHelper implements FaceLandmarksHelper {
|
130
|
130
|
if (!detections.length) {
|
131
|
131
|
return;
|
132
|
132
|
}
|
133
|
|
-
|
|
133
|
+
|
134
|
134
|
const faceBox: FaceBox = {
|
135
|
135
|
// normalize to percentage based
|
136
|
136
|
left: Math.round(Math.min(...detections.map(d => d.boxRaw[0])) * 100),
|
|
@@ -154,41 +154,49 @@ export class HumanHelper implements FaceLandmarksHelper {
|
154
|
154
|
}
|
155
|
155
|
}
|
156
|
156
|
|
|
157
|
+ async getDetections(image: ImageBitmap | ImageData) {
|
|
158
|
+ if (!this.human) {
|
|
159
|
+ return;
|
|
160
|
+ }
|
|
161
|
+
|
|
162
|
+ this.human.tf.engine().startScope();
|
|
163
|
+
|
|
164
|
+ const imageTensor = this.human.tf.browser.fromPixels(image);
|
|
165
|
+ const { face: detections } = await this.human.detect(imageTensor, this.config);
|
|
166
|
+
|
|
167
|
+ this.human.tf.engine().endScope();
|
|
168
|
+
|
|
169
|
+ return detections.filter(detection => detection.score > FACE_DETECTION_SCORE_THRESHOLD);
|
|
170
|
+ }
|
|
171
|
+
|
157
|
172
|
public async detect({ image, threshold } : DetectInput): Promise<DetectOutput | undefined> {
|
158
|
173
|
let detections;
|
159
|
174
|
let faceExpression;
|
160
|
175
|
let faceBox;
|
161
|
176
|
|
162
|
|
- if (!this.human){
|
163
|
|
- return;
|
164
|
|
- }
|
165
|
|
-
|
166
|
177
|
this.detectionInProgress = true;
|
167
|
|
- this.human.tf.engine().startScope();
|
168
|
|
-
|
169
|
|
- const imageTensor = this.human.tf.browser.fromPixels(image);
|
170
|
178
|
|
171
|
179
|
if (this.faceDetectionTypes.includes(DETECTION_TYPES.FACE_EXPRESSIONS)) {
|
172
|
|
- const { face } = await this.human.detect(imageTensor, this.config);
|
|
180
|
+ detections = await this.getDetections(image);
|
173
|
181
|
|
174
|
|
- detections = face;
|
175
|
|
- faceExpression = this.getFaceExpression({ detections });
|
|
182
|
+ if (detections) {
|
|
183
|
+ faceExpression = this.getFaceExpression({ detections });
|
|
184
|
+ }
|
176
|
185
|
}
|
177
|
186
|
|
178
|
187
|
if (this.faceDetectionTypes.includes(DETECTION_TYPES.FACE_BOX)) {
|
179
|
188
|
if (!detections) {
|
180
|
|
- const { face } = await this.human.detect(imageTensor, this.config);
|
181
|
|
-
|
182
|
|
- detections = face;
|
|
189
|
+ detections = await this.getDetections(image);
|
183
|
190
|
}
|
184
|
191
|
|
185
|
|
- faceBox = this.getFaceBox({
|
186
|
|
- detections,
|
187
|
|
- threshold
|
188
|
|
- });
|
|
192
|
+ if(detections) {
|
|
193
|
+ faceBox = this.getFaceBox({
|
|
194
|
+ detections,
|
|
195
|
+ threshold
|
|
196
|
+ });
|
|
197
|
+ }
|
189
|
198
|
}
|
190
|
|
-
|
191
|
|
- this.human.tf.engine().endScope();
|
|
199
|
+
|
192
|
200
|
this.detectionInProgress = false;
|
193
|
201
|
|
194
|
202
|
return {
|