Raspberry Pi is a powerful tool, and when coupled with OpenCV library can be used for many image processing projects. At the end of this article you will learn to build one such application ‘Face detection’. Face detection is exactly what is sounds like, the camera will capture an image and find the faces in the image and show the user. For this purpose, we will use a cascade classifier that OpenCV already has in order to detect the face. In this project we will also use the Raspberry Pi camera module to take the pictures for analysis.
What are cascade classifiers?
Cascade classifier is a training approach wherein there are hundreds of positive and negative examples that are agglomerated. The data thus made are stored as XML files and can be used in to detect the object that it was trained for. Thus, ensuring that the target is identified irrespective of variations and lighting. ‘Cascade’ implies that there are several simple stages that are applied till either the image passes all the stages, or fails at one stage. In this application we use haar cascade classifier.
Hardware requirements:
- Raspberry Pi with OS installed (available on the official website)
- Camera module
- Power cable
- Monitor
- HDMI connector
- USB or Bluetooth mouse
- USB or Bluetooth keyboard
Setup:
Software:
Before starting the project, download OpenCV and extract it from the official website. After which, if you open the file you should see a sub folder called sources. In sources, click on data sub-folder, in which you can open a file called haarcascades.
In this list, copy the ‘haarcascade_frontalface_default’ XML and paste it in the same folder that you are going to use to save your program.
Hardware:
- Connect the Raspberry Pi camera module and enable it (for any help on that, check out our article on that https://iot4beginners.com/how-to-capture-image-and-video-in-raspberry-pi/).
- Use the HDMI cable to connect your Raspberry Pi to a display
- Connect your mouse and keyboard as well (through USB or Bluetooth)
- Make sure to install NumPy and OpenCV library on your Raspberry Pi before you start
Code:
import numpy as np import cv2 import io import picamera stream = io.BytesIO() with picamera.PiCamera() as camera: camera.capture(stream,format='jpeg') numparray = numpy.fromstring(stream.getvalue(),dtype=numpy.uint8) image = cv2.imdecode(numparray,1) faceDetectset= cv2.CascadeClassifier('haarcascade_frontalface_default.xml'); #convert to gray scale gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) #now we can look for faces faces = faceDetectset.detectMultiScale(gray,1.3,5); for (x,y,w,h) in faces: #draw box on original cv2.rectangle(img,(x,y),(x+w,y+h),(0,0,0),2) #show the output in window cv2.imshow("Detected",img) if cv2.waitKey()==ord('q'): break; stream.truncate(0) cv2.destroyAllWindows()
Code Explanation:
First we start the code by importing the libraries necessary for the program.
import numpy as np import cv2 import io import picamera import time
We then create a stream to avoid using memory space on your Pi for every image you capture. After this, we use the Raspberry Pi camera to capture an image after showing preview.
stream = io.BytesIO() #capture image with picamera.PiCamera() as camera: camera.start_preview() time.sleep(5) camera.capture(stream,format='jpeg')
To use the image captured with OpenCV and make the processing speed faster, we convert the image to a NumPy array. We then assign the variable name ‘image’ to read data from the ‘numparray’ and decode to image format.
numparray = numpy.fromstring(stream.getvalue(),dtype=numpy.uint8) image = cv2.imdecode(numparray,1)
Remember that XML file we found and pasted in the same folder as your program? We are going to finally use that by assigning a variable name to it. It is also worthy to note that classifiers usually only work for gray scale images, but the image your pi cam takes is color (i.e.,RGB). As a result, we have to convert the image to gray scale.
faceDetectset= cv2.CascadeClassifier('haarcascade_frontalface_default.xml'); gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
Now we can look for faces and using the function .detectMultiScale() we can find the coordinates of the object we are looking for (also as I’ve specified in the program feel free to play around with the scaling factors). Which in this case, is the face! After finding the face in the image, we then draw a rectangle around the location of the face to indicate it. For this, the parameters we specify are the variable name of the image, the start and end coordinates, the color specification for the rectangle (in this case, black) and then the thickness.
After the box is drawn, we then display the original colored image with the box drawn on it in a separate window called ‘Detected’ until the key ‘e’ is clicked to exit the window.
faces = faceDetectset.detectMultiScale(gray,1.3,5);#scaling factors can be varied for (x,y,w,h) in faces: cv2.rectangle(img,(x,y),(x+w,y+h),(0,0,0),2) cv2.imshow("Detected",img) if cv2.waitKey()==ord('e'): break; stream.truncate(0) cv2.destroyAllWindows()
Output:
And with that, your project is over. Feel free to move around and take pictures under different lighting conditions, face orientations and expressions and you should be able to see the program detecting and drawing a box around your face! This is a fun project that is a precursor towards building a face recognition system which requires you to create your own classifier or tree with images of specific people that you want to detect.