Face recognition using webcam in php

Table of Contents

  • What is FPEG?
  • Using Face Detection with PHP Example
  • Architecture
  • How to Perform Facial Detection with PHP (using a Face Detector API)
    • 1. Set Your API Key
    • 2. Set Command Line Parameters
    • 3. Set the image URL and JPEG quality for the output image
    • 4. Fetch accuracy boost, background quality, and foreground quality
    • 5. Get the file size of the image
    • 6. Init and execute curl request
    • 7. Initialize the working images
    • 8. Copy faces from the initial image onto the working image
    • 9. Reduce image quality of the original image and Apply faces to the reduced background image
    • 10. Verify faces were found and save the image
    • The Full Code
  • Conclusion
  • Related Resources

What is FPEG?

FPEG detects faces in an image and compresses those regions less than the surrounding pixels. In theory the human visual cortex is more sensitive to compression artifacts on faces then surrounding context, therefore using higher compression in non-facial regions will lead to smaller images with comparable perceived quality. — Andrew Schreiber

Using the face detection API at RapidAPI to reduce the background quality of images while maintaining the resolution of faces and reduce the image size considerably. The name is a play on “Faces JPEG”. This library is based on the strategy of FPEG by Andrew Schreiber.

Connect to the Face Detection API

Using Face Detection with PHP Example

This is a single page PHP script that takes a URL to a jpg, png, webp, bmp, or gif and finds all the faces in the image then reduces the quality of the background while saving the resolution of the faces. The effect of this transformation is an image that appears to maintain the resolution of the original image because the faces in the image are the focus and the resolution of the faces has not changed.

The example image we are using can be found at https://upload.wikimedia.org/wikipedia/en/7/7d/Lenna_%28test_image%29.png

Output size is flexible based on the -b=backgroundQuality and -f=foregroundQuality variables. The effect of this transformation on an example image measured backgroundQuality/foregroundQuality @ 20/80 is:

Original ImageFPEG Image @ 20/80 quality
Face recognition using webcam in php

Size: 473,831

Size: 32,161

Architecture

  • An image is loaded from a URL.
  • The settings for the script are the image URL and optionally the foreground image quality, the background image quality, and the accuracy boost.
  • Adjust the image quality as desired.

The RapidAPI Face Detection API is used to find all faces in the image, then each face is copied from the original image into a working image at the same location.

After all the faces have been copied the original image is reduced in quality through jpeg compression.

The compressed image is then loaded back into the script and the faces from the working image are copied onto the original image. Then the original image is saved as output.jpg.

RapidAPI offers several other face detection, facial recognition APIs, and OCR APIs, but for this script, we only need to perform facial detection.

Connect to the Face Detection API

How to Perform Facial Detection with PHP (using a Face Detector API)

Making requests to the API is uncomplicated with only 2 endpoints and 2 parameters. There is an endpoint for detecting faces and calculating age and gender and an endpoint for just detecting faces.

In this article, we’ll be using the second endpoint because we are only interested in the positions of faces and not the details of each face.

The endpoint URL is located at https://face-detection6.p.rapidapi.com/img/face which only accepts a POST. The POST parameters are

url: "path-to-image"
accuracy_boost: default 2; range 1-4

The API returns a response like

{
  "detected_faces": [
    {
      "BoundingBox": {
        "startX": 151, 
        "startY": 113, 
        "endX": 402, 
        "endY": 479
      }, 
      "Probability": 83.6599349975586
    }
  ]
}

This JSON result tells us:

  • where each face is,
  • where it starts,
  • and the dimensions from the start.

"detected_faces” is an array of all the faces found in the url image.

Parameters

-i Url to input image (required)
-a Accuracy Boost [1-4] default 2 (optional)
-b Background JPEG Quality default 20 (optional)
-f Foreground JPEG Quality default 80 (optional)

Execute

Copy the code to a local file fpeg.php. Then run the script with the image and quality parameters

php fpeg.php -i=https://upload.wikimedia.org/wikipedia/en/7/7d/Lenna_%28test_image%29.png -b=20 -f=80

Face recognition using webcam in php

and a new file, output.jpg, will be created in the same directory.

1. Set Your API Key

// Set your RapidAPI key 
$rapidApiKey = '1234567890123456789012345678901234567890';

2. Set Command Line Parameters

