Detect faces using Golang and OpenCV
OpenCV is a library made for computer vision that has been around for almost 20 years. I’ve used it through college and for personal projects using C++ and Python because it has quite a bit of support for those languages. But as I was starting to learn and use Go, I wondered if it is possible to use OpenCV with it. There were a few examples / tutorials on how to use OpenCV with Go but I found them too hacky or overly complicated. But the wrapper written by the folks at hybridgroup is the one that I’ve found that’s easiest to use and well documented. In this article I’ll be showing you how to get started with gocv and create a simple facial detector using Haar Cascades.
Requirements -
- Go
- OpenCV ( follow the links under installation )
- a webcam / camera
Installation -
linux : https://gocv.io/getting-started/linux/
macOS : https://gocv.io/getting-started/macos/
windows : https://gocv.io/getting-started/windows/
Example 1 -
In the first example let’s try create an app to open up a window that displays a video stream using your webcam.
Let’s first import the libraries we need.
import (
“log”
“gocv.io/x/gocv”
)
Then let’s create a VideoCapture object using the VideoCaptureDevice function. The VideoCaptureDevice function will allow you to capture a video stream using the webcam. The function takes in an integer as a parameter which represents the device ID.
webcam, err := gocv.VideoCaptureDevice(0)if err != nil { log.Fatalf(“error opening web cam: %v”, err)}defer webcam.Close()
Now we create an empty n-dimensional matrix. These matrix will be used to store the images we read from our camera later.
img := gocv.NewMat()defer img.Close()
To display the video stream we will need to create a window. This can be done by using the NewWindow function.
window := gocv.NewWindow(“webcamwindow”)defer window.Close()
Now let’s get into the fun part.
Since the video is a continuous stream of images we will have to create an infinite loop and keep reading from the camera indefinitely. For this we will use the Read method of the VideoCapture type. This will expect a Mat type ( the matrix we created above ) and it will return a boolean value indicating if a frame from the VideoCapture was read successfully or not.
for { if ok := webcam.Read(&img); !ok || img.Empty() { log.Println(“Unable to read from the webcam”) continue }
.
.
.
}
Finally let’s display the frame in the window we created. Then wait 50ms before moving to the next frame.
window.IMShow(img)window.WaitKey(50)
when we run the application we will see a new window opens up with the video stream from your camera.
Example 2 -
In this example let’s take the previous example and build upon it to detect faces using Haar Cascades.
But first .. what are Haar Cascades ?
In simpler terms Haar cascades are cascading classifiers that are trained based on the Haar Wavelet technique. It analyzes pixels in an image to detect features in it. To learn more about Haar-Cascades you can refer to these links.
Viola-Jones object detection framework
Cascading classifiers
Haar-like feature
You can download pre-trained Haar-Cascades in the opencv repository. For this example we will use the Haar-Cascade that allows us to detect a person’s frontal face.
Let’s create a classifier and feed the pre-trained Haar-Cascade file to the classifier. In this case I have already downloaded the opencv_haarcascade_frontalface_default.xml into the directory where our program is located.
harrcascade := “opencv_haarcascade_frontalface_default.xml”classifier := gocv.NewCascadeClassifier()classifier.Load(harrcascade)defer classifier.Close()
Then to detect the faces in the image lets call DetectMultiScale method. This function will take in frame ( Mat type ) that was just read from the camera and will return an array of Rectangle type. The size of the array represents the number of faces the classifier was able to detect in the frame. Then to make sure we see this detection let’s iterate through the list of rectangles and print the Rectangle object to the console and create a border around the rectangle that was detected. You can do this by calling the Rectangle function. This function will take in the Mat that was read by the camera, a Rectangle object that was returned from the DetectMultiScale method, a color and a thickness for the border.
for _, r := range rects {fmt.Println(“detected”, r)gocv.Rectangle(&img, r, color, 2)}
And finally, let’s run the application.
And there we go ! We have a simple face detector that’s written using Go. I’m planning on extending this series and build more cool things using Go and OpenCV. Stay tuned for future articles.
P.S ..
If you are interested, you can checkout the gRPC web server I wrote using python and OpenCV that streams a data whenever a face was detected. This allows you to create as many clients in different programming languages to subscribe to the server and read data from it.
Thanks for reading. Happy Hacking !