Python 中 3 種人臉辨識方法比較:Eigenfaces(PCA)、LBPH 與 DeepFace
Comparing 3 Face Recognition Approaches in Python: Eigenfaces (PCA), LBPH, and DeepFace
這篇教學以 Python 實作並比較 Eigenfaces(PCA)、LBPH 和 DeepFace,並測試三者在光線變暗時的表現。內容亦説明所需套件與環境設定,指出 Eigenfaces 和 LBPH 需要安裝 opencv-contrib-python 才能使用 cv2.face 模組。
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.
🧠 Overview of the 3 Approaches
-
Eigenfaces (PCA-based Representation)
- Extracts principal components (eigenvectors) of the face distribution.
- Pros: Fast and computationally lightweight.
- Cons: Very sensitive to lighting, pose, and requires uniform image sizes.
-
LBPH (Local Binary Pattern Histograms)
- Analyzes local pixel neighborhoods by thresholding surrounding pixels against the center pixel.
- Pros: Much more robust to illumination changes than Eigenfaces because it looks at relative local textures rather than global pixel intensities.
- Cons: Less accurate than deep learning on unconstrained real-world faces.
-
DeepFace (Deep Learning-based Recognition)
- Uses pre-trained Convolutional Neural Networks (CNNs) like VGG-Face, FaceNet, or ArcFace to generate high-dimensional face embeddings.
- Pros: State-of-the-art accuracy, highly robust to lighting and angles, and requires zero explicit training for verification.
- Cons: Requires heavier dependencies (TensorFlow/Keras) and more compute.
🛠️ Prerequisites & Avoiding 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'
How to Set Up Properly:
- Use Google Colab (Recommended for zero setup) or a Local Python Environment (VS Code, PyCharm, Jupyter).
- Install
opencv-contrib-pythoninstead of standardopencv-python. Standard OpenCV does not include thecv2.facemodule 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
💻 Option 1: Clean & Simple Exam/Lab Script (With Local Images)
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
# 1. Load and preprocess the small dataset (Resize to 100x100 & Grayscale)
def load_img(path):
img = cv2.imread(path, cv2.IMREAD_GRAYSCALE)
return cv2.resize(img, (100, 100))
# Training data: 2 images of Person 0, 1 image of Person 1
train_imgs = [load_img('p1_1.jpg'), load_img('p1_2.jpg'), load_img('p2_1.jpg')]
labels = np.array([0, 0, 1])
# Test data: Another image of Person 1
test_img = load_img('p2_2.jpg')
# Simulate illumination change (reduce brightness by 50%)
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
# ---------------------------------------------------------
# APPROACH 1: Eigenfaces (PCA-based)
# ---------------------------------------------------------
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)
# ---------------------------------------------------------
# APPROACH 2: LBPH (Local Binary Pattern Histograms)
# ---------------------------------------------------------
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)
# ---------------------------------------------------------
# APPROACH 3: DeepFace (Deep Learning-based)
# ---------------------------------------------------------
# DeepFace compares images directly without explicit training
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)
# ---------------------------------------------------------
# OUTPUT & COMPARISON (Expected Label = 1 / True)
# ---------------------------------------------------------
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']}")
☁️ Option 2: Self-Contained Google Colab Script (No Image Uploads Needed!)
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:
# Step 1: Install required libraries in Colab
!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
# Step 2: Load a small built-in face dataset (No manual image upload needed)
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)
# Resize all to 100x100
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])
# Simulate illumination change (50% darker)
dark_test_img = (test_img * 0.5).astype(np.uint8)
# Save images temporarily for DeepFace (requires RGB/file paths)
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))
# 1. Eigenfaces (PCA)
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])
# 2. LBPH
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])
# 3. DeepFace
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'])
📊 Final Comparison Summary
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 straightforward cv2.face API. |
Easiest — Just 1 line of code (DeepFace.verify()) with no training loop needed. |
💡 Key Takeaway
- If you are building on an ultra-low-power embedded device without a GPU, LBPH offers a great balance of speed and lighting resilience.
- For academic understanding of dimensionality reduction in computer vision, Eigenfaces (PCA) is a classic starting point.
- For production applications where accuracy and robustness are top priorities, DeepFace wins hands down.
Happy coding! Feel free to drop any questions in the comments below. 👇
來源:DEV Community · dev.to