// Command Line Parameters
$options = getopt(""
    . "i:"  // Image URL
    . "a::" // Accuracy Boost 1-4
    . "b::" // Background Quality (optional)
    . "f::" // Foreground Quality (optional)
    , []
);

3. Set the image URL and JPEG quality for the output image

// Set the image url and jpeg quality for the output image
$imageUrl = $options['i'] ?? '';
if (! filter_var($imageUrl, FILTER_VALIDATE_URL)) {
    throw new Exception('Invalid URL');
}

4. Fetch accuracy boost, background quality, and foreground quality

// Fetch accuracy boost
$accuracyBoost = $options['a'] ?? 2;
if ($accuracyBoost < 1) {
    $accuracyBoost = 1;
} elseif ($accuracyBoost > 4) {
    $accuracyBoost = 4;
}

// Fetch background quality and validate
$backgroundQuality = $options['b'] ?? 20;
if ($backgroundQuality < 1) {
    $backgroundQuality = 1;
} elseif ($backgroundQuality > 100) {
    $backgroundQuality = 100;
}

// Fetch foreground quality and validate
$foregroundQuality = $options['f'] ?? 80;
if ($foregroundQuality < 1) {
    $foregroundQuality = 1;
} elseif ($foregroundQuality > 100) {
    $foregroundQuality = 100;
}

5. Get the file size of the image

// Get the file size of the remote image
$curl = curl_init($imageUrl);
curl_setopt_array($curl, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HEADER => true,
    CURLOPT_NOBODY => true,
]);
curl_exec($curl);
$error = curl_error($curl);
if ($error) {
    throw new Exception(
        "Unable to fetch remote image size.  Curl Error #:" . $error
    );
}
$imageFileSize = curl_getinfo($curl, CURLINFO_CONTENT_LENGTH_DOWNLOAD);
curl_close($curl);

// Init curl for the request to RapidAPI
$curl = curl_init();
curl_setopt_array($curl, array(
    CURLOPT_URL => "https://face-detection6.p.rapidapi.com/img/face",
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_FOLLOWLOCATION => true,
    CURLOPT_CUSTOMREQUEST => "POST",
    CURLOPT_POSTFIELDS => "{"url":"$imageUrl","accuracy_boost":$accuracyBoost}",
    CURLOPT_HTTPHEADER => array(
        "accept: application/json",
        "content-type: application/json",
        "x-rapidapi-host: face-detection6.p.rapidapi.com",
        "x-rapidapi-key: $rapidApiKey"
    ),
));

// Execute the curl and decode the response
$response = curl_exec($curl);
$error = curl_error($curl);
curl_close($curl);
if ($error) {
    throw new Exception(
        "Error response from Face Detection API. curl Error #:" . $error
    );
}
$response = json_decode($response, true);

6. Init and execute curl request

// Init curl for the request to RapidAPI
$curl = curl_init();
curl_setopt_array($curl, array(
    CURLOPT_URL => "https://face-detection6.p.rapidapi.com/img/face",
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_FOLLOWLOCATION => true,
    CURLOPT_CUSTOMREQUEST => "POST",
    CURLOPT_POSTFIELDS => "{"url":"$imageUrl","accuracy_boost":$accuracyBoost}",
    CURLOPT_HTTPHEADER => array(
        "accept: application/json",
        "content-type: application/json",
        "x-rapidapi-host: face-detection6.p.rapidapi.com",
        "x-rapidapi-key: $rapidApiKey"
    ),
));

// Execute the curl and decode the response
$response = curl_exec($curl);
$error = curl_error($curl);
curl_close($curl);
if ($error) {
    throw new Exception(
        "Error response from Face Detection API. curl Error #:" . $error
    );
}
$response = json_decode($response, true);

7. Initialize the working images

// Initialize the working images
$imageDimentions = getimagesize($imageUrl);
switch($imageDimentions['mime']) {
    case 'image/gif':
        $imageResource = imagecreatefromgif($imageUrl);
        break;
    case 'image/png':
        $imageResource = imagecreatefrompng($imageUrl);
        break;
    case 'image/webp':
        $imageResource = imagecreatefromwebp($imageUrl);
        break;
    case 'image/x-ms-bmp':
        $imageResource = imagecreatefrombmp($imageUrl);
        break;
    case 'image/jpeg':
        $imageResource = imagecreatefromjpeg($imageUrl);
        break;
    default:
        throw new Exception('Unsupported image type');
}
$workingImageResource = 
    imagecreatetruecolor($imageDimentions[0], $imageDimentions[1]);

