Using the face_recognition Library in Python
Detect faces, recognize people, and build a real-time webcam recognition system with just a few lines of code, explained with working examples, real output, and the reasoning behind every step.
1What is face_recognition
Face recognition has gone from science fiction to daily reality, it unlocks phones, powers surveillance systems, and quietly runs inside a growing number of smart apps. Python makes it surprisingly approachable to implement, largely thanks to the face_recognition library.
face_recognition is a Python library built directly on top of dlib and its deep learning face recognition model, wrapped in a much simpler, high-level API. With it you can:
- Detect faces in images or video
- Recognize and identify specific people
- Extract facial features and compare faces numerically
- Label known people automatically in a batch of photos
It is known for three things in particular: it is extremely accurate, since it is built on deep learning rather than older classical methods, it is very easy to use, and it is open-source and actively maintained.
face_recognition does under the hood is dlib: the same HOG or CNN-based detector, the same 68-point shape predictor, the same 128-dimensional embedding model. If you want to understand exactly what is happening beneath this library's simple function calls, or need lower-level control, the dlib in Python guide covers the same pipeline one layer down.
2Installation
First, make sure you are using a supported Python version, Python 3.6 through 3.11 at the time of writing. Because this library depends on dlib, which compiles C++ code, the install has a couple of extra steps compared to a typical pip package.
1. Install CMake
dlib's build process needs CMake available first:
pip install cmake
2. Install dlib and face_recognition
pip install dlib pip install face_recognition
You can check the package details on its PyPI page before installing if you want to confirm the latest version.
pip install dlib succeeds, since dlib compiles from source. On macOS, install CMake through Homebrew instead if the pip version gives you trouble: brew install cmake. The full detail on dlib's build requirements is covered in the dlib in Python guide, since this library inherits the exact same installation constraints.
3Preparing your images
Before writing any recognition code, it helps to organize your images into a predictable folder structure. A typical layout separates the people you already know from the photo you want to identify:
- Place clear, front-facing images of each known person in
known/, one photo per person, named after them. - Place the photo you want to identify in
unknown/.
4Basic face detection
The simplest possible use of the library is just finding how many faces exist in an image and where they are:
import face_recognition image = face_recognition.load_image_file("unknown/test.jpg") face_locations = face_recognition.face_locations(image) print(f"Found {len(face_locations)} face(s) in the image.")
Loads an image directly as a NumPy array in RGB order, ready to feed into the rest of the library's functions. This matters because it is the opposite of OpenCV's default: if you ever mix the two libraries in one script, remember cv2.imread() gives you BGR while this gives you RGB, and passing the wrong order into either library silently produces wrong-looking results rather than an error. See the OpenCV in Python guide for the full BGR versus RGB explanation.
face_locations() returns a list of tuples, each in (top, right, bottom, left) order, one tuple per detected face.
5Comparing two faces
Detecting a face and identifying whose face it is are two different problems. To compare faces, you first convert each one into a numeric encoding, then check whether two encodings are close enough to count as a match.
known_image = face_recognition.load_image_file("known/alice.jpg") unknown_image = face_recognition.load_image_file("unknown/test.jpg") alice_encoding = face_recognition.face_encodings(known_image)[0] unknown_encoding = face_recognition.face_encodings(unknown_image)[0] results = face_recognition.compare_faces([alice_encoding], unknown_encoding) if results[0]: print("This is Alice!") else: print("Not Alice.")
face_encodings() returns a list, one 128-dimensional encoding per face found in the image, which is why the code indexes into it with [0] to grab the first (and in these examples, only) face. compare_faces() takes a list of known encodings to check against and a single new encoding, returning a list of booleans indicating which known encodings matched.
face_encodings() returns an empty list, and indexing it with [0] raises an IndexError. Section 10 covers handling this safely, it is one of the most common errors beginners hit with this library.
6Identifying multiple people in a photo
A more realistic scenario is not comparing against one known person, but checking a photo against an entire folder of known faces at once, and labeling each detected face with whichever known person it matches.
import os known_encodings = [] known_names = [] for filename in os.listdir("known"): image = face_recognition.load_image_file(f"known/{filename}") encoding = face_recognition.face_encodings(image)[0] known_encodings.append(encoding) known_names.append(os.path.splitext(filename)[0]) # Load unknown image image = face_recognition.load_image_file("unknown/test.jpg") face_locations = face_recognition.face_locations(image) face_encodings = face_recognition.face_encodings(image, face_locations) for (top, right, bottom, left), face_encoding in zip(face_locations, face_encodings): matches = face_recognition.compare_faces(known_encodings, face_encoding) name = "Unknown" if True in matches: first_match_index = matches.index(True) name = known_names[first_match_index] print(f"Detected: {name}")
The first loop builds a lookup of every known encoding and the name it belongs to, taken directly from each file's filename minus its extension. The second half then detects every face in the unknown image and checks each one against the entire known list at once, rather than comparing to just a single person as in the previous section.
matches.index(True) returns only the first match it finds, which is fine for small, curated datasets but can pick the wrong person if two known faces are similar enough to both cross the match threshold. For larger datasets, face_recognition.face_distance(), covered in section 9, lets you pick the closest match rather than just the first one.
7Real-time recognition with a webcam
Combining everything so far with OpenCV's video capture produces a live recognition system that labels a known face directly on the video feed.
import face_recognition import cv2 # Load known face known_image = face_recognition.load_image_file("known/alice.jpg") known_encoding = face_recognition.face_encodings(known_image)[0] known_names = ["Alice"] video_capture = cv2.VideoCapture(0) while True: ret, frame = video_capture.read() small_frame = cv2.resize(frame, (0, 0), fx=0.25, fy=0.25) rgb_small_frame = cv2.cvtColor(small_frame, cv2.COLOR_BGR2RGB) face_locations = face_recognition.face_locations(rgb_small_frame) face_encodings = face_recognition.face_encodings(rgb_small_frame, face_locations) for (top, right, bottom, left), face_encoding in zip(face_locations, face_encodings): matches = face_recognition.compare_faces([known_encoding], face_encoding) name = "Unknown" if True in matches: name = known_names[0] # Scale back up top *= 4; right *= 4; bottom *= 4; left *= 4 cv2.rectangle(frame, (left, top), (right, bottom), (0, 255, 0), 2) cv2.putText(frame, name, (left, top - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.9, (255, 255, 255), 2) cv2.imshow('Video', frame) if cv2.waitKey(1) == ord('q'): break video_capture.release() cv2.destroyAllWindows()
Running face detection and encoding on a full-resolution webcam frame every single loop iteration is expensive. Shrinking the frame to a quarter size with fx=0.25, fy=0.25 before detection speeds this up enormously, since detection cost scales with pixel count.
The coordinates returned from that shrunk frame are also in the shrunk frame's scale, so multiplying top, right, bottom, and left each by 4 maps them back to the original full-size frame before drawing the rectangle, otherwise the box would appear a quarter of the correct size in the top-left corner of the actual face.
video_capture.release() keeps the webcam locked after the script ends. See the working with camera feed guide for the full explanation of this pattern and other camera handling details.
8Tips for better accuracy
- Use high-resolution images for face encoding. Low-resolution or heavily compressed reference photos give the encoding model less detail to work with.
- Make sure faces are front-facing and well-lit. Extreme angles, heavy shadows, or backlighting reduce accuracy more than almost any other factor.
- For faster performance, resize frames to a quarter scale for video, as shown in the webcam example above, this is the single biggest speed win available with almost no accuracy cost.
9Advanced features
| Feature | Method |
|---|---|
| Get face landmarks | face_recognition.face_landmarks() |
| Find facial features | Returns coordinates for eyes, nose, lips, and jaw |
| Compare multiple faces | compare_faces() with a list of multiple known encodings |
| Get face distances | face_recognition.face_distance() |
face_distance() deserves a closer look, since it solves the "which match is actually closest" problem mentioned back in section 6. Instead of a simple true or false, it returns the actual numeric distance between encodings, letting you pick the smallest one explicitly:
distances = face_recognition.face_distance(known_encodings, face_encoding) best_match_index = distances.argmin() if distances[best_match_index] < 0.6: name = known_names[best_match_index]
This is generally the more reliable approach once you have more than a couple of known people in your dataset.
10Troubleshooting
| Problem | Solution |
|---|---|
| No faces found | Use clear, front-facing, well-lit images, extreme angles or poor lighting are the most common cause |
IndexError on encoding | Check that face_encodings() actually returned a result before indexing into it with [0], an empty list means no face was detected |
| Slow webcam performance | Resize the frame to a quarter scale as shown in section 7, or use a GPU-accelerated build of dlib if your hardware supports it |
Guarding against the empty-list case from the second row looks like this in practice:
encodings = face_recognition.face_encodings(image) if len(encodings) == 0: print("No face detected in this image.") else: encoding = encodings[0] # continue with recognition
11What you can build
- A smart door lock using a Raspberry Pi and camera module, unlocking automatically for recognized faces.
- An attendance system for schools, checking students in against a known roster instead of manual sign-in.
- A face-sorting photo gallery, automatically grouping photos by which known people appear in them.
- Real-time face-based tagging for security cameras, flagging when a known or unknown person appears on camera.
12Where to go next
The face_recognition library makes face detection and recognition in Python extremely accessible, even for complete beginners. With just a few lines of code you can build genuinely impressive, real-world projects that leverage the same deep learning models used in production systems.
You now know how to detect and identify faces in images and video, compare faces against known profiles, and build real-time recognition with a webcam. A few directions to take it further:
- Drop down a level to dlib directly if you need more control over the detection or encoding process than this library's simplified API exposes.
- Build a complete, persistent system with a proper database of known faces rather than a folder of images, covered in the full face recognition system build.
- Combine this with general OpenCV image handling techniques from the OpenCV in Python guide for preprocessing steps like resizing, cropping, or enhancing images before recognition.
For the broader sequence of what to study before and after this topic, see the Python roadmap.
