How to use Google cloud vision API  to detect the face(s) on image uploads in Laravel

How to use Google cloud vision API to detect the face(s) on image uploads in Laravel

Using Google cloud vision API to detect the face(s) and their mood on image upload in a Laravel application

In this article, we'll be look at how to use the Google cloud vision API to detect the faces on image upload in a Laravel application.

Face Detection detects multiple faces within an image along with the associated key facial attributes such as emotional state or wearing headwear. Specific individual Facial Recognition is not supported.

  • Detect Faces in a local image

The Vision API can perform feature detection on a local image file by sending the contents of the image file as a base64 encoded string in the body of your request.

In this tutorial on How to use Google cloud vision API safe search detection to detect explicit content on image uploads in Laravel, we covered the details on how to create a Google Cloud Platform (GCP) project, service account credentials and cloud vision package integration into Laravel.

In order to keep this simple, We'll go straight to exploring how to detect the face(s) on image uploads because we already have a form for uploading files from the previous feature integration.

image.png

NB: each feature has its own route in the web.php file for clarity purposes.

You can also check into a specific branch on GitHub to go over its implementation

Here's a repository with an example of its integration.

When the file is uploaded, we can run the detection inside the post method.

  • Import the classes
use Google\Cloud\Vision\V1\ImageAnnotatorClient;
// this HtmlStringclass is used to format the text detected on the image
use Illuminate\Support\HtmlString;
  • Running the faceDetection on the uploaded image

Just like in the safe search detection feature the response for each of the face detection methods could be any one of the values in the array below.

            $likelihoodName = [
                'UNKNOWN', 'VERY_UNLIKELY', 'UNLIKELY',
                'POSSIBLE', 'LIKELY', 'VERY_LIKELY'
            ];

With these values, we can detect the likelihood of the face if it's anger, joy or surprise mood.

  • Code snippets
    public function detectFaces(Request $request)
    {
        $request->validate([
            'avatar' => 'required|image|max:10240',
        ]);

        try {
            $imageAnnotator = new ImageAnnotatorClient([
                //we can also keep the details of the google cloud JSON file in an env and read it as an object here
                'credentials' => config_path('laravel-cloud.json')
            ]);
            # annotate the image

            $path = $request->file("avatar");
            $image = file_get_contents($path);

            $outFile = null;

            $response = $imageAnnotator->faceDetection($image);
            $faces = $response->getFaceAnnotations();

            # names of likelihood from google.cloud.vision.enums
            $likelihoodName = [
                'UNKNOWN', 'VERY_UNLIKELY', 'UNLIKELY',
                'POSSIBLE', 'LIKELY', 'VERY_LIKELY'
            ];

            $number_of_faces = count($faces);

            // the number of faces found on the image
            // printf('%d faces found:' . PHP_EOL, count($faces));

            $image_face_content = '';

            $count = 0;

            foreach ($faces as $face) {
                $count = +1;
                $anger = $face->getAngerLikelihood();
                //the likelihood of anger
                // printf('Anger: %s' . PHP_EOL, $likelihoodName[$anger]);
                $image_face_content .= "Face $count is Angry?: $likelihoodName[$anger] \n";

                $joy = $face->getJoyLikelihood();
                //the likelihood of joy
                // printf('Joy: %s' . PHP_EOL, $likelihoodName[$joy]);
                $image_face_content .= "Face $count is Joyful?: $likelihoodName[$joy] \n";

                $surprise = $face->getSurpriseLikelihood();
                //suprise status
                // printf('Surprise: %s' . PHP_EOL, $likelihoodName[$surprise]);
                $image_face_content .= "Face $count is Suprised?: $likelihoodName[$surprise] \n";

                # get bounds
                $vertices = $face->getBoundingPoly()->getVertices();
                $bounds = [];
                foreach ($vertices as $vertex) {
                    $bounds[] = sprintf('(%d,%d)', $vertex->getX(), $vertex->getY());
                }

                //returns the bounds in for the faces result
                print('Bounds: ' . join(', ', $bounds) . PHP_EOL);
                print(PHP_EOL);
            }
            // [END vision_face_detection]

            # [START vision_face_detection_tutorial_process_response]
            # draw box around faces
            if ($faces && $outFile) {
                $imageCreateFunc = [
                    'png' => 'imagecreatefrompng',
                    'gd' => 'imagecreatefromgd',
                    'gif' => 'imagecreatefromgif',
                    'jpg' => 'imagecreatefromjpeg',
                    'jpeg' => 'imagecreatefromjpeg',
                ];
                $imageWriteFunc = [
                    'png' => 'imagepng',
                    'gd' => 'imagegd',
                    'gif' => 'imagegif',
                    'jpg' => 'imagejpeg',
                    'jpeg' => 'imagejpeg',
                ];

                copy($path, $outFile);
                $ext = strtolower(pathinfo($path, PATHINFO_EXTENSION));
                if (!array_key_exists($ext, $imageCreateFunc)) {
                    throw new \Exception('Unsupported image extension');
                }

                $outputImage = call_user_func($imageCreateFunc[$ext], $outFile);

                foreach ($faces as $face) {
                    $vertices = $face->getBoundingPoly()->getVertices();
                    if ($vertices) {
                        $x1 = $vertices[0]->getX();
                        $y1 = $vertices[0]->getY();
                        $x2 = $vertices[2]->getX();
                        $y2 = $vertices[2]->getY();
                        imagerectangle($outputImage, $x1, $y1, $x2, $y2, 0x00ff00);
                    }
                }


                call_user_func($imageWriteFunc[$ext], $outputImage, $outFile);

                printf('Output image written to %s' . PHP_EOL, $outFile);

                //to display the image with boxes on surrounding the faces
                // header('Content-Type: image/jpeg');
                // imagejpeg($outputImage);
                // imagedestroy($outputImage);
            }

            $formatted_text = new HtmlString($image_face_content);

            return redirect()->route('home')
                ->with('success', "Number of faces on the image: $number_of_faces. Details of face detection on uploaded image $formatted_text");
        } catch (Exception $e) {
            return $e->getMessage();
        }

        $imageAnnotator->close();
    }

Let's upload this image to see the outcome

image.png

  • Outcome of the face detection on the image

image.png

It is possible that the face is joyful or smiling... Yea!!!

  • Detect Faces in a remote image

For your convenience, the Vision API can perform feature detection directly on an image file located in Google Cloud Storage or on the Web without the need to send the contents of the image file in the body of your request.

Caution: When fetching images from HTTP/HTTPS URLs, Google cannot guarantee that the request will be completed. Your request may fail if the specified host denies the request (for example, due to request throttling or DOS prevention), or if Google throttles requests to the site for abuse prevention. You should not depend on externally-hosted images for production applications.

//specify the path to the file on GCS
     $image = 'file_path...https://googleapis.com.......png';

            //run the facedection feature on the image
            $response = $imageAnnotatorClient->faceDetection($image);

Here's the tutorial repository

Thank you for reading this article!!!.

If you find this article helpful, please share it with your network and feel free to use the comment section for questions, answers, and contributions.

Did you find this article valuable?

Support Alemoh Rapheal Baja by becoming a sponsor. Any amount is appreciated!