In one of my previous articles, I elaborated on using OpenCV with python to switch on a user’s webcam, and to display the live feed. As a fun-ish Python project, I also created a GUI to pick out a spot in the feed and display its colour scheme, in RGB values.
Scurrying around in the OpenCV documentation, I realized how little I knew, and how deep the proverbial rabbit hole goes, regarding this library’s scope of implementation. One of the topics that immediately piqued my curiosity was live object detection.
Haar Cascades, an Introduction
The one method that I kept seeing again and again, which is used hand-in-glove with OpenCV for object detection, is the use of Haar Cascades. A bit more primitive than more modern techniques, using Haar Cascades provides nigh-unparalleled speed, although with the caveat of frequent false-positives. Even when creating this project, I noticed that the algorithm had a strange obsession of claiming my neck as a second face.
Despite its shortcomings, it’s still widely used, even while creating AI models. The method consists of an algorithm which can detect a particular type of object in real-time, based on pre-trained parameters. A Haar Classifier is used, which can detect features like edges and lines, and determines whether there is a particular object in the video, and can demarcate in what region it is.
For example, in terms of face detection, the HaarClassifier will be able to differentiate eye and nose regions by comparing the brighter and darker pixels. The Classifier works by using similar patterns and comparisons.
Creating a Face Detection Project in Python
Well, there’s no better way to learn than diving off of the deep end. So, I decided to borrow what I learnt from my last project and add a face detection functionality to the GUI.
First off, installing all the necessary packages, via the terminal:
pip install opencv-python
pip install Pillow
pip install tk
And subsequently, importing all the aforementioned packages:
import cv2 from tkinter import * from PIL import Image, ImageTk
Using OpenCV’s method to access the devices webcam:
vc = cv2.VideoCapture(0)
A fact that I failed to mention in my previous article, is that the parameter “0” is passed into the method to access the webcam. The address for any required video, from the file directory can also be passed as a parameter, to load the video
vc = cv2.VideoCapture("Jack Ryan.mp4")
Loading the Haar Cascade Classifier:
face_classifier = cv2.CascadeClassifier(cv2.data.haarcascades + "haarcascade_frontalface_default.xml")
In this step we are using an XML file, which contains the instructions for the Haar Classifier. Here’s a snippet of the file:
From within the file we can modify the parameters as per our requirements.
This particular Classifier facilitates detection of front-facing portraits.
Now, I have to make it absolutely clear, that there is a method built into OpenCV which displays the video feed, which runs indefinitely, until the user presses a specified key.
while True: success, vf = vc.read() if (success == False): break gray = cv2.cvtColor(vf, cv2.COLOR_BGR2GRAY) fs = face_classifier.detectMultiScale(gray, 1.1, 5, minSize=(40, 40)) for (x, y, w, h) in fs: cv2.rectangle(vid, (x, y), (x + w, y + h), (0, 255, 0), 4) cv2.imshow("Face Detection", vf) if cv2.waitKey(1) & 0xFF == ord("q"): break vc.release() cv2.destroyAllWindows()
It’s a neat method. However, sometimes, a person just has to flex their Tkinter GUI skills. Using the code from my last python project to integrate the feed into a GUI;
window = Tk() window.title("Video feed") window.geometry("1200x700") button = Button(window,text="Click to detect face") button.grid(row=0, column=0) label = Label(window, height=720, width=1280, text="Video feed here") label.grid(row=1, column=1, columnspan=1) def show_frames(): success, vf = vc.read() if (success==False): return gray = cv2.cvtColor(vf, cv2.COLOR_BGR2GRAY) fs = face_classifier.detectMultiScale(gray, 1.1, 5, minSize=(40, 40)) for (x, y, w, h) in fs: cv2.rectangle(vf, (x, y), (x + w, y + h), (0, 255, 0), 4) frame = cv2.cvtColor(vf, cv2.COLOR_BGR2RGB) img = Image.fromarray(frame) imgtk = ImageTk.PhotoImage(image = img) label.imgtk = imgtk label.configure(image = imgtk) label.after(20, show_frames) button.config(command=show_frames) window.mainloop()
In both methods, the frames from the feed are being converted to grayscale, and passed into the classifier.
gray = cv2.cvtColor(vf, cv2.COLOR_BGR2GRAY)
fs = face_classifier.detectMultiScale(gray, 1.1, 5, minSize=(40, 40))
Using another OpenCV method, a rectangle is mapped onto the frame, where the classifier has detected the face.
for (x, y, w, h) in fs:
cv2.rectangle(vf, (x, y), (x + w, y + h), (0, 255, 0), 4)
Using the program to detect a face
I tried loading a clip from Patriot Games (fantastic film, by the way) into the face detection model. The model clearly has no problem detecting dear old Dr. Jack Ryan.
The model can also demarcate multiple faces, both in a video clip, and live webcam feed.