How to Build a Real-Time Face Recognition System with Dlib and OpenCV in Python
This guide walks through constructing a Python‑based real‑time face recognition pipeline using Dlib and OpenCV, covering dataset creation, feature extraction, Euclidean distance matching, and live video stream identification, complete with code snippets, parameter tuning tips, and troubleshooting advice.
Libraries used: dlib + OpenCV , Python version: 3.8 , Development environment: Jupyter Notebook (Anaconda3)
0. Dlib Face Feature Detection Principle
Extract facial landmarks (refer to relevant documentation).
Capture multiple images, compute a feature dataset and average feature vector, store them in a CSV file, then compare Euclidean distances between live camera face features and the stored averages to identify the closest match.
1. Build Face Feature Dataset
1. Install Dlib
Please refer to the official Dlib installation guide.
2. Construct Your Own Dataset
2.1 Capture Face Images
Capture 20 face images of size 256×256 from a video stream; these images form the training dataset.
The image size can be adjusted; larger images improve accuracy but increase training time.
Key considerations:
Lighting: discard overexposed or dark images; use the same device for data collection.
Code for capturing images:
import cv2
import dlib
import os
import sys
import random
# Store location
output_dir = 'D:/No1WorkSpace/JupyterNotebook/Facetrainset/Num&Name' # number + name
size = 256 # image side length
if not os.path.exists(output_dir):
os.makedirs(output_dir)
# Adjust brightness and contrast
def relight(img, light=1, bias=0):
w = img.shape[1]
h = img.shape[0]
for i in range(0, w):
for j in range(0, h):
for c in range(3):
tmp = int(img[j, i, c] * light + bias)
if tmp > 255:
tmp = 255
elif tmp < 0:
tmp = 0
img[j, i, c] = tmp
return img
# Use Dlib frontal_face_detector
detector = dlib.get_frontal_face_detector()
# Open camera
camera = cv2.VideoCapture(0)
index = 1
while True:
if index <= 20:
print('Being processed picture %s' % index)
success, img = camera.read()
gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
dets = detector(gray_img, 1)
for i, d in enumerate(dets):
x1 = d.top() if d.top() > 0 else 0
y1 = d.bottom() if d.bottom() > 0 else 0
x2 = d.left() if d.left() > 0 else 0
y2 = d.right() if d.right() > 0 else 0
face = img[x1:y1, x2:y2]
face = relight(face, random.uniform(0.5, 1.5), random.randint(-50, 50))
face = cv2.resize(face, (size, size))
cv2.imshow('image', face)
cv2.imwrite(os.path.join(output_dir, f'{index}.jpg'), face)
index += 1
key = cv2.waitKey(30) & 0xff
if key == 27:
break
else:
print('Finished!')
camera.release()
cv2.destroyAllWindows()
breakRunning effect:
2.2 Analyze Each Face's Feature Vector and Save to CSV
Extract 128‑dimensional features from the captured images and store them, along with their averages, in a CSV file.
The intermediate 68‑point feature sets can be discarded after averaging; they are shown here for learning purposes.
Code for feature extraction and CSV generation:
# Extract face features and save to CSV
# Features extraction from images and save into features_all.csv
from cv2 import cv2 as cv2
import os
import dlib
from skimage import io
import csv
import numpy as np
path_images_from_camera = "D:/No1WorkSpace/JupyterNotebook/Facetrainset/"
detector = dlib.get_frontal_face_detector()
predictor = dlib.shape_predictor("D:/No1WorkSpace/JupyterNotebook/model/shape_predictor_68_face_landmarks.dat")
face_rec = dlib.face_recognition_model_v1("D:/No1WorkSpace/JupyterNotebook/model/dlib_face_recognition_resnet_model_v1.dat")
def return_128d_features(path_img):
img_rd = io.imread(path_img)
img_gray = cv2.cvtColor(img_rd, cv2.COLOR_BGR2RGB)
faces = detector(img_gray, 1)
print("%-40s %-20s" % ("Detected image with faces:", path_img), '
')
if len(faces) != 0:
shape = predictor(img_gray, faces[0])
face_descriptor = face_rec.compute_face_descriptor(img_gray, shape)
else:
face_descriptor = 0
print("no face")
return face_descriptor
def return_features_mean_personX(path_faces_personX):
features_list_personX = []
photos_list = os.listdir(path_faces_personX)
if photos_list:
for i in range(len(photos_list)):
with open("D:/No1WorkSpace/JupyterNotebook/feature/featuresGiao"+str(i)+".csv", "w", newline="") as csvfile:
writer = csv.writer(csvfile)
print("%-40s %-20s" % ("Reading image:", path_faces_personX + "/" + photos_list[i]))
features_128d = return_128d_features(os.path.join(path_faces_personX, photos_list[i]))
print(features_128d)
writer.writerow(features_128d)
if features_128d == 0:
i += 1
else:
features_list_personX.append(features_128d)
else:
print("Warning: No images in " + path_faces_personX + '/', '
')
if features_list_personX:
features_mean_personX = np.array(features_list_personX).mean(axis=0)
else:
features_mean_personX = '0'
return features_mean_personX
people = os.listdir(path_images_from_camera)
people.sort()
with open("D:/No1WorkSpace/JupyterNotebook/feature/features_all.csv", "w", newline="") as csvfile:
writer = csv.writer(csvfile)
for person in people:
print("##### " + person + " #####")
features_mean_personX = return_features_mean_personX(os.path.join(path_images_from_camera, person))
writer.writerow(features_mean_personX)
print("Mean of features:", list(features_mean_personX), '
')
print("All face data saved to: D:/myworkspace/JupyterNotebook/People/feature/features_all2.csv")If you run the code directly, using Chinese directories may cause garbled characters.
Running effect:
2. Recognize Faces and Match Dataset
1. Principle
Compute Euclidean distance between the feature vector of a live face and each stored vector; the smallest distance indicates the best match.
Euclidean distance (or L2 norm) measures the straight‑line distance between two points in an m‑dimensional space.
2. Real‑Time Video Stream Face Recognition
Code for live face identification using the camera:
# Real‑time face recognition with camera
import os
import dlib
import csv
import time
import sys
import numpy as np
from cv2 import cv2 as cv2
import pandas as pd
facerec = dlib.face_recognition_model_v1("D:/No1WorkSpace/JupyterNotebook/model/dlib_face_recognition_resnet_model_v1.dat")
def return_euclidean_distance(feature_1, feature_2):
feature_1 = np.array(feature_1)
feature_2 = np.array(feature_2)
dist = np.sqrt(np.sum(np.square(feature_1 - feature_2)))
return dist
path_features_known_csv = "D:/No1WorkSpace/JupyterNotebook/feature/features_all.csv"
csv_rd = pd.read_csv(path_features_known_csv, header=None)
features_known_arr = []
for i in range(csv_rd.shape[0]):
features_someone_arr = []
for j in range(len(csv_rd.loc[i, :])):
features_someone_arr.append(csv_rd.loc[i, :][j])
features_known_arr.append(features_someone_arr)
print("Faces in Database:", len(features_known_arr))
detector = dlib.get_frontal_face_detector()
predictor = dlib.shape_predictor('D:/No1WorkSpace/JupyterNotebook/model/shape_predictor_68_face_landmarks.dat')
cap = cv2.VideoCapture(0)
cap.set(3, 480)
while cap.isOpened():
flag, img_rd = cap.read()
kk = cv2.waitKey(1)
img_gray = cv2.cvtColor(img_rd, cv2.COLOR_RGB2GRAY)
faces = detector(img_gray, 0)
font = cv2.FONT_HERSHEY_COMPLEX
pos_namelist = []
name_namelist = []
if kk == ord('q'):
break
else:
if len(faces) != 0:
features_cap_arr = []
for i, d in enumerate(faces):
shape = predictor(img_rd, d)
features_cap_arr.append(facerec.compute_face_descriptor(img_rd, shape))
for k in range(len(faces)):
name_namelist.append('unknown')
pos_namelist.append(tuple([faces[k].left(), int(faces[k].bottom() + (faces[k].bottom() - faces[k].top())/4)]))
e_distance_list = []
for i in range(len(features_known_arr)):
if str(features_known_arr[i][0]) != '0.0':
e_distance_tmp = return_euclidean_distance(features_cap_arr[k], features_known_arr[i])
e_distance_list.append(e_distance_tmp)
else:
e_distance_list.append(999999999)
similar_person_num = e_distance_list.index(min(e_distance_list))
if min(e_distance_list) < 0.4:
folder_name = 'D:/No1WorkSpace/JupyterNotebook/Facetrainset/'
file_names = os.listdir(folder_name)
key_id = 1
for name in file_names:
if similar_person_num + 1 == key_id:
name_namelist[k] = name[1:]
key_id += 1
# Save recognized face image
x1 = faces[k].top() if faces[k].top() > 0 else 0
y1 = faces[k].bottom() if faces[k].bottom() > 0 else 0
x2 = faces[k].left() if faces[k].left() > 0 else 0
y2 = faces[k].right() if faces[k].right() > 0 else 0
face = img_rd[x1:y1, x2:y2]
face = cv2.resize(face, (64, 64))
now_time = time.strftime("%Y-%m-%d-%H-%M-%S", time.localtime())
save_path = f"D:/No1WorkSpace/JupyterNotebook/KnownFacetrainset/{now_time}{name_namelist[k]}.jpg"
cv2.imwrite(save_path, face)
else:
# Save unknown face image
x1 = faces[k].top() if faces[k].top() > 0 else 0
y1 = faces[k].bottom() if faces[k].bottom() > 0 else 0
x2 = faces[k].left() if faces[k].left() > 0 else 0
y2 = faces[k].right() if faces[k].right() > 0 else 0
face = img_rd[x1:y1, x2:y2]
face = cv2.resize(face, (64, 64))
now_time = time.strftime("%Y-%m-%d-%H-%M-%S", time.localtime())
save_path = f"D:/No1WorkSpace/JupyterNotebook/UnKnownFacetrainset/{now_time}unknown.jpg"
cv2.imwrite(save_path, face)
# Draw rectangle and name
cv2.rectangle(img_rd, (faces[k].left(), faces[k].top()), (faces[k].right(), faces[k].bottom()), (0, 255, 255), 2)
cv2.putText(img_rd, name_namelist[k], pos_namelist[k], font, 0.8, (0, 255, 255), 1, cv2.LINE_AA)
cv2.putText(img_rd, "Face Recognition", (20, 40), font, 1, (0, 0, 255), 1, cv2.LINE_AA)
cv2.putText(img_rd, "Visitors: " + str(len(faces)), (20, 100), font, 1, (0, 0, 255), 1, cv2.LINE_AA)
cv2.imshow('camera', img_rd)
else:
cv2.putText(img_rd, "Face Recognition", (20, 40), font, 1, (0, 0, 255), 1, cv2.LINE_AA)
cv2.imshow('camera', img_rd)
cap.release()
cv2.destroyAllWindows()If you run the code directly, using Chinese directory names may cause garbled output.
Running effect:
In the screenshot, two known faces are correctly identified, while an unknown face is labeled as "unknown".
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
MaGe Linux Operations
Founded in 2009, MaGe Education is a top Chinese high‑end IT training brand. Its graduates earn 12K+ RMB salaries, and the school has trained tens of thousands of students. It offers high‑pay courses in Linux cloud operations, Python full‑stack, automation, data analysis, AI, and Go high‑concurrency architecture. Thanks to quality courses and a solid reputation, it has talent partnerships with numerous internet firms.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
