Is there a library for detecting faces that have been rotated in the image plane? Or is there some way in which I could use a cascade for upright face detection with opencv to do it?
When it comes to a good, all-purpose face detector, I suggest using OpenCV's DNN face detector: It achieves a nice balance of speed and accuracy. As a deep learning-based detector, it's more accurate than its Haar cascade and HOG + Linear SVM counterparts. It's fast enough to run real-time on CPUs.
Once enabled, it harnesses not just the angle of your phone relative to the ground, but also your face's orientation. That means it considers how you're looking at your phone, not just what the accelerometer says, making it perfect for a bit of bedtime doomscrolling in portrait.
Face detection is implemented using the camshift algorithm. The camshift algorithm works on a search window that can find facial movements in each frame. The camshift algorithm that has been applied can calculate the size and location of the search window that will be used for the next frame.
Histogram of Oriented Gradients, also known as HOG, is a feature descriptor like the Canny Edge Detector, SIFT (Scale Invariant and Feature Transform) . It is used in computer vision and image processing for the purpose of object detection.
Here's a simple one I wrote with Python cv2
It's not the most efficient thing, and it uses the naive way suggested by etarion, but it works fairly well for just normal head tilting (It detect anything from -40 to 40 head tilt, which is roughly as much as you can tilt your head staying upright.
import cv2 from math import sin, cos, radians camera = cv2.VideoCapture(0) face = cv2.CascadeClassifier("haarcascade_frontalface_alt2.xml") settings = { 'scaleFactor': 1.3, 'minNeighbors': 3, 'minSize': (50, 50), 'flags': cv2.cv.CV_HAAR_FIND_BIGGEST_OBJECT|cv2.cv.CV_HAAR_DO_ROUGH_SEARCH } def rotate_image(image, angle): if angle == 0: return image height, width = image.shape[:2] rot_mat = cv2.getRotationMatrix2D((width/2, height/2), angle, 0.9) result = cv2.warpAffine(image, rot_mat, (width, height), flags=cv2.INTER_LINEAR) return result def rotate_point(pos, img, angle): if angle == 0: return pos x = pos[0] - img.shape[1]*0.4 y = pos[1] - img.shape[0]*0.4 newx = x*cos(radians(angle)) + y*sin(radians(angle)) + img.shape[1]*0.4 newy = -x*sin(radians(angle)) + y*cos(radians(angle)) + img.shape[0]*0.4 return int(newx), int(newy), pos[2], pos[3] while True: ret, img = camera.read() for angle in [0, -25, 25]: rimg = rotate_image(img, angle) detected = face.detectMultiScale(rimg, **settings) if len(detected): detected = [rotate_point(detected[-1], img, -angle)] break # Make a copy as we don't want to draw on the original image: for x, y, w, h in detected[-1:]: cv2.rectangle(img, (x, y), (x+w, y+h), (255,0,0), 2) cv2.imshow('facedetect', img) if cv2.waitKey(5) != -1: break cv2.destroyWindow("facedetect")
Personally, I don't know of a library. But, what I can say is, use an eye detection Haar Cascade, and draw a line between the eyes. Then, you can use the atan
function and find the angle by which the head is rotated. (Assuming that the person has both eyes on the same horizontal level when head is not rotated)
deg = atan( (leftEye.y - rightEye.y) / (leftEye.x - rightEye.x) )
Once you get this angle, rotate the image you have by negative deg
degrees and you should have a face which can be detected using the Haar Cascades.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With