facecog-liveness-showcase 0.0.1
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/.browserslistrc +15 -0
- package/.dockerignore +48 -0
- package/.editorconfig +16 -0
- package/.eslintrc.json +47 -0
- package/.vercelignore +7 -0
- package/.vscode/extensions.json +5 -0
- package/.vscode/settings.json +3 -0
- package/DOCKER.md +221 -0
- package/Dockerfile +33 -0
- package/README.md +268 -0
- package/angular.json +156 -0
- package/capacitor.config.ts +9 -0
- package/docker-compose.dev.yml +20 -0
- package/docker-compose.yml +18 -0
- package/ionic.config.json +7 -0
- package/jest.config.js +38 -0
- package/nginx.conf +50 -0
- package/package.json +131 -0
- package/patches/ng-packagr+20.3.2.patch +60 -0
- package/projects/facecog-liveness-verification/README.md +295 -0
- package/projects/facecog-liveness-verification/ng-package.json +7 -0
- package/projects/facecog-liveness-verification/package.json +48 -0
- package/projects/facecog-liveness-verification/scripts/build-with-wrapper-copy.js +38 -0
- package/projects/facecog-liveness-verification/scripts/copy-wrapper-after-ngc.js +35 -0
- package/projects/facecog-liveness-verification/sources/FaceLivenessReactWrapper.tsx +320 -0
- package/projects/facecog-liveness-verification/src/lib/components/aws-face-liveness/FaceLivenessReactWrapper.generated.d.ts +28 -0
- package/projects/facecog-liveness-verification/src/lib/components/aws-face-liveness/FaceLivenessReactWrapper.generated.js +247 -0
- package/projects/facecog-liveness-verification/src/lib/components/aws-face-liveness/FaceLivenessReactWrapper.generated.js.map +1 -0
- package/projects/facecog-liveness-verification/src/lib/components/aws-face-liveness/FaceLivenessReactWrapper.js.map +1 -0
- package/projects/facecog-liveness-verification/src/lib/components/aws-face-liveness/FaceLivenessReactWrapper.ts +5 -0
- package/projects/facecog-liveness-verification/src/lib/components/aws-face-liveness/aws-face-liveness.component.ts +500 -0
- package/projects/facecog-liveness-verification/src/lib/components/camera-permission/camera-permission.component.html +41 -0
- package/projects/facecog-liveness-verification/src/lib/components/camera-permission/camera-permission.component.scss +234 -0
- package/projects/facecog-liveness-verification/src/lib/components/camera-permission/camera-permission.component.spec.ts +158 -0
- package/projects/facecog-liveness-verification/src/lib/components/camera-permission/camera-permission.component.ts +58 -0
- package/projects/facecog-liveness-verification/src/lib/components/camera-verification/camera-verification.component.html +34 -0
- package/projects/facecog-liveness-verification/src/lib/components/camera-verification/camera-verification.component.ts +210 -0
- package/projects/facecog-liveness-verification/src/lib/components/dialogs/save-custom-pose-dialog.component.ts +174 -0
- package/projects/facecog-liveness-verification/src/lib/components/facetec-scan/facetec-scan.component.html +45 -0
- package/projects/facecog-liveness-verification/src/lib/components/facetec-scan/facetec-scan.component.scss +87 -0
- package/projects/facecog-liveness-verification/src/lib/components/facetec-scan/facetec-scan.component.ts +182 -0
- package/projects/facecog-liveness-verification/src/lib/components/intro/intro.component.html +394 -0
- package/projects/facecog-liveness-verification/src/lib/components/intro/intro.component.scss +1567 -0
- package/projects/facecog-liveness-verification/src/lib/components/intro/intro.component.spec.ts +699 -0
- package/projects/facecog-liveness-verification/src/lib/components/intro/intro.component.ts +721 -0
- package/projects/facecog-liveness-verification/src/lib/components/live-preview/live-preview.component.html +120 -0
- package/projects/facecog-liveness-verification/src/lib/components/live-preview/live-preview.component.scss +611 -0
- package/projects/facecog-liveness-verification/src/lib/components/live-preview/live-preview.component.spec.ts +605 -0
- package/projects/facecog-liveness-verification/src/lib/components/live-preview/live-preview.component.ts +524 -0
- package/projects/facecog-liveness-verification/src/lib/components/liveness-flow/liveness-flow.component.html +73 -0
- package/projects/facecog-liveness-verification/src/lib/components/liveness-flow/liveness-flow.component.scss +19 -0
- package/projects/facecog-liveness-verification/src/lib/components/liveness-flow/liveness-flow.component.spec.ts +673 -0
- package/projects/facecog-liveness-verification/src/lib/components/liveness-flow/liveness-flow.component.ts +963 -0
- package/projects/facecog-liveness-verification/src/lib/components/liveness-verification/liveness-verification.component.html +38 -0
- package/projects/facecog-liveness-verification/src/lib/components/liveness-verification/liveness-verification.component.scss +10 -0
- package/projects/facecog-liveness-verification/src/lib/components/liveness-verification/liveness-verification.component.ts +233 -0
- package/projects/facecog-liveness-verification/src/lib/components/pose-selection/pose-selection.component.html +17 -0
- package/projects/facecog-liveness-verification/src/lib/components/pose-selection/pose-selection.component.spec.ts +35 -0
- package/projects/facecog-liveness-verification/src/lib/components/pose-selection/pose-selection.component.ts +33 -0
- package/projects/facecog-liveness-verification/src/lib/components/processing/processing.component.html +17 -0
- package/projects/facecog-liveness-verification/src/lib/components/processing/processing.component.scss +156 -0
- package/projects/facecog-liveness-verification/src/lib/components/processing/processing.component.spec.ts +46 -0
- package/projects/facecog-liveness-verification/src/lib/components/processing/processing.component.ts +18 -0
- package/projects/facecog-liveness-verification/src/lib/components/verification-result/verification-result.component.html +190 -0
- package/projects/facecog-liveness-verification/src/lib/components/verification-result/verification-result.component.scss +534 -0
- package/projects/facecog-liveness-verification/src/lib/components/verification-result/verification-result.component.spec.ts +286 -0
- package/projects/facecog-liveness-verification/src/lib/components/verification-result/verification-result.component.ts +155 -0
- package/projects/facecog-liveness-verification/src/lib/interfaces/analyze-response.interface.ts +16 -0
- package/projects/facecog-liveness-verification/src/lib/interfaces/aws-face-liveness.interface.ts +46 -0
- package/projects/facecog-liveness-verification/src/lib/interfaces/backend-adapter.interface.ts +21 -0
- package/projects/facecog-liveness-verification/src/lib/interfaces/backend-http-client.interface.ts +93 -0
- package/projects/facecog-liveness-verification/src/lib/interfaces/backend-response.interface.ts +9 -0
- package/projects/facecog-liveness-verification/src/lib/interfaces/camera-provider.interface.ts +107 -0
- package/projects/facecog-liveness-verification/src/lib/interfaces/category-info.interface.ts +9 -0
- package/projects/facecog-liveness-verification/src/lib/interfaces/custom-pose-data.interface.ts +14 -0
- package/projects/facecog-liveness-verification/src/lib/interfaces/custom-pose-repository.interface.ts +48 -0
- package/projects/facecog-liveness-verification/src/lib/interfaces/custom-pose-response.interface.ts +14 -0
- package/projects/facecog-liveness-verification/src/lib/interfaces/index.ts +52 -0
- package/projects/facecog-liveness-verification/src/lib/interfaces/liveness-action-result.interface.ts +13 -0
- package/projects/facecog-liveness-verification/src/lib/interfaces/liveness-config.interface.ts +17 -0
- package/projects/facecog-liveness-verification/src/lib/interfaces/liveness-metadata.interface.ts +17 -0
- package/projects/facecog-liveness-verification/src/lib/interfaces/liveness-result.interface.ts +24 -0
- package/projects/facecog-liveness-verification/src/lib/interfaces/liveness-verification-config.interface.ts +41 -0
- package/projects/facecog-liveness-verification/src/lib/interfaces/multi-backend-analyze-response.interface.ts +21 -0
- package/projects/facecog-liveness-verification/src/lib/interfaces/multi-backend-liveness-result.interface.ts +14 -0
- package/projects/facecog-liveness-verification/src/lib/interfaces/pose-definition.interface.ts +35 -0
- package/projects/facecog-liveness-verification/src/lib/interfaces/pose-keypoint.interface.ts +12 -0
- package/projects/facecog-liveness-verification/src/lib/interfaces/pose-match-result.interface.ts +9 -0
- package/projects/facecog-liveness-verification/src/lib/interfaces/pose-verify-response.interface.ts +8 -0
- package/projects/facecog-liveness-verification/src/lib/interfaces/scan-results.interface.ts +29 -0
- package/projects/facecog-liveness-verification/src/lib/interfaces/verification-plan.interface.ts +42 -0
- package/projects/facecog-liveness-verification/src/lib/interfaces/verification-progress-event.interface.ts +12 -0
- package/projects/facecog-liveness-verification/src/lib/interfaces/verification-session.interface.ts +72 -0
- package/projects/facecog-liveness-verification/src/lib/interfaces/verification-step-change-event.interface.ts +11 -0
- package/projects/facecog-liveness-verification/src/lib/interfaces/video-recording.interface.ts +9 -0
- package/projects/facecog-liveness-verification/src/lib/liveness-verification.module.ts +123 -0
- package/projects/facecog-liveness-verification/src/lib/models/constants/aws-face-liveness-component.token.ts +23 -0
- package/projects/facecog-liveness-verification/src/lib/models/constants/category-info.constant.ts +14 -0
- package/projects/facecog-liveness-verification/src/lib/models/constants/default-liveness-config.constant.ts +18 -0
- package/projects/facecog-liveness-verification/src/lib/models/constants/index.ts +5 -0
- package/projects/facecog-liveness-verification/src/lib/models/constants/liveness-verification-config.token.ts +16 -0
- package/projects/facecog-liveness-verification/src/lib/models/constants/pose-definitions.constant.ts +377 -0
- package/projects/facecog-liveness-verification/src/lib/models/index.ts +5 -0
- package/projects/facecog-liveness-verification/src/lib/models/utils/index.ts +2 -0
- package/projects/facecog-liveness-verification/src/lib/models/utils/pose.utils.spec.ts +76 -0
- package/projects/facecog-liveness-verification/src/lib/models/utils/pose.utils.ts +59 -0
- package/projects/facecog-liveness-verification/src/lib/services/aws-face-liveness.service.ts +49 -0
- package/projects/facecog-liveness-verification/src/lib/services/backend-http.service.spec.ts +111 -0
- package/projects/facecog-liveness-verification/src/lib/services/backend-http.service.ts +130 -0
- package/projects/facecog-liveness-verification/src/lib/services/backends/azure-backend.service.spec.ts +69 -0
- package/projects/facecog-liveness-verification/src/lib/services/backends/azure-backend.service.ts +72 -0
- package/projects/facecog-liveness-verification/src/lib/services/backends/facetec-backend.service.spec.ts +24 -0
- package/projects/facecog-liveness-verification/src/lib/services/backends/facetec-backend.service.ts +35 -0
- package/projects/facecog-liveness-verification/src/lib/services/backends/mock-backend.service.spec.ts +36 -0
- package/projects/facecog-liveness-verification/src/lib/services/backends/mock-backend.service.ts +39 -0
- package/projects/facecog-liveness-verification/src/lib/services/backends/openpose-backend.service.spec.ts +81 -0
- package/projects/facecog-liveness-verification/src/lib/services/backends/openpose-backend.service.ts +72 -0
- package/projects/facecog-liveness-verification/src/lib/services/backends/rekognition-analysis-backend.service.spec.ts +69 -0
- package/projects/facecog-liveness-verification/src/lib/services/backends/rekognition-analysis-backend.service.ts +83 -0
- package/projects/facecog-liveness-verification/src/lib/services/camera.service.spec.ts +200 -0
- package/projects/facecog-liveness-verification/src/lib/services/camera.service.ts +155 -0
- package/projects/facecog-liveness-verification/src/lib/services/custom-poses-api.service.ts +117 -0
- package/projects/facecog-liveness-verification/src/lib/services/index.ts +18 -0
- package/projects/facecog-liveness-verification/src/lib/services/liveness-backend.service.spec.ts +103 -0
- package/projects/facecog-liveness-verification/src/lib/services/liveness-backend.service.ts +61 -0
- package/projects/facecog-liveness-verification/src/lib/services/liveness-config.service.spec.ts +109 -0
- package/projects/facecog-liveness-verification/src/lib/services/liveness-config.service.ts +70 -0
- package/projects/facecog-liveness-verification/src/lib/services/liveness-orchestrator.service.spec.ts +144 -0
- package/projects/facecog-liveness-verification/src/lib/services/liveness-orchestrator.service.ts +162 -0
- package/projects/facecog-liveness-verification/src/lib/services/pose-detection/hand-gesture-detection.service.ts +315 -0
- package/projects/facecog-liveness-verification/src/lib/services/pose-detection/index.ts +5 -0
- package/projects/facecog-liveness-verification/src/lib/services/pose-detection/openpose.service.ts +287 -0
- package/projects/facecog-liveness-verification/src/lib/services/pose-detection/pose-comparison.service.ts +353 -0
- package/projects/facecog-liveness-verification/src/lib/services/pose-detection/pose-matching.service.ts +2370 -0
- package/projects/facecog-liveness-verification/src/lib/services/pose-detection/reference-pose.service.ts +271 -0
- package/projects/facecog-liveness-verification/src/lib/services/pose-selection.service.spec.ts +183 -0
- package/projects/facecog-liveness-verification/src/lib/services/pose-selection.service.ts +179 -0
- package/projects/facecog-liveness-verification/src/lib/services/verification-api.service.spec.ts +159 -0
- package/projects/facecog-liveness-verification/src/lib/services/verification-api.service.ts +151 -0
- package/projects/facecog-liveness-verification/src/lib/services/verification-plan.service.spec.ts +184 -0
- package/projects/facecog-liveness-verification/src/lib/services/verification-plan.service.ts +94 -0
- package/projects/facecog-liveness-verification/src/lib/services/video-recorder.service.spec.ts +52 -0
- package/projects/facecog-liveness-verification/src/lib/services/video-recorder.service.ts +117 -0
- package/projects/facecog-liveness-verification/src/lib/types/detection-strategy.type.ts +5 -0
- package/projects/facecog-liveness-verification/src/lib/types/index.ts +7 -0
- package/projects/facecog-liveness-verification/src/lib/types/liveness-action.type.ts +31 -0
- package/projects/facecog-liveness-verification/src/lib/types/liveness-backend.type.ts +5 -0
- package/projects/facecog-liveness-verification/src/lib/types/pose-category.type.ts +5 -0
- package/projects/facecog-liveness-verification/src/lib/types/pose-difficulty.type.ts +5 -0
- package/projects/facecog-liveness-verification/src/lib/types/verification-flow-step.type.ts +5 -0
- package/projects/facecog-liveness-verification/src/lib/types/verification-step-kind.type.ts +4 -0
- package/projects/facecog-liveness-verification/src/public-api.ts +150 -0
- package/projects/facecog-liveness-verification/tsconfig.lib.json +20 -0
- package/projects/facecog-liveness-verification/tsconfig.lib.prod.json +11 -0
- package/projects/facecog-liveness-verification/tsconfig.spec.json +13 -0
- package/projects/facecog-liveness-verification/tsconfig.wrapper.json +15 -0
- package/projects/facecog-liveness-verification-test/src/app/app-routing.module.ts +22 -0
- package/projects/facecog-liveness-verification-test/src/app/app.component.html +3 -0
- package/projects/facecog-liveness-verification-test/src/app/app.component.scss +0 -0
- package/projects/facecog-liveness-verification-test/src/app/app.component.ts +11 -0
- package/projects/facecog-liveness-verification-test/src/app/app.module.ts +27 -0
- package/projects/facecog-liveness-verification-test/src/app/home/home-routing.module.ts +16 -0
- package/projects/facecog-liveness-verification-test/src/app/home/home.module.ts +19 -0
- package/projects/facecog-liveness-verification-test/src/app/home/home.page.html +39 -0
- package/projects/facecog-liveness-verification-test/src/app/home/home.page.scss +97 -0
- package/projects/facecog-liveness-verification-test/src/app/home/home.page.spec.ts +24 -0
- package/projects/facecog-liveness-verification-test/src/app/home/home.page.ts +92 -0
- package/projects/facecog-liveness-verification-test/src/app/home/verification-modal.component.ts +106 -0
- package/projects/facecog-liveness-verification-test/src/assets/fonts/gilroy/Gilroy-Bold_0.ttf +0 -0
- package/projects/facecog-liveness-verification-test/src/assets/fonts/gilroy/Gilroy-Medium_0.ttf +0 -0
- package/projects/facecog-liveness-verification-test/src/assets/fonts/gilroy/Gilroy-Regular_0.ttf +0 -0
- package/projects/facecog-liveness-verification-test/src/assets/fonts/gilroy/Gilroy-SemiBold_0.ttf +0 -0
- package/projects/facecog-liveness-verification-test/src/assets/fonts/gilroy/Gilroy-Thin_0.ttf +0 -0
- package/projects/facecog-liveness-verification-test/src/assets/icon/favicon.png +0 -0
- package/projects/facecog-liveness-verification-test/src/assets/images/poses/Five_Fingers_Left.jpg +0 -0
- package/projects/facecog-liveness-verification-test/src/assets/images/poses/Left_Palm.jpg +0 -0
- package/projects/facecog-liveness-verification-test/src/assets/images/poses/Ok_Sign_Right.jpg +0 -0
- package/projects/facecog-liveness-verification-test/src/assets/images/poses/Peace_Sign_Left.jpg +0 -0
- package/projects/facecog-liveness-verification-test/src/assets/images/poses/README.md +77 -0
- package/projects/facecog-liveness-verification-test/src/assets/images/poses/Right_Palm.jpg +0 -0
- package/projects/facecog-liveness-verification-test/src/assets/images/poses/Speak_Phrase.jpg +0 -0
- package/projects/facecog-liveness-verification-test/src/assets/images/poses/Three_Fingers_Right.jpg +0 -0
- package/projects/facecog-liveness-verification-test/src/assets/images/poses/Thumbs_Up_Left.jpg +0 -0
- package/projects/facecog-liveness-verification-test/src/assets/images/poses/Thumbs_Up_Right.jpg +0 -0
- package/projects/facecog-liveness-verification-test/src/assets/images/poses/Wave_Right.jpg +0 -0
- package/projects/facecog-liveness-verification-test/src/assets/images/poses/blink.jpeg +0 -0
- package/projects/facecog-liveness-verification-test/src/assets/images/poses/blink_twice.jpeg +0 -0
- package/projects/facecog-liveness-verification-test/src/assets/images/poses/center_face.png +0 -0
- package/projects/facecog-liveness-verification-test/src/assets/images/poses/clap.jpeg +0 -0
- package/projects/facecog-liveness-verification-test/src/assets/images/poses/cover_mouth.png +0 -0
- package/projects/facecog-liveness-verification-test/src/assets/images/poses/cover_right_eye.png +0 -0
- package/projects/facecog-liveness-verification-test/src/assets/images/poses/cross_arms.png +0 -0
- package/projects/facecog-liveness-verification-test/src/assets/images/poses/face_straight.png +0 -0
- package/projects/facecog-liveness-verification-test/src/assets/images/poses/follow_dot.png +0 -0
- package/projects/facecog-liveness-verification-test/src/assets/images/poses/look_down.png +0 -0
- package/projects/facecog-liveness-verification-test/src/assets/images/poses/look_up.png +0 -0
- package/projects/facecog-liveness-verification-test/src/assets/images/poses/move_closer.png +0 -0
- package/projects/facecog-liveness-verification-test/src/assets/images/poses/nod.png +0 -0
- package/projects/facecog-liveness-verification-test/src/assets/images/poses/open_mouth.png +0 -0
- package/projects/facecog-liveness-verification-test/src/assets/images/poses/raise_eyebrow.png +0 -0
- package/projects/facecog-liveness-verification-test/src/assets/images/poses/rotate_face.jpeg +0 -0
- package/projects/facecog-liveness-verification-test/src/assets/images/poses/shake_head.jpeg +0 -0
- package/projects/facecog-liveness-verification-test/src/assets/images/poses/smile.png +0 -0
- package/projects/facecog-liveness-verification-test/src/assets/images/poses/tilt_left.png +0 -0
- package/projects/facecog-liveness-verification-test/src/assets/images/poses/tilt_right.png +0 -0
- package/projects/facecog-liveness-verification-test/src/assets/images/poses/touch_chin_left.jpg +0 -0
- package/projects/facecog-liveness-verification-test/src/assets/images/poses/touch_left_cheek.jpeg +0 -0
- package/projects/facecog-liveness-verification-test/src/assets/images/poses/touch_nose_right.png +0 -0
- package/projects/facecog-liveness-verification-test/src/assets/images/poses/touch_right_cheek.jpeg +0 -0
- package/projects/facecog-liveness-verification-test/src/assets/images/poses/turn_left.png +0 -0
- package/projects/facecog-liveness-verification-test/src/assets/images/poses/turn_right.png +0 -0
- package/projects/facecog-liveness-verification-test/src/assets/images/poses/wink.jpeg +0 -0
- package/projects/facecog-liveness-verification-test/src/assets/images/reference-pose.jpg +0 -0
- package/projects/facecog-liveness-verification-test/src/assets/shapes.svg +1 -0
- package/projects/facecog-liveness-verification-test/src/environments/environment.prod.ts +4 -0
- package/projects/facecog-liveness-verification-test/src/environments/environment.ts +17 -0
- package/projects/facecog-liveness-verification-test/src/global.scss +288 -0
- package/projects/facecog-liveness-verification-test/src/index.html +31 -0
- package/projects/facecog-liveness-verification-test/src/main.ts +6 -0
- package/projects/facecog-liveness-verification-test/src/polyfills.ts +55 -0
- package/projects/facecog-liveness-verification-test/src/theme/nextsapien-theme.scss +174 -0
- package/projects/facecog-liveness-verification-test/src/theme/variables.scss +2 -0
- package/projects/facecog-liveness-verification-test/src/zone-flags.ts +6 -0
- package/projects/facecog-liveness-verification-test/tsconfig.app.json +15 -0
- package/projects/facecog-liveness-verification-test/tsconfig.spec.json +14 -0
- package/setup-jest.ts +118 -0
- package/tsconfig.json +41 -0
- package/tsconfig.spec.json +15 -0
- package/vercel.json +24 -0
package/projects/facecog-liveness-verification/src/lib/services/liveness-orchestrator.service.ts
ADDED
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
import { Injectable, Inject, Optional } from '@angular/core';
|
|
2
|
+
import { Observable } from 'rxjs';
|
|
3
|
+
import { LivenessConfigService } from './liveness-config.service';
|
|
4
|
+
import { MockBackendService } from './backends/mock-backend.service';
|
|
5
|
+
import { RekognitionAnalysisBackendService } from './backends/rekognition-analysis-backend.service';
|
|
6
|
+
import { OpenPoseBackendService } from './backends/openpose-backend.service';
|
|
7
|
+
import { FaceTecBackendService } from './backends/facetec-backend.service';
|
|
8
|
+
import { AzureBackendService } from './backends/azure-backend.service';
|
|
9
|
+
import { IBackendAdapter } from '../interfaces/backend-adapter.interface';
|
|
10
|
+
import { IBackendHttpClient, BACKEND_HTTP_CLIENT } from '../interfaces/backend-http-client.interface';
|
|
11
|
+
import { BackendResponse } from '../interfaces/backend-response.interface';
|
|
12
|
+
import { MultiBackendAnalyzeResponse } from '../interfaces/multi-backend-analyze-response.interface';
|
|
13
|
+
import { LivenessBackend } from '../types/liveness-backend.type';
|
|
14
|
+
|
|
15
|
+
@Injectable({
|
|
16
|
+
providedIn: 'root'
|
|
17
|
+
})
|
|
18
|
+
export class LivenessOrchestratorService {
|
|
19
|
+
private backends: Map<LivenessBackend, IBackendAdapter> = new Map();
|
|
20
|
+
public multiBackendResult: MultiBackendAnalyzeResponse | null = null;
|
|
21
|
+
|
|
22
|
+
constructor(
|
|
23
|
+
private configService: LivenessConfigService,
|
|
24
|
+
private mockBackend: MockBackendService,
|
|
25
|
+
private rekognitionBackend: RekognitionAnalysisBackendService,
|
|
26
|
+
private openposeBackend: OpenPoseBackendService,
|
|
27
|
+
private facetecBackend: FaceTecBackendService,
|
|
28
|
+
private azureBackend: AzureBackendService,
|
|
29
|
+
@Optional() @Inject(BACKEND_HTTP_CLIENT) private backendClient: IBackendHttpClient | null
|
|
30
|
+
) {
|
|
31
|
+
this.initializeBackends();
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
private initializeBackends(): void {
|
|
35
|
+
this.backends.set('mock', this.mockBackend);
|
|
36
|
+
this.backends.set('amazon', this.rekognitionBackend);
|
|
37
|
+
this.backends.set('openpose', this.openposeBackend);
|
|
38
|
+
this.backends.set('facetec', this.facetecBackend);
|
|
39
|
+
this.backends.set('azure', this.azureBackend);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Verify liveness using multi-backend parallel analysis
|
|
44
|
+
* Uses configured backends from config (defaults to all if not specified)
|
|
45
|
+
*/
|
|
46
|
+
verifyLiveness(imageData: string, videoBlob?: Blob): Observable<BackendResponse> {
|
|
47
|
+
const config = this.configService.getConfig();
|
|
48
|
+
const configuredBackends = config.backends || ['amazon', 'openpose', 'facetec'];
|
|
49
|
+
console.log('[Frontend Orchestrator] Configured backends:', configuredBackends);
|
|
50
|
+
|
|
51
|
+
// If no backend HTTP client configured, use mock
|
|
52
|
+
if (!this.backendClient) {
|
|
53
|
+
console.warn('[Frontend Orchestrator] No backend HTTP client configured, using mock');
|
|
54
|
+
return this.mockBackend.verifyLiveness(imageData, videoBlob);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// Use selected backends from config
|
|
58
|
+
console.log('[Frontend Orchestrator] Using multi-backend parallel analysis with backends:', configuredBackends);
|
|
59
|
+
return this.verifyWithSelectedBackends(imageData, videoBlob, configuredBackends as LivenessBackend[]);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Verify liveness using selected backends in parallel with voting system
|
|
64
|
+
*/
|
|
65
|
+
private verifyWithSelectedBackends(imageData: string, videoBlob?: Blob, backends?: LivenessBackend[]): Observable<BackendResponse> {
|
|
66
|
+
return new Observable(observer => {
|
|
67
|
+
if (!this.backendClient) {
|
|
68
|
+
observer.error(new Error('Backend HTTP client not configured'));
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const selectedBackends = backends || ['amazon', 'openpose', 'facetec'] as LivenessBackend[];
|
|
73
|
+
|
|
74
|
+
// First create a session
|
|
75
|
+
this.backendClient.createSession('amazon').subscribe({
|
|
76
|
+
next: (sessionResponse) => {
|
|
77
|
+
const sessionId = sessionResponse.sessionId;
|
|
78
|
+
|
|
79
|
+
// Call the analyze-selected endpoint with configured backends
|
|
80
|
+
this.backendClient!.analyzeWithSelectedBackends(sessionId, imageData, selectedBackends).subscribe({
|
|
81
|
+
next: (multiResult: MultiBackendAnalyzeResponse) => {
|
|
82
|
+
// Store the multi-backend result
|
|
83
|
+
this.multiBackendResult = multiResult;
|
|
84
|
+
|
|
85
|
+
// Return the consensus result
|
|
86
|
+
const response: BackendResponse = {
|
|
87
|
+
isLive: multiResult.consensus.isLive,
|
|
88
|
+
confidence: multiResult.consensus.confidence,
|
|
89
|
+
details: multiResult
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
observer.next(response);
|
|
93
|
+
observer.complete();
|
|
94
|
+
},
|
|
95
|
+
error: (error: any) => {
|
|
96
|
+
console.error('Multi-backend analysis failed:', error);
|
|
97
|
+
observer.error(error);
|
|
98
|
+
}
|
|
99
|
+
});
|
|
100
|
+
},
|
|
101
|
+
error: (error: any) => {
|
|
102
|
+
console.error('Failed to create session:', error);
|
|
103
|
+
observer.error(error);
|
|
104
|
+
}
|
|
105
|
+
});
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Verify liveness using all backends in parallel with voting system
|
|
111
|
+
* @deprecated Use verifyLiveness with configured backends instead
|
|
112
|
+
*/
|
|
113
|
+
private verifyWithAllBackends(imageData: string, videoBlob?: Blob): Observable<BackendResponse> {
|
|
114
|
+
return this.verifyWithSelectedBackends(imageData, videoBlob, ['amazon', 'openpose', 'facetec']);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Upload video to S3
|
|
119
|
+
*/
|
|
120
|
+
uploadVideoToS3(videoBlob: Blob, sessionId: string): Observable<{ success: boolean; videoUrl: string; sessionId: string }> {
|
|
121
|
+
if (!this.backendClient) {
|
|
122
|
+
return new Observable(observer => {
|
|
123
|
+
observer.error(new Error('Backend HTTP client not configured'));
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
return this.backendClient.uploadVideo(videoBlob, sessionId);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Upload a base64 image to S3 (fallback when video recording is unavailable)
|
|
132
|
+
*/
|
|
133
|
+
uploadBase64ImageToS3(base64Image: string, sessionId: string): Observable<{ success: boolean; videoUrl: string; sessionId: string }> {
|
|
134
|
+
if (!this.backendClient) {
|
|
135
|
+
return new Observable(observer => {
|
|
136
|
+
observer.error(new Error('Backend HTTP client not configured'));
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
return this.backendClient.uploadBase64Image(base64Image, sessionId);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Get a specific backend adapter by name
|
|
145
|
+
*/
|
|
146
|
+
getBackend(name: LivenessBackend): IBackendAdapter | undefined {
|
|
147
|
+
return this.backends.get(name);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Get all available backends
|
|
152
|
+
*/
|
|
153
|
+
getAvailableBackends(): LivenessBackend[] {
|
|
154
|
+
const available: LivenessBackend[] = [];
|
|
155
|
+
this.backends.forEach((backend, name) => {
|
|
156
|
+
if (backend.isAvailable()) {
|
|
157
|
+
available.push(name);
|
|
158
|
+
}
|
|
159
|
+
});
|
|
160
|
+
return available;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
@@ -0,0 +1,315 @@
|
|
|
1
|
+
import { Injectable } from '@angular/core';
|
|
2
|
+
import { HandLandmarker, FilesetResolver, HandLandmarkerResult } from '@mediapipe/tasks-vision';
|
|
3
|
+
|
|
4
|
+
export interface HandGestureResult {
|
|
5
|
+
gesture: string;
|
|
6
|
+
confidence: number;
|
|
7
|
+
handedness: 'Left' | 'Right';
|
|
8
|
+
landmarks: any[];
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
@Injectable({
|
|
12
|
+
providedIn: 'root'
|
|
13
|
+
})
|
|
14
|
+
export class HandGestureDetectionService {
|
|
15
|
+
private handLandmarker: HandLandmarker | null = null;
|
|
16
|
+
private isInitialized = false;
|
|
17
|
+
|
|
18
|
+
constructor() {}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Initialize MediaPipe Hand Landmarker
|
|
22
|
+
*/
|
|
23
|
+
async loadModel(): Promise<void> {
|
|
24
|
+
if (this.isInitialized) {
|
|
25
|
+
console.log('[MediaPipe Hands] Model already loaded');
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
try {
|
|
30
|
+
console.log('[MediaPipe Hands] Loading Hand Landmarker model...');
|
|
31
|
+
|
|
32
|
+
const vision = await FilesetResolver.forVisionTasks(
|
|
33
|
+
'https://cdn.jsdelivr.net/npm/@mediapipe/tasks-vision@latest/wasm'
|
|
34
|
+
);
|
|
35
|
+
|
|
36
|
+
// Try GPU first, fallback to CPU for Safari compatibility
|
|
37
|
+
try {
|
|
38
|
+
this.handLandmarker = await HandLandmarker.createFromOptions(vision, {
|
|
39
|
+
baseOptions: {
|
|
40
|
+
modelAssetPath: 'https://storage.googleapis.com/mediapipe-models/hand_landmarker/hand_landmarker/float16/1/hand_landmarker.task',
|
|
41
|
+
delegate: 'GPU'
|
|
42
|
+
},
|
|
43
|
+
runningMode: 'VIDEO',
|
|
44
|
+
numHands: 2,
|
|
45
|
+
minHandDetectionConfidence: 0.5,
|
|
46
|
+
minHandPresenceConfidence: 0.5,
|
|
47
|
+
minTrackingConfidence: 0.5
|
|
48
|
+
});
|
|
49
|
+
console.log('[MediaPipe Hands] Hand Landmarker loaded with GPU delegate');
|
|
50
|
+
} catch (gpuError) {
|
|
51
|
+
console.warn('[MediaPipe Hands] GPU delegate failed, trying CPU for Safari compatibility:', gpuError);
|
|
52
|
+
this.handLandmarker = await HandLandmarker.createFromOptions(vision, {
|
|
53
|
+
baseOptions: {
|
|
54
|
+
modelAssetPath: 'https://storage.googleapis.com/mediapipe-models/hand_landmarker/hand_landmarker/float16/1/hand_landmarker.task',
|
|
55
|
+
delegate: 'CPU'
|
|
56
|
+
},
|
|
57
|
+
runningMode: 'VIDEO',
|
|
58
|
+
numHands: 2,
|
|
59
|
+
minHandDetectionConfidence: 0.5,
|
|
60
|
+
minHandPresenceConfidence: 0.5,
|
|
61
|
+
minTrackingConfidence: 0.5
|
|
62
|
+
});
|
|
63
|
+
console.log('[MediaPipe Hands] Hand Landmarker loaded with CPU delegate (Safari fallback)');
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
this.isInitialized = true;
|
|
67
|
+
console.log('[MediaPipe Hands] Hand Landmarker loaded successfully');
|
|
68
|
+
} catch (error) {
|
|
69
|
+
console.error('[MediaPipe Hands] Failed to load model:', error);
|
|
70
|
+
throw new Error('Failed to load hand detection model');
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Detect hands in video frame
|
|
76
|
+
*/
|
|
77
|
+
async detectHands(videoElement: HTMLVideoElement): Promise<HandLandmarkerResult | null> {
|
|
78
|
+
try {
|
|
79
|
+
if (!this.isInitialized || !this.handLandmarker) {
|
|
80
|
+
console.warn('[MediaPipe Hands] Model not loaded, attempting to load...');
|
|
81
|
+
await this.loadModel();
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const timestamp = performance.now();
|
|
85
|
+
const result = this.handLandmarker!.detectForVideo(videoElement, timestamp);
|
|
86
|
+
|
|
87
|
+
return result && result.landmarks && result.landmarks.length > 0 ? result : null;
|
|
88
|
+
} catch (error) {
|
|
89
|
+
console.error('[MediaPipe Hands] Hand detection error:', error);
|
|
90
|
+
return null;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Detect specific hand gesture from landmarks
|
|
96
|
+
*/
|
|
97
|
+
detectGesture(result: HandLandmarkerResult): HandGestureResult[] {
|
|
98
|
+
const gestures: HandGestureResult[] = [];
|
|
99
|
+
|
|
100
|
+
if (!result.landmarks || result.landmarks.length === 0) {
|
|
101
|
+
return gestures;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// Process each detected hand
|
|
105
|
+
for (let i = 0; i < result.landmarks.length; i++) {
|
|
106
|
+
const landmarks = result.landmarks[i];
|
|
107
|
+
const handedness = result.handedness?.[i]?.[0]?.categoryName || 'Unknown';
|
|
108
|
+
|
|
109
|
+
console.log(`[MediaPipe Hands] Raw handedness from MediaPipe: "${handedness}"`);
|
|
110
|
+
|
|
111
|
+
// Detect gesture based on finger positions
|
|
112
|
+
const gesture = this.classifyGesture(landmarks);
|
|
113
|
+
|
|
114
|
+
gestures.push({
|
|
115
|
+
gesture: gesture.name,
|
|
116
|
+
confidence: gesture.confidence,
|
|
117
|
+
handedness: handedness as 'Left' | 'Right',
|
|
118
|
+
landmarks: landmarks
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
console.log(`[MediaPipe Hands] Classified gesture: ${gesture.name}, Final handedness: ${handedness}`);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
return gestures;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Classify gesture based on hand landmarks
|
|
129
|
+
*/
|
|
130
|
+
private classifyGesture(landmarks: any[]): { name: string; confidence: number } {
|
|
131
|
+
// Get finger states (extended or closed)
|
|
132
|
+
const fingers = {
|
|
133
|
+
thumb: this.isThumbExtended(landmarks),
|
|
134
|
+
index: this.isFingerExtended(landmarks, 'index'),
|
|
135
|
+
middle: this.isFingerExtended(landmarks, 'middle'),
|
|
136
|
+
ring: this.isFingerExtended(landmarks, 'ring'),
|
|
137
|
+
pinky: this.isFingerExtended(landmarks, 'pinky')
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
const extendedCount = Object.values(fingers).filter(Boolean).length;
|
|
141
|
+
|
|
142
|
+
// Debug logging
|
|
143
|
+
console.log(`[Gesture Classification] Extended fingers: thumb=${fingers.thumb}, index=${fingers.index}, middle=${fingers.middle}, ring=${fingers.ring}, pinky=${fingers.pinky}, total=${extendedCount}`);
|
|
144
|
+
|
|
145
|
+
// Classify based on finger patterns
|
|
146
|
+
// Priority order matters! Check specific patterns before general counts.
|
|
147
|
+
|
|
148
|
+
// Thumbs Up: Only thumb extended, all others closed
|
|
149
|
+
// MUST check this FIRST with strictest conditions to avoid false positives
|
|
150
|
+
if (fingers.thumb && !fingers.index && !fingers.middle && !fingers.ring && !fingers.pinky) {
|
|
151
|
+
console.log('[Gesture Classification] Detected: thumbs_up');
|
|
152
|
+
return { name: 'thumbs_up', confidence: 0.9 };
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// Fist: All fingers closed (no fingers extended)
|
|
156
|
+
// Check early to distinguish from other gestures
|
|
157
|
+
if (extendedCount === 0) {
|
|
158
|
+
console.log('[Gesture Classification] Detected: fist');
|
|
159
|
+
return { name: 'fist', confidence: 0.9 };
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
// OK Sign: Thumb and index tips close together (forming circle), other fingers extended
|
|
163
|
+
// MUST check BEFORE peace sign to avoid conflicts
|
|
164
|
+
if (this.isOKSign(landmarks, fingers)) {
|
|
165
|
+
console.log('[Gesture Classification] Detected: ok');
|
|
166
|
+
return { name: 'ok', confidence: 0.85 };
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
// Peace Sign: Index and middle extended, ring and pinky closed
|
|
170
|
+
// More lenient: allow thumb to be slightly extended
|
|
171
|
+
if (fingers.index && fingers.middle && !fingers.ring && !fingers.pinky) {
|
|
172
|
+
console.log('[Gesture Classification] Detected: peace');
|
|
173
|
+
return { name: 'peace', confidence: 0.9 };
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// Three Fingers: Index + Middle + Ring extended (typical three finger gesture)
|
|
177
|
+
// Check this BEFORE palm to avoid confusion
|
|
178
|
+
if (fingers.index && fingers.middle && fingers.ring && !fingers.pinky) {
|
|
179
|
+
console.log('[Gesture Classification] Detected: three (index+middle+ring)');
|
|
180
|
+
return { name: 'three', confidence: 0.9 };
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
// Palm/Open Hand: All 5 fingers extended OR all 4 non-thumb fingers extended
|
|
184
|
+
// Be strict: exactly 5 fingers OR exactly 4 fingers (index, middle, ring, pinky all up)
|
|
185
|
+
const allFingersUp = extendedCount === 5;
|
|
186
|
+
const fourFingersUp = !fingers.thumb && fingers.index && fingers.middle && fingers.ring && fingers.pinky;
|
|
187
|
+
|
|
188
|
+
if (allFingersUp || fourFingersUp) {
|
|
189
|
+
console.log('[Gesture Classification] Detected: palm');
|
|
190
|
+
return { name: 'palm', confidence: 0.9 };
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
// Three fingers (any combination of 3 extended fingers, but not the specific patterns above)
|
|
194
|
+
if (extendedCount === 3) {
|
|
195
|
+
console.log('[Gesture Classification] Detected: three (generic 3 fingers)');
|
|
196
|
+
return { name: 'three', confidence: 0.8 };
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
// If we get here, it's an unknown gesture (1, 2, or 4+ fingers in unexpected patterns)
|
|
200
|
+
console.log('[Gesture Classification] Detected: unknown');
|
|
201
|
+
return { name: 'unknown', confidence: 0.5 };
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
/**
|
|
205
|
+
* Check if thumb is extended
|
|
206
|
+
*/
|
|
207
|
+
private isThumbExtended(landmarks: any[]): boolean {
|
|
208
|
+
// Thumb: landmarks 1-4
|
|
209
|
+
// Extended if tip (4) is farther from wrist (0) than base (2)
|
|
210
|
+
const wrist = landmarks[0];
|
|
211
|
+
const thumbBase = landmarks[2];
|
|
212
|
+
const thumbTip = landmarks[4];
|
|
213
|
+
|
|
214
|
+
const baseDist = this.distance(wrist, thumbBase);
|
|
215
|
+
const tipDist = this.distance(wrist, thumbTip);
|
|
216
|
+
|
|
217
|
+
// Balanced threshold: strict enough to avoid false positives, lenient enough for detection
|
|
218
|
+
const isExtended = tipDist > baseDist * 1.25;
|
|
219
|
+
|
|
220
|
+
return isExtended;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
/**
|
|
224
|
+
* Check if a finger is extended
|
|
225
|
+
*/
|
|
226
|
+
private isFingerExtended(landmarks: any[], finger: 'index' | 'middle' | 'ring' | 'pinky'): boolean {
|
|
227
|
+
const fingerIndices = {
|
|
228
|
+
index: { base: 5, tip: 8, mid: 6 },
|
|
229
|
+
middle: { base: 9, tip: 12, mid: 10 },
|
|
230
|
+
ring: { base: 13, tip: 16, mid: 14 },
|
|
231
|
+
pinky: { base: 17, tip: 20, mid: 18 }
|
|
232
|
+
};
|
|
233
|
+
|
|
234
|
+
const indices = fingerIndices[finger];
|
|
235
|
+
const base = landmarks[indices.base];
|
|
236
|
+
const mid = landmarks[indices.mid];
|
|
237
|
+
const tip = landmarks[indices.tip];
|
|
238
|
+
const wrist = landmarks[0];
|
|
239
|
+
|
|
240
|
+
// Extended if tip is farther from wrist than base
|
|
241
|
+
const baseDist = this.distance(wrist, base);
|
|
242
|
+
const tipDist = this.distance(wrist, tip);
|
|
243
|
+
const midDist = this.distance(wrist, mid);
|
|
244
|
+
|
|
245
|
+
// Balanced thresholds for better accuracy
|
|
246
|
+
// Primary check: tip should be significantly farther than base
|
|
247
|
+
const distanceCheck = tipDist > baseDist * 1.12;
|
|
248
|
+
|
|
249
|
+
// Secondary check: middle joint should be at least slightly away from base
|
|
250
|
+
// This is more lenient to allow natural hand variations
|
|
251
|
+
const midCheck = midDist > baseDist * 1.02;
|
|
252
|
+
|
|
253
|
+
const isExtended = distanceCheck && midCheck;
|
|
254
|
+
|
|
255
|
+
return isExtended;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
/**
|
|
259
|
+
* Check if hand is making OK sign
|
|
260
|
+
* OK sign = thumb and index tips touching (forming circle) + other 3 fingers extended
|
|
261
|
+
*/
|
|
262
|
+
private isOKSign(landmarks: any[], fingers: any): boolean {
|
|
263
|
+
const thumbTip = landmarks[4];
|
|
264
|
+
const indexTip = landmarks[8];
|
|
265
|
+
|
|
266
|
+
// First check: thumb and index tips must be close together (forming the circle)
|
|
267
|
+
const dist = this.distance(thumbTip, indexTip);
|
|
268
|
+
const tipsClose = dist < 0.05; // Threshold for normalized coordinates
|
|
269
|
+
|
|
270
|
+
if (!tipsClose) {
|
|
271
|
+
return false;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
// Second check: middle, ring, and pinky must be EXTENDED (not closed like thumbs up)
|
|
275
|
+
// At least 2 of the 3 fingers should be extended for a valid OK sign
|
|
276
|
+
const otherFingersExtended = [fingers.middle, fingers.ring, fingers.pinky].filter(Boolean).length;
|
|
277
|
+
|
|
278
|
+
// OK sign requires other fingers to be up (at least 2 of them)
|
|
279
|
+
// This prevents thumbs up (all fingers closed) from being detected as OK
|
|
280
|
+
const isOK = tipsClose && otherFingersExtended >= 2;
|
|
281
|
+
|
|
282
|
+
console.log(`[OK Sign Check] Tips close: ${tipsClose}, Distance: ${dist.toFixed(4)}, Other fingers extended: ${otherFingersExtended}/3, Result: ${isOK}`);
|
|
283
|
+
|
|
284
|
+
return isOK;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
/**
|
|
288
|
+
* Calculate Euclidean distance between two landmarks
|
|
289
|
+
*/
|
|
290
|
+
private distance(p1: any, p2: any): number {
|
|
291
|
+
const dx = p1.x - p2.x;
|
|
292
|
+
const dy = p1.y - p2.y;
|
|
293
|
+
const dz = (p1.z || 0) - (p2.z || 0);
|
|
294
|
+
return Math.sqrt(dx * dx + dy * dy + dz * dz);
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
/**
|
|
298
|
+
* Compare detected gesture with expected gesture
|
|
299
|
+
*/
|
|
300
|
+
matchGesture(detected: string, expected: string): boolean {
|
|
301
|
+
return detected.toLowerCase() === expected.toLowerCase();
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
/**
|
|
305
|
+
* Cleanup resources
|
|
306
|
+
*/
|
|
307
|
+
cleanup(): void {
|
|
308
|
+
if (this.handLandmarker) {
|
|
309
|
+
this.handLandmarker.close();
|
|
310
|
+
this.handLandmarker = null;
|
|
311
|
+
this.isInitialized = false;
|
|
312
|
+
console.log('[MediaPipe Hands] Hand Landmarker disposed');
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { OpenposeService, PoseKeypoints } from './openpose.service';
|
|
2
|
+
export { HandGestureDetectionService, HandGestureResult } from './hand-gesture-detection.service';
|
|
3
|
+
export { ReferencePoseService, ReferencePose } from './reference-pose.service';
|
|
4
|
+
export { PoseComparisonService, PoseComparisonResult } from './pose-comparison.service';
|
|
5
|
+
export { PoseMatchingService } from './pose-matching.service';
|