8. Copy faces from the initial image onto the working image

// Copy faces from initial image onto working image
$faceCount = 0;
foreach ($response['detected_faces'] as $face) {
    $boundingBox = $face['BoundingBox'];
    $success = imagecopy(
        $workingImageResource,
        $imageResource,
        $boundingBox['startX'], // Source X
        $boundingBox['startY'], // Source Y
        $boundingBox['startX'], // Destination X
        $boundingBox['startY'], // Destination Y
        $boundingBox['endX'] - $boundingBox['startX'], // width
        $boundingBox['endY'] - $boundingBox['startY'] // height
    );

    $faceCount ++;

    if (! $success) {
        throw new Exception(error_get_last()['message']);
    }
}

// All faces are now copied into the working image

9. Reduce image quality of the original image and Apply faces to the reduced background image

// Reduce image quality of Source image
$imageTempName = tempnam(sys_get_temp_dir(), 'fpeg');
imagejpeg($imageResource, $imageTempName, $backgroundQuality);

// Load quality reduced image
$imageResource = imagecreatefromjpeg($imageTempName);
unlink($imageTempName);

// Apply faces to reduced background quality image
foreach ($response['detected_faces'] as $face) {
    $boundingBox = $face['BoundingBox'];
    $success = imagecopy(
        $imageResource,
        $workingImageResource,
        $boundingBox['startX'], // Source X
        $boundingBox['startY'], // Source Y
        $boundingBox['startX'], // Destination X
        $boundingBox['startY'], // Destination Y
        $boundingBox['endX'] - $boundingBox['startX'], // width
        $boundingBox['endY'] - $boundingBox['startY'] // height
    );

    if (! $success) {
        throw new Exception(error_get_last()['message']);
    }
}

10. Verify faces were found and save the image

// Verify faces were found
if (! $faceCount) {
    throw new Exception('No faces were found in image');
}

// Save the created image and output statistics
imagejpeg($imageResource, 'output.jpg', $foregroundQuality);

$imageOutputSize = filesize('output.jpg');

if ($imageFileSize <= $imageOutputSize) {
   throw new Exception("FPEG DID NOT IMPROVE COMPRESSION");
}

echo 'Original Size: ' . $imageFileSize . "n";
echo 'FPEG Size: ' . $imageOutputSize . "n";
echo 'Faces: ' . $faceCount . "n";

imagedestroy($imageResource);
imagedestroy($workingImageResource);

Connect to the Face Detection API

The Full Code

<?php

/**
 * Copyright (c) 2020 API Skeletons <>
 *
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
 
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
 */

// Set your RapidAPI key
$rapidApiKey = '1234567890123456789012345678901234567890';

// Command Line Parameters
$options = getopt(""
    . "i:"  // Image URL
    . "a::" // Accuracy Boost 1-4
    . "b::" // Background Quality (optional)
    . "f::" // Foreground Quality (optional)
    , []
);

// Set the image url and jpeg quality for the output image
$imageUrl = $options['i'] ?? '';
if (! filter_var($imageUrl, FILTER_VALIDATE_URL)) {
    throw new Exception('Invalid URL');
}

// Fetch accuracy boost
$accuracyBoost = $options['a'] ?? 2;
if ($accuracyBoost < 1) {
    $accuracyBoost = 1;
} elseif ($accuracyBoost > 4) {
    $accuracyBoost = 4;
}

// Fetch background quality and validate
$backgroundQuality = $options['b'] ?? 20;
if ($backgroundQuality < 1) {
    $backgroundQuality = 1;
} elseif ($backgroundQuality > 100) {
    $backgroundQuality = 100;
}

// Fetch foreground quality and validate
$foregroundQuality = $options['f'] ?? 80;
if ($foregroundQuality < 1) {
    $foregroundQuality = 1;
} elseif ($foregroundQuality > 100) {
    $foregroundQuality = 100;
}

// Get the file size of the remote image
$curl = curl_init($imageUrl);
curl_setopt_array($curl, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HEADER => true,
    CURLOPT_NOBODY => true,
]);
curl_exec($curl);
$error = curl_error($curl);
if ($error) {
    throw new Exception(
        "Unable to fetch remote image size.  Curl Error #:" . $error
    );
}
$imageFileSize = curl_getinfo($curl, CURLINFO_CONTENT_LENGTH_DOWNLOAD);
curl_close($curl);

