Golang : Detect face in uploaded photo like GPlus




Problem:

You have an app or website that allow users to upload their profile photo to your server. However, you want to discourage the users from uploading profile photo or avatar that has no real human face. Also you want to impress the users that your website or app is backed a smart artificial intelligence software.

Something like what Google Plus did when a user uploaded a picture without an actual human face. It will tease the user with....

"Are you sure people will recognize you in this photo? It doesn't seem to have a face in it."

Are you sure people will recognize you in this photo? It doesn't seem to have a face in it image

How to do that?

Solution:

Combine these two previous tutorials how to upload file in Golang and how to detect faces or vehicles in a photo with OpenCV to produce the backend server program below.

Here you go!


 package main

 import (
 "fmt"
 "github.com/lazywei/go-opencv/opencv"
 "image"
 gif "image/gif"
 _ "image/jpeg"
 _ "image/png"
 "io"
 "net/http"
 "os"
 )

 var cascade = new(opencv.HaarCascade)

 func uploadHandler(w http.ResponseWriter, r *http.Request) {

 // the FormFile function takes in the POST input id file
 file, header, err := r.FormFile("file")

 if err != nil {
 fmt.Fprintln(w, err)
 return
 }

 defer file.Close()

 // put the uploaded file in the same directory
 // as the server executable
 out, err := os.Create(header.Filename)
 if err != nil {
 fmt.Fprintf(w, "Unable to create the file for writing. Check your write access privilege")
 return
 }

 defer out.Close()

 // write the content from POST to the file
 _, err = io.Copy(out, file)
 if err != nil {
 fmt.Fprintln(w, err)
 }

 // now try to detect face in the file

 // we will use Go's method to load the upload file
 // instead of openCV.LoadImage
 // because we want to detect if the user supplies animated GIF or not
 imageFile, err := os.Open(header.Filename)

 if err != nil {
 fmt.Fprintf(w, "Unable to read uploaded file. ")
 return
 }

 defer imageFile.Close()

 img, _, err := image.Decode(imageFile)

 if err != nil {
 fmt.Fprintf(w, "Unable to decode uploaded file. ")
 return
 }

 buffer := make([]byte, 512)
 imageFile.Seek(0, 0) // reset reader
 _, err = imageFile.Read(buffer)

 if err != nil {
 fmt.Fprintf(w, "Unable to read uploaded file. ")
 return
 }

 filetype := http.DetectContentType(buffer)
 // check if image is GIF and if yes, check to see if it is animated GIF by
 // counting the LoopCount number

 if filetype == "image/gif" {
 imageFile.Seek(0, 0)
 // warn if image is animated GIF
 gif, err := gif.DecodeAll(imageFile)

 if err != nil {
 fmt.Fprintf(w, "Unable to read uploaded .gif file. ")
 return
 }
 if gif.LoopCount != 0 {
 fmt.Println("Animated gif detected. Will only scan for faces in the 1st frame.")
 }
 }

 cascade = opencv.LoadHaarClassifierCascade("./haarcascade_frontalface_alt.xml")
 defer cascade.Release()

 // convert Go's image.Image type to OpenCV's IplImage(Intel Image Processing Library)
 openCVimg := opencv.FromImage(img)
 defer openCVimg.Release()

 if openCVimg != nil {
 faces := cascade.DetectObjects(openCVimg)

 if len(faces) == 0 {

 fmt.Fprintf(w, "Are you sure people will recognize you in this photo? It doesn't seem to have a face in it.\n") // <------- here !
 } else {
 fmt.Fprintf(w, "Detected [%v] faces in image.\n", len(faces))
 fmt.Printf("Detected [%v] faces in image.\n", len(faces))
 }
 } else {
 fmt.Fprintf(w, "OpenCV FromImage error")
 }

 }

 func home(w http.ResponseWriter, r *http.Request) {
 html := `<html>
 <title>Upload photo and detect face</title>
 <body>

 <form action="http://localhost:8888/receiveupload" method="post" enctype="multipart/form-data">
 <label for="file">Filename:</label>
 <input type="file" name="file" id="file"><br>
 <input type="submit" name="submit" value="Submit">
 </form>

 </body>
 </html>`

 w.Write([]byte(fmt.Sprintf(html)))
 }

 func main() {

 http.HandleFunc("/receiveupload", uploadHandler)
 http.HandleFunc("/", home)

 http.ListenAndServe(":8888", nil)
 }

  • Build the program and run it.
  • Point your browser to localhost:8888 and you will be prompted with a page to upload an image file.
  • Play around with photos that have a human face and those that don't. You will see different output.

Happy coding!

References:

https://www.socketloop.com/tutorials/golang-upload-file

https://www.socketloop.com/tutorials/golang-detect-number-of-faces-or-vehicles-in-a-photo

  See also : Golang : Detect number of faces or vehicles in a photo





By Adam Ng

IF you gain some knowledge or the information here solved your programming problem. Please consider donating to the less fortunate or some charities that you like. Apart from donation, planting trees, volunteering or reducing your carbon footprint will be great too.


Advertisement