cd /news/computer-vision/comparing-3-face-recognition-approac… · home › topics › computer-vision › article
[ARTICLE · art-157337] src=dev.to ↗ pub= topic=computer-vision verified=true sentiment=· neutral

Comparing 3 Face Recognition Approaches in Python: Eigenfaces (PCA), LBPH, and DeepFace

A developer implemented and compared three Python face recognition approaches — Eigenfaces (PCA), LBPH, and DeepFace — on a small sample dataset, testing each against a simulated 50% brightness reduction to gauge robustness to illumination changes. The writeup includes runnable code, notes that standard opencv-python lacks the cv2.face module required for Eigenfaces and LBPH (fixed by installing opencv-contrib-python), and offers a Google Colab variant that pulls real faces from Scikit-Learn's LFW dataset.

by read4 min views2 publishedOct 25, 2026

Face recognition has evolved significantly—from classical statistical methods like Eigenfaces (PCA) and texture-based descriptors like LBPH (Local Binary Pattern Histograms) to modern deep learning frameworks like DeepFace.

In this post, we will implement and compare all three approaches on a small dataset in Python, test how they hold up against illumination changes (e.g., low lighting), and look at how to run the code effortlessly without running into environment issues.

Eigenfaces (PCA-based Representation)

LBPH (Local Binary Pattern Histograms)

DeepFace (Deep Learning-based Recognition)

ModuleNotFoundError: No module named 'cv2' A common mistake when running this code is executing it inside lightweight online compilers (like Programiz or OnlineGDB), which results in:

Traceback (most recent call last):
  File "/box/main.py", line 1, in <module>
    import cv2
ModuleNotFoundError: No module named 'cv2'

opencv-contrib-python`` opencv-python. Standard OpenCV does cv2.face module needed for Eigenfaces and LBPH! Run this in your terminal:

pip uninstall opencv-python -y
pip install opencv-contrib-python deepface scikit-learn tf-keras

If you have 4 sample face images in your project directory (p1_1.jpg, p1_2.jpg for Person 0, and p2_1.jpg, p2_2.jpg for Person 1), here is the cleanest implementation:

import cv2
import numpy as np
from deepface import DeepFace

def load_img(path):
    img = cv2.imread(path, cv2.IMREAD_GRAYSCALE)
    return cv2.resize(img, (100, 100))

train_imgs = [load_img('p1_1.jpg'), load_img('p1_2.jpg'), load_img('p2_1.jpg')]
labels = np.array([0, 0, 1])

test_img = load_img('p2_2.jpg')

dark_test_img = np.clip(test_img * 0.5, 0, 255).astype(np.uint8)
cv2.imwrite('dark_test.jpg', dark_test_img) # Save for DeepFace

eigen_model = cv2.face.EigenFaceRecognizer_create()
eigen_model.train(train_imgs, labels)

pred_eigen_norm, _ = eigen_model.predict(test_img)
pred_eigen_dark, _ = eigen_model.predict(dark_test_img)

lbph_model = cv2.face.LBPHFaceRecognizer_create()
lbph_model.train(train_imgs, labels)

pred_lbph_norm, _ = lbph_model.predict(test_img)
pred_lbph_dark, _ = lbph_model.predict(dark_test_img)

df_norm = DeepFace.verify('p2_1.jpg', 'p2_2.jpg', enforce_detection=False)
df_dark = DeepFace.verify('p2_1.jpg', 'dark_test.jpg', enforce_detection=False)

print("--- COMPARISON RESULTS (Target: Person 1) ---")
print(f"1. Eigenfaces | Normal: {pred_eigen_norm == 1} | Dark: {pred_eigen_dark == 1}")
print(f"2. LBPH       | Normal: {pred_lbph_norm == 1} | Dark: {pred_lbph_dark == 1}")
print(f"3. DeepFace   | Normal: {df_norm['verified']} | Dark: {df_dark['verified']}")

Don't have sample photos handy? Paste this directly into a Google Colab cell. It automatically installs the dependencies and fetches real faces from Scikit-Learn's built-in LFW (Labeled Faces in the Wild) dataset:

!pip install -q opencv-contrib-python deepface scikit-learn

import cv2
import numpy as np
from deepface import DeepFace
from sklearn.datasets import fetch_lfw_people

lfw = fetch_lfw_people(min_faces_per_person=10, resize=1.0)
img_p1_1 = (lfw.images[0] * 255).astype(np.uint8) # Person 0, Image 1
img_p1_2 = (lfw.images[1] * 255).astype(np.uint8) # Person 0, Image 2
img_p2_1 = (lfw.images[2] * 255).astype(np.uint8) # Person 1, Image 1 (Train)
test_img = (lfw.images[3] * 255).astype(np.uint8) # Person 1, Image 2 (Test)

train_imgs = [cv2.resize(x, (100, 100)) for x in [img_p1_1, img_p1_2, img_p2_1]]
test_img = cv2.resize(test_img, (100, 100))
labels = np.array([0, 0, 1])

dark_test_img = (test_img * 0.5).astype(np.uint8)

cv2.imwrite('train_p2.jpg', cv2.cvtColor(train_imgs[2], cv2.COLOR_GRAY2BGR))
cv2.imwrite('test_norm.jpg', cv2.cvtColor(test_img, cv2.COLOR_GRAY2BGR))
cv2.imwrite('test_dark.jpg', cv2.cvtColor(dark_test_img, cv2.COLOR_GRAY2BGR))

eigen = cv2.face.EigenFaceRecognizer_create()
eigen.train(train_imgs, labels)
print("Eigenfaces (Normal, Dark):", eigen.predict(test_img)[0], eigen.predict(dark_test_img)[0])

lbph = cv2.face.LBPHFaceRecognizer_create()
lbph.train(train_imgs, labels)
print("LBPH       (Normal, Dark):", lbph.predict(test_img)[0], lbph.predict(dark_test_img)[0])

df_norm = DeepFace.verify('train_p2.jpg', 'test_norm.jpg', enforce_detection=False)
df_dark = DeepFace.verify('train_p2.jpg', 'test_dark.jpg', enforce_detection=False)
print("DeepFace   (Normal, Dark):", df_norm['verified'], df_dark['verified'])

Here is how the three approaches stack up across key metrics:

Evaluation Metric 1. Eigenfaces (PCA) 2. LBPH 3. DeepFace
Accuracy Low to Moderate (struggles with pose and lighting variations). Moderate to High on small, controlled datasets. Very High (Backed by state-of-the-art CNNs).
Robustness Under Illumination Changes Poor — Global pixel intensity changes drastically shift PCA eigenvectors. Good — Local pixel thresholding preserves texture patterns even when darkened. Excellent — Pre-trained on millions of faces across diverse lighting conditions.
Ease of Implementation Medium — Requires strictly identical image dimensions and grayscale conversion. Easy — Handles varied sizes and uses the straightforwardcv2.face API. Easiest — Just 1 line of code (DeepFace.verify() ) with no training loop needed.

Happy coding! Feel free to drop any questions in the comments below. 👇

── more in #computer-vision 4 stories · sorted by recency
── more on @opencv 3 stories trending now
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain — perfect for shipping the agent you just read about.

$git push zahid main
→ Live at https://your-agent.zahid.host ✓
Get free account → Pricing
from €0/mo · no card required
LIVE [news/comparing-3-face-rec…] indexed:0 read:4min 2026-10-25 · —