// Init curl for the request to RapidAPI
$curl = curl_init();
curl_setopt_array($curl, array(
    CURLOPT_URL => "https://face-detection6.p.rapidapi.com/img/face",
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_FOLLOWLOCATION => true,
    CURLOPT_CUSTOMREQUEST => "POST",
    CURLOPT_POSTFIELDS => "{"url":"$imageUrl","accuracy_boost":$accuracyBoost}",
    CURLOPT_HTTPHEADER => array(
        "accept: application/json",
        "content-type: application/json",
        "x-rapidapi-host: face-detection6.p.rapidapi.com",
        "x-rapidapi-key: $rapidApiKey"
    ),
));

// Execute the curl and decode the response
$response = curl_exec($curl);
$error = curl_error($curl);
curl_close($curl);
if ($error) {
    throw new Exception(
        "Error response from Face Detection API. curl Error #:" . $error
    );
}
$response = json_decode($response, true);

// Initialize the working images
$imageDimentions = getimagesize($imageUrl);
switch($imageDimentions['mime']) {
    case 'image/gif':
        $imageResource = imagecreatefromgif($imageUrl);
        break;
    case 'image/png':
        $imageResource = imagecreatefrompng($imageUrl);
        break;
    case 'image/webp':
        $imageResource = imagecreatefromwebp($imageUrl);
        break;
    case 'image/x-ms-bmp':
        $imageResource = imagecreatefrombmp($imageUrl);
        break;
    case 'image/jpeg':
        $imageResource = imagecreatefromjpeg($imageUrl);
        break;
    default:
        throw new Exception('Unsupported image type');
}
$workingImageResource = 
    imagecreatetruecolor($imageDimentions[0], $imageDimentions[1]);

// Copy faces from initial image onto working image
$faceCount = 0;
foreach ($response['detected_faces'] as $face) {
    $boundingBox = $face['BoundingBox'];
    $success = imagecopy(
        $workingImageResource,
        $imageResource,
        $boundingBox['startX'], // Source X
        $boundingBox['startY'], // Source Y
        $boundingBox['startX'], // Destination X
        $boundingBox['startY'], // Destination Y
        $boundingBox['endX'] - $boundingBox['startX'], // width
        $boundingBox['endY'] - $boundingBox['startY'] // height
    );

    $faceCount ++;

    if (! $success) {
        throw new Exception(error_get_last()['message']);
    }
}

// All faces are now copied into the working image

// Reduce image quality of Source image
$imageTempName = tempnam(sys_get_temp_dir(), 'fpeg');
imagejpeg($imageResource, $imageTempName, $backgroundQuality);

// Load quality reduced image
$imageResource = imagecreatefromjpeg($imageTempName);
unlink($imageTempName);

// Apply faces to reduced background quality image
foreach ($response['detected_faces'] as $face) {
    $boundingBox = $face['BoundingBox'];
    $success = imagecopy(
        $imageResource,
        $workingImageResource,
        $boundingBox['startX'], // Source X
        $boundingBox['startY'], // Source Y
        $boundingBox['startX'], // Destination X
        $boundingBox['startY'], // Destination Y
        $boundingBox['endX'] - $boundingBox['startX'], // width
        $boundingBox['endY'] - $boundingBox['startY'] // height
    );

    if (! $success) {
        throw new Exception(error_get_last()['message']);
    }
}

// Verify faces were found
if (! $faceCount) {
    throw new Exception('No faces were found in image');
}

// Save the created image and output statistics
imagejpeg($imageResource, 'output.jpg', $foregroundQuality);

$imageOutputSize = filesize('output.jpg');

if ($imageFileSize <= $imageOutputSize) {
   throw new Exception("FPEG DID NOT IMPROVE COMPRESSION");
}

echo 'Original Size: ' . $imageFileSize . "n";
echo 'FPEG Size: ' . $imageOutputSize . "n";
echo 'Faces: ' . $faceCount . "n";

imagedestroy($imageResource);
imagedestroy($workingImageResource);

Connect to the Face Detection API

Conclusion

The clever technique this script creates using the face detection API at RapidAPI will reduce your website’s load time across any device.

If you have a large number of images primarily of faces (such as LinkedIn), then this technique could really change your company’s offering.

  • Facial Recognition API with JavaScript
  • Build a Facial Recognition App (Python)
  • RapidAPI PHP Documentation
  • How to build an API
    • with PHP
  • Facial Recognition with Deep Learning