|
| 1 | +# Facial Recognition Feature Documentation |
| 2 | + |
| 3 | +## Overview |
| 4 | + |
| 5 | +The facial recognition feature helps users organize and tag family members in uploaded photos automatically. The system can detect faces, suggest person tags, and allow users to review and confirm these suggestions. |
| 6 | + |
| 7 | +## User Guide |
| 8 | + |
| 9 | +### Uploading Photos |
| 10 | + |
| 11 | +1. Navigate to a Person's profile in the application |
| 12 | +2. Click on the "Photos" tab |
| 13 | +3. Click "New Photo" or "Upload Photo" |
| 14 | +4. Select an image file from your device |
| 15 | +5. Add an optional description |
| 16 | +6. Click "Save" |
| 17 | + |
| 18 | +The system will automatically analyze the photo for faces upon upload. |
| 19 | + |
| 20 | +### Reviewing Facial Recognition Tags |
| 21 | + |
| 22 | +1. Navigate to **Family Tree > Review Photo Tags** in the main menu |
| 23 | +2. You'll see photos with detected faces that need review |
| 24 | +3. For each detected face: |
| 25 | + - The system shows the suggested person (if a match was found) |
| 26 | + - Displays the confidence score |
| 27 | + - Shows the face location with a bounding box overlay |
| 28 | + |
| 29 | +4. Review options: |
| 30 | + - **Confirm**: Accept the suggested tag |
| 31 | + - **Select Different Person**: Choose the correct person from the dropdown |
| 32 | + - **Reject**: Mark the tag as incorrect |
| 33 | + - **Skip**: Move to the next tag without making a decision |
| 34 | + |
| 35 | +5. The progress bar shows how many tags remain to review |
| 36 | + |
| 37 | +### Managing Photos |
| 38 | + |
| 39 | +From a Person's profile Photos tab, you can: |
| 40 | + |
| 41 | +- **View all photos** associated with that person |
| 42 | +- **See tag counts** for each photo |
| 43 | +- **Manually analyze** photos that weren't automatically analyzed |
| 44 | +- **Edit photo descriptions** |
| 45 | +- **Delete photos** (and their associated tags) |
| 46 | + |
| 47 | +### Understanding Confidence Scores |
| 48 | + |
| 49 | +- **90-100%**: Very high confidence - likely accurate |
| 50 | +- **80-89%**: High confidence - usually accurate |
| 51 | +- **70-79%**: Medium confidence - review carefully |
| 52 | +- **Below 70%**: Low confidence - likely needs correction |
| 53 | + |
| 54 | +## Features |
| 55 | + |
| 56 | +### Automatic Face Detection |
| 57 | + |
| 58 | +- Detects multiple faces in a single photo |
| 59 | +- Provides bounding box coordinates for each face |
| 60 | +- Calculates confidence scores for matches |
| 61 | + |
| 62 | +### Person Matching |
| 63 | + |
| 64 | +- Compares detected faces with known face encodings |
| 65 | +- Suggests person tags based on similarity |
| 66 | +- Learns from confirmed tags to improve future matches |
| 67 | + |
| 68 | +### Tag Management |
| 69 | + |
| 70 | +- Three status states: Pending, Confirmed, Rejected |
| 71 | +- Track who confirmed each tag and when |
| 72 | +- Update person assignments as needed |
| 73 | + |
| 74 | +### Face Encoding |
| 75 | + |
| 76 | +- Stores facial features for confirmed tags |
| 77 | +- Uses encodings for future matching |
| 78 | +- Supports multiple encodings per person |
| 79 | + |
| 80 | +## Developer Guide |
| 81 | + |
| 82 | +### Architecture |
| 83 | + |
| 84 | +The facial recognition system is built with a provider pattern, allowing different facial recognition services to be used: |
| 85 | + |
| 86 | +``` |
| 87 | +FacialRecognitionService (Main Service) |
| 88 | + ↓ |
| 89 | +FacialRecognitionProviderInterface |
| 90 | + ↓ |
| 91 | +├── MockProvider (Development/Testing) |
| 92 | +├── AwsRekognitionProvider (Production - Not yet implemented) |
| 93 | +└── AzureFaceApiProvider (Future option - Not yet implemented) |
| 94 | +``` |
| 95 | + |
| 96 | +### Adding a New Provider |
| 97 | + |
| 98 | +To add a new facial recognition provider (e.g., AWS Rekognition): |
| 99 | + |
| 100 | +1. Create a new provider class implementing `FacialRecognitionProviderInterface`: |
| 101 | + |
| 102 | +```php |
| 103 | +<?php |
| 104 | + |
| 105 | +namespace App\Services\FacialRecognition\Providers; |
| 106 | + |
| 107 | +use App\Services\FacialRecognition\FacialRecognitionProviderInterface; |
| 108 | + |
| 109 | +class AwsRekognitionProvider implements FacialRecognitionProviderInterface |
| 110 | +{ |
| 111 | + public function detectFaces(string $imagePath): array |
| 112 | + { |
| 113 | + // Implement AWS Rekognition face detection |
| 114 | + } |
| 115 | + |
| 116 | + public function matchFaces(string $imagePath, array $faceEncodings): array |
| 117 | + { |
| 118 | + // Implement AWS Rekognition face matching |
| 119 | + } |
| 120 | + |
| 121 | + public function getFaceEncoding(string $imagePath, array $boundingBox): string |
| 122 | + { |
| 123 | + // Implement AWS Rekognition face encoding |
| 124 | + } |
| 125 | + |
| 126 | + public function isAvailable(): bool |
| 127 | + { |
| 128 | + // Check if AWS credentials are configured |
| 129 | + } |
| 130 | +} |
| 131 | +``` |
| 132 | + |
| 133 | +2. Update `FacialRecognitionService::getProvider()` to include your new provider: |
| 134 | + |
| 135 | +```php |
| 136 | +protected function getProvider(): FacialRecognitionProviderInterface |
| 137 | +{ |
| 138 | + $provider = config('services.facial_recognition.provider', 'mock'); |
| 139 | + |
| 140 | + return match ($provider) { |
| 141 | + 'mock' => new MockProvider(), |
| 142 | + 'aws' => new AwsRekognitionProvider(), |
| 143 | + // Add your provider here |
| 144 | + default => new MockProvider(), |
| 145 | + }; |
| 146 | +} |
| 147 | +``` |
| 148 | + |
| 149 | +3. Add configuration in `config/services.php`: |
| 150 | + |
| 151 | +```php |
| 152 | +'facial_recognition' => [ |
| 153 | + 'provider' => env('FACIAL_RECOGNITION_PROVIDER', 'mock'), |
| 154 | + 'aws' => [ |
| 155 | + 'key' => env('AWS_ACCESS_KEY_ID'), |
| 156 | + 'secret' => env('AWS_SECRET_ACCESS_KEY'), |
| 157 | + 'region' => env('AWS_DEFAULT_REGION', 'us-east-1'), |
| 158 | + ], |
| 159 | +], |
| 160 | +``` |
| 161 | + |
| 162 | +4. Add environment variables to `.env`: |
| 163 | + |
| 164 | +```env |
| 165 | +FACIAL_RECOGNITION_PROVIDER=aws |
| 166 | +AWS_ACCESS_KEY_ID=your_key_here |
| 167 | +AWS_SECRET_ACCESS_KEY=your_secret_here |
| 168 | +AWS_DEFAULT_REGION=us-east-1 |
| 169 | +``` |
| 170 | + |
| 171 | +### Database Schema |
| 172 | + |
| 173 | +#### person_photos |
| 174 | +Stores photo metadata for person photos. |
| 175 | + |
| 176 | +| Column | Type | Description | |
| 177 | +|--------|------|-------------| |
| 178 | +| id | bigint | Primary key | |
| 179 | +| person_id | bigint | Foreign key to people table | |
| 180 | +| team_id | bigint | Foreign key to teams table | |
| 181 | +| file_path | string | Storage path to photo file | |
| 182 | +| file_name | string | Original filename | |
| 183 | +| mime_type | string | File MIME type | |
| 184 | +| file_size | integer | File size in bytes | |
| 185 | +| width | integer | Image width in pixels | |
| 186 | +| height | integer | Image height in pixels | |
| 187 | +| description | text | Optional photo description | |
| 188 | +| is_analyzed | boolean | Whether facial recognition has been run | |
| 189 | +| analyzed_at | timestamp | When facial recognition was run | |
| 190 | + |
| 191 | +#### photo_tags |
| 192 | +Stores facial recognition tags linking faces to people. |
| 193 | + |
| 194 | +| Column | Type | Description | |
| 195 | +|--------|------|-------------| |
| 196 | +| id | bigint | Primary key | |
| 197 | +| photo_id | bigint | Foreign key to person_photos | |
| 198 | +| person_id | bigint | Foreign key to people (nullable) | |
| 199 | +| team_id | bigint | Foreign key to teams | |
| 200 | +| confidence | decimal(5,2) | Match confidence score (0-100) | |
| 201 | +| bounding_box | json | Face coordinates {left, top, width, height} | |
| 202 | +| status | enum | Tag status: pending, confirmed, rejected | |
| 203 | +| confirmed_by | bigint | Foreign key to users (who confirmed) | |
| 204 | +| confirmed_at | timestamp | When tag was confirmed | |
| 205 | + |
| 206 | +#### face_encodings |
| 207 | +Stores face encoding data for matching. |
| 208 | + |
| 209 | +| Column | Type | Description | |
| 210 | +|--------|------|-------------| |
| 211 | +| id | bigint | Primary key | |
| 212 | +| person_id | bigint | Foreign key to people | |
| 213 | +| team_id | bigint | Foreign key to teams | |
| 214 | +| source_photo_id | bigint | Foreign key to person_photos | |
| 215 | +| encoding | text | Encrypted face encoding data | |
| 216 | +| provider | string | Provider that created encoding | |
| 217 | + |
| 218 | +### API Methods |
| 219 | + |
| 220 | +#### FacialRecognitionService |
| 221 | + |
| 222 | +**analyzePhoto(PersonPhoto $photo): array** |
| 223 | +- Analyzes a photo for faces |
| 224 | +- Creates tags for detected faces |
| 225 | +- Returns results with face count and success status |
| 226 | + |
| 227 | +**confirmTag(PhotoTag $tag, int $userId, bool $createEncoding = true): bool** |
| 228 | +- Confirms a photo tag |
| 229 | +- Optionally creates face encoding |
| 230 | +- Records who confirmed and when |
| 231 | + |
| 232 | +**rejectTag(PhotoTag $tag): bool** |
| 233 | +- Rejects a photo tag |
| 234 | +- Updates status to rejected |
| 235 | + |
| 236 | +**updateTagPerson(PhotoTag $tag, int $personId, int $userId): bool** |
| 237 | +- Updates tag to different person |
| 238 | +- Confirms the corrected tag |
| 239 | +- Creates face encoding for new assignment |
| 240 | + |
| 241 | +**getPendingTags(?int $teamId = null, int $limit = 50)** |
| 242 | +- Returns pending tags for review |
| 243 | +- Filtered by team if specified |
| 244 | +- Ordered by creation date |
| 245 | + |
| 246 | +### Testing |
| 247 | + |
| 248 | +Run the test suite: |
| 249 | + |
| 250 | +```bash |
| 251 | +php artisan test --filter FacialRecognition |
| 252 | +php artisan test --filter PhotoTagging |
| 253 | +``` |
| 254 | + |
| 255 | +Unit tests cover: |
| 256 | +- Face detection |
| 257 | +- Tag creation and management |
| 258 | +- Person matching |
| 259 | +- Error handling |
| 260 | + |
| 261 | +Feature tests cover: |
| 262 | +- Complete photo upload workflow |
| 263 | +- Tag review and confirmation |
| 264 | +- Tag correction and rejection |
| 265 | +- Relationship integrity |
| 266 | + |
| 267 | +### Security Considerations |
| 268 | + |
| 269 | +1. **Face Encodings**: Stored encrypted in the database |
| 270 | +2. **File Storage**: Photos stored in Laravel's storage with proper permissions |
| 271 | +3. **Team Isolation**: All queries filtered by team_id for multi-tenancy |
| 272 | +4. **User Authorization**: Only team members can review and confirm tags |
| 273 | +5. **Input Validation**: File uploads validated for type and size |
| 274 | + |
| 275 | +## Configuration |
| 276 | + |
| 277 | +### Environment Variables |
| 278 | + |
| 279 | +```env |
| 280 | +# Facial Recognition Provider |
| 281 | +FACIAL_RECOGNITION_PROVIDER=mock # Options: mock, aws |
| 282 | +
|
| 283 | +# AWS Rekognition (if using AWS provider) |
| 284 | +AWS_ACCESS_KEY_ID= |
| 285 | +AWS_SECRET_ACCESS_KEY= |
| 286 | +AWS_DEFAULT_REGION=us-east-1 |
| 287 | +AWS_REKOGNITION_COLLECTION_ID=genealogy-faces |
| 288 | +``` |
| 289 | + |
| 290 | +### Storage Configuration |
| 291 | + |
| 292 | +Photos are stored using Laravel's filesystem in the `public` disk under `person-photos/` directory. |
| 293 | + |
| 294 | +To publish storage: |
| 295 | +```bash |
| 296 | +php artisan storage:link |
| 297 | +``` |
| 298 | + |
| 299 | +## Troubleshooting |
| 300 | + |
| 301 | +### Photos Not Being Analyzed |
| 302 | + |
| 303 | +1. Check if the storage link is created: `php artisan storage:link` |
| 304 | +2. Verify file permissions on storage directory |
| 305 | +3. Check logs for errors: `tail -f storage/logs/laravel.log` |
| 306 | +4. Ensure the provider is configured correctly |
| 307 | + |
| 308 | +### No Faces Detected |
| 309 | + |
| 310 | +1. Verify image quality (should be at least 400x400 pixels) |
| 311 | +2. Check if faces are clearly visible and front-facing |
| 312 | +3. Try re-analyzing the photo manually |
| 313 | +4. Review provider-specific limitations |
| 314 | + |
| 315 | +### Tags Not Matching Correctly |
| 316 | + |
| 317 | +1. Ensure confirmed tags exist for the person |
| 318 | +2. Check if face encodings were created |
| 319 | +3. Verify the person has multiple confirmed tags for better matching |
| 320 | +4. Review confidence threshold in provider |
| 321 | + |
| 322 | +## Future Enhancements |
| 323 | + |
| 324 | +- [ ] Implement AWS Rekognition provider |
| 325 | +- [ ] Add batch photo upload |
| 326 | +- [ ] Implement automatic tag confirmation above threshold |
| 327 | +- [ ] Add face grouping for unknown faces |
| 328 | +- [ ] Support for video analysis |
| 329 | +- [ ] Mobile-optimized review interface |
| 330 | +- [ ] Export tagged photo collections |
| 331 | +- [ ] Integration with photo timeline view |
| 332 | + |
| 333 | +## Support |
| 334 | + |
| 335 | +For issues or questions: |
| 336 | +- Check the logs: `storage/logs/laravel.log` |
| 337 | +- Review the test suite for usage examples |
| 338 | +- Consult the codebase documentation |
| 339 | +- Contact the development team |
0 commit comments