|
| 1 | +# openFaceCamera |
| 2 | + |
| 3 | +## Overview |
| 4 | + |
| 5 | +The `ensemble_face_camera` module adds real-time face detection to the Ensemble framework. |
| 6 | +It is extracted from the original `ensemble_camera` package and focused on face-based capture workflows across Mobile and Web. |
| 7 | + |
| 8 | +## What It Does |
| 9 | + |
| 10 | +- Real-time face detection on Mobile and Web |
| 11 | +- Auto-capture when alignment conditions are met |
| 12 | +- Configurable detection options (yaw, tilt, thresholds, performance mode) |
| 13 | +- Seamless integration with Ensemble via `openFaceCamera` |
| 14 | +- Direct Flutter widget support |
| 15 | + |
| 16 | +## Installation |
| 17 | + |
| 18 | +Add this to `pubspec.yaml`: |
| 19 | + |
| 20 | +```yaml |
| 21 | +dependencies: |
| 22 | + ensemble_face_camera: |
| 23 | + git: |
| 24 | + url: https://github.com/EnsembleUI/ensemble.git |
| 25 | + ref: main |
| 26 | + path: modules/face_camera |
| 27 | +``` |
| 28 | +
|
| 29 | +## Required Setup |
| 30 | +
|
| 31 | +Register the manager during app initialization: |
| 32 | +
|
| 33 | +```dart |
| 34 | +import 'package:ensemble_face_camera/ensemble_face_camera.dart'; |
| 35 | + |
| 36 | +GetIt.I.registerSingleton<FaceCameraManager>( |
| 37 | + FaceCameraManagerImpl(), |
| 38 | +); |
| 39 | +``` |
| 40 | + |
| 41 | +Without this registration, the `openFaceCamera` action will not work. |
| 42 | + |
| 43 | +## Action |
| 44 | + |
| 45 | +Use `openFaceCamera` in YAML. |
| 46 | + |
| 47 | +### Properties |
| 48 | + |
| 49 | +| Property | Type | Description | |
| 50 | +| :------------ | :----- | :-------------------------------------------------------------------------------- | |
| 51 | +| id | string | Camera ID used to bind captured results (for example `${myFaceCamera.files}`). | |
| 52 | +| onCapture | action | Executes when an image is captured. Captured files are available via `event.data.files`. | |
| 53 | +| onError | action | Executes on error. Error message is available via `event.error`. | |
| 54 | +| options | object | Additional configuration for camera and detection. | |
| 55 | + |
| 56 | +### options |
| 57 | + |
| 58 | +| Property | Type | Description | |
| 59 | +| :------------------------ | :------ | :------------------------------------------------------------------------------------------------ | |
| 60 | +| initialCamera | string | Which lens to start with: `front` (default), `back` | |
| 61 | +| message | string | Message shown above camera preview | |
| 62 | +| messageStyle | object | Text style for `message` | |
| 63 | +| showControls | boolean | Show/hide all camera controls. Default `true` | |
| 64 | +| showCaptureControl | boolean | Show/hide capture button. Default `true` | |
| 65 | +| showFlashControl | boolean | Show/hide flash control. Default `true` | |
| 66 | +| showCameraLensControl | boolean | Show/hide camera switch control. Default `true` | |
| 67 | +| showStatusMessage | boolean | Show/hide face detection status text. Default `true` | |
| 68 | +| indicatorShape | string | Face indicator shape: `circle`, `square` | |
| 69 | +| autoDisableCaptureControl | boolean | Disable capture while no valid face is detected. Default `false` | |
| 70 | +| autoCapture | boolean | Automatically capture when face qualifies. Default `false` | |
| 71 | +| imageResolution | string | Capture resolution: `low`, `medium`, `high` (default), `veryHigh`, `ultraHigh`, `max` | |
| 72 | +| defaultFlashMode | string | Initial flash mode: `off` (default), `auto`, `always` | |
| 73 | +| orientation | string | Camera orientation: `portraitUp` (default), `portraitDown`, `landscapeLeft`, `landscapeRight` | |
| 74 | +| performanceMode | string | Face detector mode: `fast` (default), `accurate` | |
| 75 | +| accuracyConfig | object | Fine-grained face detection thresholds. Web only. See `options.accuracyConfig` below. | |
| 76 | + |
| 77 | +### options.accuracyConfig |
| 78 | + |
| 79 | +> Note: `accuracyConfig` is supported only on web. |
| 80 | +
|
| 81 | +The following properties are verified in code as parsed and used by web face detection: |
| 82 | + |
| 83 | +| Property | Type | Default | Description | |
| 84 | +| :------------------------- | :----- | :------ | :--------------------------------------------------------------------------- | |
| 85 | +| detectionThreshold | number | 0.6 | Minimum confidence score for a valid face detection | |
| 86 | +| intersectionRatioThreshold | number | 0.9 | Minimum overlap ratio between detected face and expected region | |
| 87 | +| extraHeightFactor | number | 0.3 | Additional height factor for face bounding box | |
| 88 | +| inputSize | number | 224 | Input image size used by detector | |
| 89 | +| landmarkRatio | number | 0.95 | Minimum landmark alignment/visibility ratio | |
| 90 | +| frameMargin | number | 0.05 | Margin ratio to ensure face is not too close to frame edges | |
| 91 | +| tiltAngleThreshold | number | 6 | Maximum allowed tilt angle in degrees | |
| 92 | +| horizontalCenterTolerance | number | 0.08 | Allowed horizontal centering tolerance | |
| 93 | +| earThreshold | number | 0.25 | Eye aspect ratio threshold for open-eye validation | |
| 94 | +| minFaceWidthRatio | number | 0.18 | Minimum face width ratio relative to frame | |
| 95 | +| maxFaceWidthRatio | number | 0.82 | Maximum face width ratio relative to frame | |
| 96 | +| qualityPassThreshold | number | 0.8 | Minimum quality score required to pass | |
| 97 | +| yawLowerThreshold | number | 0.85 | Lower yaw ratio bound | |
| 98 | +| yawUpperThreshold | number | 1.15 | Upper yaw ratio bound | |
| 99 | + |
| 100 | +Alias keys also supported by parser: |
| 101 | + |
| 102 | +- `threshold` -> `detectionThreshold` |
| 103 | +- `yaw` -> `yawUpperThreshold` |
| 104 | +- `tilt` -> `tiltAngleThreshold` |
| 105 | +- `minFaceSize` -> `minFaceWidthRatio` |
| 106 | + |
| 107 | +## Usage Examples |
| 108 | + |
| 109 | +### 1. Basic capture and preview |
| 110 | + |
| 111 | +Open the face camera, bind the result to an ID, and preview the captured image. |
| 112 | + |
| 113 | +```yaml |
| 114 | +View: |
| 115 | + header: |
| 116 | + title: "Action: openFaceCamera" |
| 117 | + styles: |
| 118 | + scrollableView: true |
| 119 | + body: |
| 120 | + Column: |
| 121 | + styles: { gap: 16, padding: 24 } |
| 122 | + children: |
| 123 | + - Button: |
| 124 | + label: Open Face Camera |
| 125 | + onTap: |
| 126 | + openFaceCamera: |
| 127 | + id: myFaceCamera |
| 128 | + |
| 129 | + - Conditional: |
| 130 | + conditions: |
| 131 | + - if: ${myFaceCamera.files.length > 0} |
| 132 | + Image: |
| 133 | + source: ${myFaceCamera.files[0].path} |
| 134 | +``` |
| 135 | +
|
| 136 | +### 2. Capture with common options |
| 137 | +
|
| 138 | +Configure the most common face camera options and log the result when a capture succeeds. |
| 139 | +
|
| 140 | +```yaml |
| 141 | +- Button: |
| 142 | + label: Open Face Camera with Options |
| 143 | + onTap: |
| 144 | + openFaceCamera: |
| 145 | + id: myFaceCamera |
| 146 | + options: |
| 147 | + initialCamera: front |
| 148 | + performanceMode: fast |
| 149 | + imageResolution: high |
| 150 | + defaultFlashMode: off |
| 151 | + orientation: portraitUp |
| 152 | + message: "Align your face" |
| 153 | + messageStyle: |
| 154 | + color: 0xFFFFFFFF |
| 155 | + indicatorShape: circle |
| 156 | + showStatusMessage: true |
| 157 | + showControls: true |
| 158 | + showCaptureControl: true |
| 159 | + showFlashControl: true |
| 160 | + showCameraLensControl: true |
| 161 | + onCapture: |
| 162 | + executeCode: |
| 163 | + body: | |
| 164 | + console.log('Face camera captured image with id: ' + myFaceCamera.files); |
| 165 | + onError: |
| 166 | + showToast: |
| 167 | + message: "Error capturing image: ${event.error}" |
| 168 | +``` |
| 169 | +
|
| 170 | +### 3. Auto-capture and upload |
| 171 | +
|
| 172 | +Automatically capture once the face is valid, then upload the captured file. |
| 173 | +
|
| 174 | +```yaml |
| 175 | +- Button: |
| 176 | + label: Auto Capture and Upload |
| 177 | + onTap: |
| 178 | + openFaceCamera: |
| 179 | + id: captureMedia |
| 180 | + options: |
| 181 | + autoCapture: true |
| 182 | + performanceMode: accurate |
| 183 | + message: "Hold still for capture" |
| 184 | + onCapture: |
| 185 | + uploadFiles: |
| 186 | + id: uploader |
| 187 | + files: ${captureMedia.files[0]} |
| 188 | + uploadApi: fileUploadApi |
| 189 | + fieldName: file |
| 190 | + |
| 191 | +- Markdown: |
| 192 | + text: ${uploader.body} |
| 193 | + |
| 194 | +API: |
| 195 | + fileUploadApi: |
| 196 | + inputs: |
| 197 | + - url |
| 198 | + uri: ${url} |
| 199 | + method: POST |
| 200 | +``` |
| 201 | +
|
| 202 | +### 4. Web accuracy config |
| 203 | +
|
| 204 | +Use strict face detection thresholds for web capture. |
| 205 | +
|
| 206 | +```yaml |
| 207 | +- Button: |
| 208 | + label: Open Camera (web, strict) |
| 209 | + onTap: |
| 210 | + openFaceCamera: |
| 211 | + id: cameraWithFaceDetection |
| 212 | + options: |
| 213 | + initialCamera: front |
| 214 | + autoCapture: false |
| 215 | + performanceMode: accurate |
| 216 | + accuracyConfig: |
| 217 | + detectionThreshold: 0.5 |
| 218 | + intersectionRatioThreshold: 0.9 |
| 219 | + extraHeightFactor: 0.6 |
| 220 | + inputSize: 224 |
| 221 | + landmarkRatio: 0.95 |
| 222 | + frameMargin: 0.05 |
| 223 | + tiltAngleThreshold: 6 |
| 224 | + horizontalCenterTolerance: 0.08 |
| 225 | + earThreshold: 0.25 |
| 226 | + minFaceWidthRatio: 0.18 |
| 227 | + maxFaceWidthRatio: 0.82 |
| 228 | + qualityPassThreshold: 0.8 |
| 229 | + yawLowerThreshold: 0.85 |
| 230 | + yawUpperThreshold: 1.15 |
| 231 | + message: "Align your face in the square" |
| 232 | + messageStyle: |
| 233 | + color: "#FF0000" |
| 234 | + fontSize: 20 |
| 235 | + onCapture: |
| 236 | + uploadFiles: |
| 237 | + id: uploader |
| 238 | + files: ${cameraWithFaceDetection.files[0]} |
| 239 | + uploadApi: fileUploadApi |
| 240 | + fieldName: file |
| 241 | + onError: |
| 242 | + showToast: |
| 243 | + message: "Error capturing image: ${event.error}" |
| 244 | +``` |
| 245 | +
|
0 commit comments