laravel-rekognition-face maintained by olorunda
Laravel AWS Rekognition Face Comparison & Real Face Verifier
Production-ready Laravel & standalone PHP package to compare two human face images for biometric identity matching and verify whether an image contains a genuine, high-quality, real human face using Amazon Rekognition.
🌟 Key Features
-
Biometric Face Comparison (
CompareFaces):- Compares two faces and computes biometric similarity percentage (0% to 100%).
- Configurable similarity threshold (e.g. 80% default).
- Returns bounding boxes, confidence scores, matched landmarks, and unmatched faces in target photo.
-
Real Human Face & Quality Verification (
DetectFaces):- Human Face Detection Confidence: Verifies Rekognition detects a human face with high confidence (e.g. ≥ 95%).
- Single Face Enforcement: Ensures exactly one human face is present (flags multi-face or crowded photos for KYC / ID verification).
- Image Sharpness & Blur Filter: Rejects motion-blurred, out-of-focus, or low-resolution spoof images.
- Brightness & Exposure Validation: Ensures balanced lighting (rejects pitch black or washed-out photocopies).
- 3D Head Pose Orientation: Checks Yaw (turning), Pitch (tilting up/down), and Roll (sideways tilt) to enforce frontal portrait alignment.
- Open Eyes & Liveness Heuristics: Detects closed eyes (flags sleeping/passive photo spoofing).
- Occlusion & Mask Detection: Rejects sunglasses and facial coverings that conceal biometric landmarks.
- Composite Quality Score: Generates a normalized score (0–100) and actionable diagnostic checklist.
-
Combined Verification Pipeline (
verifyAndCompare):- Verifies that both images are real human faces first.
- Compares the two faces and checks similarity.
- Returns a comprehensive audit trail with pass/fail status and specific violation reasons.
-
AWS Rekognition Face Liveness Session:
- Helpers to generate AWS Face Liveness sessions (
createLivenessSession) and fetch results (getLivenessResults) for frontend camera SDKs (Amplify FaceLivenessDetector).
- Helpers to generate AWS Face Liveness sessions (
-
Universal Image Input Support:
- Local file paths (
/path/to/selfie.jpg) - Raw binary bytes (
file_get_contents(...)) - Base64 strings & Data URIs (
data:image/jpeg;base64,...) - Remote HTTP / HTTPS URLs (auto-downloaded securely)
- Amazon S3 objects (
['bucket' => '...', 'key' => '...']) - Laravel
Illuminate\Http\UploadedFileinstances ($request->file('avatar'))
- Local file paths (
-
Artisan CLI Tools:
php artisan face:compare {source} {target}php artisan face:verify {image}
-
Framework Flexibility:
- Fully integrated with Laravel (Service Provider, Facade, Config publishing, Artisan CLI).
- Can also be instantiated directly in standalone PHP without Laravel.
📦 Installation
Install via Composer:
composer require olorunda/laravel-rekognition-face
In Laravel, the Service Provider and RekognitionFace Facade are registered automatically.
Publish the configuration file:
php artisan vendor:publish --tag="rekognition-face-config"
⚙️ Configuration & Environment
Add your AWS credentials to your .env file:
AWS_ACCESS_KEY_ID=your-aws-access-key-id
AWS_SECRET_ACCESS_KEY=your-aws-secret-access-key
AWS_DEFAULT_REGION=us-east-1
# Optional overrides:
REKOGNITION_SIMILARITY_THRESHOLD=80.0
REKOGNITION_MIN_FACE_CONFIDENCE=95.0
REKOGNITION_STRICT_SINGLE_FACE=true
REKOGNITION_MIN_SHARPNESS=20.0
REKOGNITION_MIN_BRIGHTNESS=15.0
REKOGNITION_MAX_BRIGHTNESS=95.0
REKOGNITION_REQUIRE_EYES_OPEN=true
REKOGNITION_DISALLOW_SUNGLASSES=true
REKOGNITION_DISALLOW_OCCLUSION=true
# Test & Simulation Mode (Run without real AWS keys!):
REKOGNITION_TEST_MODE=false
REKOGNITION_SIMULATE_SCENARIO=match # match, no_match, blurry, closed_eyes, multiple_faces, occluded, not_human
REKOGNITION_SIMULATE_SIMILARITY=96.5
REKOGNITION_SIMULATE_CONFIDENCE=99.8
🚀 Usage
1. Compare Two Faces (Biometric Matching)
Compare an ID card photo and a selfie to see if they belong to the same person:
use Olorunda\RekognitionFace\Facades\RekognitionFace;
// Compare local files, URLs, base64 strings, or UploadedFiles
$result = RekognitionFace::compare(
sourceImage: '/storage/id_card.jpg',
targetImage: '/storage/selfie.jpg',
similarityThreshold: 85.0 // Optional override
);
if ($result->isMatch()) {
echo "Faces match! Similarity: {$result->getSimilarity()}%\n";
echo "Detection confidence: {$result->getConfidence()}%\n";
} else {
echo "Not a match. Similarity was {$result->getSimilarity()}%\n";
}
// Inspect details
$matchedFace = $result->getMatchedFace();
echo "Face pitch: {$matchedFace->pitch}°, yaw: {$matchedFace->yaw}°\n";
echo "Unmatched faces in target image: {$result->getUnmatchedCount()}\n";
2. Verify If An Image Is A Real Human Face
Inspect an image for authenticity, quality, pose, and absence of spoofs or occlusions:
use Olorunda\RekognitionFace\Facades\RekognitionFace;
$realness = RekognitionFace::verifyRealHumanFace('/storage/selfie.jpg');
if ($realness->isRealHumanFace()) {
echo "Genuine human face verified!\n";
echo "Quality Score: {$realness->getQualityScore()} / 100\n";
echo "Detection Confidence: {$realness->getConfidence()}%\n";
} else {
echo "Verification failed! Issues:\n";
foreach ($realness->getViolations() as $violation) {
echo " - {$violation}\n";
}
}
// Checklist breakdown
$checks = $realness->getChecks();
/*
[
'human_detected' => true, // Rekognition detected human face >= 95%
'single_face' => true, // Exactly 1 face found in image
'sharpness_ok' => true, // Not blurry (sharpness >= 20)
'brightness_ok' => true, // Balanced exposure
'pose_frontal' => true, // Facing camera (yaw/pitch/roll within bounds)
'eyes_open' => true, // Open eyes detected
'no_occlusion' => true, // No sunglasses or masks
'min_face_size_ok' => true, // Face is prominent in the frame
]
*/
Customizing checks on the fly:
$realness = RekognitionFace::verifyRealHumanFace($image, [
'strict_single_face' => false, // Allow photos with multiple people
'min_sharpness' => 40.0, // Require higher sharpness
'require_eyes_open' => false, // Permit closed eyes
]);
3. Complete End-to-End Pipeline (verifyAndCompare)
Runs both real face checks on the source and target images before comparing them:
use Olorunda\RekognitionFace\Facades\RekognitionFace;
$verification = RekognitionFace::verifyAndCompare(
sourceImage: $request->file('id_card'),
targetImage: $request->file('selfie'),
options: ['threshold' => 80.0]
);
if ($verification->passed()) {
echo "Verification SUCCESS!\n";
echo "Similarity: {$verification->getSimilarity()}%\n";
} else {
echo "Verification FAILED!\n";
foreach ($verification->getFailureReasons() as $reason) {
echo " - {$reason}\n";
}
}
4. AWS Rekognition Face Liveness Session
For active 3D liveness detection using AWS Amplify web or mobile SDK:
use Olorunda\RekognitionFace\Facades\RekognitionFace;
// 1. Create a session for the mobile/web frontend
$sessionId = RekognitionFace::createLivenessSession();
// 2. Pass $sessionId to client app running AWS Amplify FaceLivenessDetector
// 3. Retrieve results once client completes the test
$results = RekognitionFace::getLivenessResults($sessionId);
if ($results['Status'] === 'SUCCEEDED' && $results['Confidence'] >= 90.0) {
echo "Liveness check passed with confidence {$results['Confidence']}%\n";
}
5. 🧪 Test & Simulation Mode (Run Without AWS Keys)
You can develop, test, and run biometric verification without supplying real AWS credentials. This is ideal for local development, CI/CD, staging, and demo environments.
A. Enable via .env:
REKOGNITION_TEST_MODE=true
REKOGNITION_SIMULATE_SCENARIO=match # Options: match, no_match, blurry, closed_eyes, multiple_faces, occluded, not_human
B. Runtime Simulation (Mocking like Http::fake()):
use Olorunda\RekognitionFace\Facades\RekognitionFace;
// Turn on test mode on the fly
RekognitionFace::fake();
// Switch test scenarios:
RekognitionFace::fakeScenario('match'); // Matches with high similarity (96.5%)
RekognitionFace::fakeScenario('no_match'); // Valid faces, but different people (38.4% similarity)
RekognitionFace::fakeScenario('blurry'); // Fails sharpness quality filter
RekognitionFace::fakeScenario('closed_eyes'); // Fails eyes open liveness check
RekognitionFace::fakeScenario('multiple_faces'); // Multiple people in image (fails strict single-face)
RekognitionFace::fakeScenario('occluded'); // Face wearing sunglasses or mask
RekognitionFace::fakeScenario('not_human'); // No human face found
// Custom simulation parameters:
RekognitionFace::fake([
'similarity' => 92.0,
'is_match' => true,
'confidence' => 99.9,
]);
// Check status or turn off:
RekognitionFace::isTestMode(); // true
RekognitionFace::enableTestMode(false);
C. Available Simulation Scenarios:
| Scenario | Real Face Result | Comparison Result | Typical Use Case |
|---|---|---|---|
match (default) |
Pass (Quality: ~94) | Match (Similarity: 96.5%) | Happy path testing |
no_match |
Pass | No Match (Similarity: 38.4%) | Testing rejection of non-matching IDs |
blurry |
Fail (Sharpness: 8.5 < 20) | Match | Testing low-quality camera uploads |
closed_eyes |
Fail (Eyes closed) | Match | Testing sleeping/photo liveness spoof |
multiple_faces |
Fail (2 faces found) | Match | Testing anti-crowd / multiple person photo |
occluded |
Fail (Sunglasses detected) | Match | Testing mask/sunglasses rejection |
not_human |
Fail (0 faces found) | Throws Exception | Testing object or pet photos |
6. Flexible Image Inputs
The package accepts any of the following formats interchangeably:
// Local file path
RekognitionFace::compare('/path/to/photo.jpg', '/path/to/selfie.png');
// Laravel UploadedFile from form request
RekognitionFace::compare($request->file('id_document'), $request->file('webcam_capture'));
// Base64 Data URI from HTML5 webcam
RekognitionFace::verifyRealHumanFace('data:image/jpeg;base64,/9j/4AAQSkZJRg...');
// Raw binary bytes
RekognitionFace::compare($rawJpegBytes1, $rawJpegBytes2);
// Remote HTTP / HTTPS URL
RekognitionFace::compare('https://mycdn.com/id.jpg', 'https://mycdn.com/selfie.jpg');
// AWS S3 Object reference
RekognitionFace::compare(
['bucket' => 'my-private-bucket', 'key' => 'users/123/passport.jpg'],
['bucket' => 'my-private-bucket', 'key' => 'users/123/live_capture.jpg']
);
7. Artisan CLI Commands
Compare Two Face Images
# Standard mode (with AWS keys):
php artisan face:compare /path/to/id.jpg /path/to/selfie.jpg --threshold=85
# Test mode (without AWS keys):
php artisan face:compare /path/to/id.jpg /path/to/selfie.jpg --simulate --scenario=match
Output:
Comparing faces using AWS Rekognition...
Source: /path/to/id.jpg
Target: /path/to/selfie.jpg
MATCH DETECTED!
+----------------------------+-----------+
| Metric | Value |
+----------------------------+-----------+
| Is Match | YES |
| Similarity Score | 96.5% |
| Required Threshold | 85% |
| Detection Confidence | 99.8% |
| Unmatched Faces in Target | 0 |
+----------------------------+-----------+
Verify a Real Human Face
# Standard mode:
php artisan face:verify /path/to/selfie.jpg --strict
# Test mode:
php artisan face:verify /path/to/selfie.jpg --simulate --scenario=blurry
Output:
Analyzing image for real human face...
Image: /path/to/selfie.jpg
REAL HUMAN FACE VERIFIED
+-------------------------+-----------+
| Metric | Value |
+-------------------------+-----------+
| Is Real Human Face | YES |
| Detection Confidence | 99.9% |
| Composite Quality Score | 94.2 / 100|
| Faces Detected | 1 |
| Passed All Checks | YES |
+-------------------------+-----------+
Validation Checklist:
+-------------------+--------+
| Check | Status |
+-------------------+--------+
| Human Detected | PASS |
| Single Face | PASS |
| Sharpness Ok | PASS |
| Brightness Ok | PASS |
| Pose Frontal | PASS |
| Eyes Open | PASS |
| No Occlusion | PASS |
| Min Face Size Ok | PASS |
+-------------------+--------+
8. Standalone PHP Usage (Without Laravel)
require_once __DIR__ . '/vendor/autoload.php';
use Olorunda\RekognitionFace\Services\RekognitionFaceService;
$service = new RekognitionFaceService([
'region' => 'us-east-1',
'credentials' => [
'key' => 'YOUR_AWS_KEY',
'secret' => 'YOUR_AWS_SECRET',
],
'comparison' => [
'default_threshold' => 80.0,
],
]);
$result = $service->compare('id.jpg', 'selfie.jpg');
if ($result->isMatch()) {
echo "Matched! Similarity: " . $result->getSimilarity() . "%\n";
}
🔒 Required AWS IAM Policy
Your AWS IAM user or role must have the following permissions:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "RekognitionFacePermissions",
"Effect": "Allow",
"Action": [
"rekognition:CompareFaces",
"rekognition:DetectFaces",
"rekognition:CreateFaceLivenessSession",
"rekognition:GetFaceLivenessSessionResults"
],
"Resource": "*"
}
]
}
(If using S3 object references directly, also ensure s3:GetObject permission on the target buckets).
🧪 Testing
Run PHPUnit tests:
composer test
All unit and feature tests use the AWS SDK MockHandler to run offline without hitting AWS or incurring costs.
📄 License
The MIT License (MIT). Please see LICENSE.md for more information.