Initial commit

This commit is contained in:
2026-03-31 13:27:52 +02:00
commit 3530d7f4c5
9 changed files with 233 additions and 0 deletions

50
.gitignore vendored Normal file
View File

@@ -0,0 +1,50 @@
# ── Python ──────────────────────────────────────────────────────────────────
__pycache__/
*.py[cod]
*.pyo
*.pyd
*.pyc
# ── Environnements virtuels ──────────────────────────────────────────────────
venv/
.venv/
env/
ENV/
Pipfile.lock
# ── Secrets ───────────────────────────────────────────────────────────────────
.env
.env.*
secret.env
secrets.py
*.secret
credentials.json
token.json
# ── Logs ─────────────────────────────────────────────────────────────────────
*.log
logs/
# ── IDE ───────────────────────────────────────────────────────────────────────
.vscode/
.idea/
*.swp
.DS_Store
Thumbs.db
# ── Tests / Coverage ─────────────────────────────────────────────────────────
.coverage
htmlcov/
.pytest_cache/
# ── Build ─────────────────────────────────────────────────────────────────────
dist/
build/
*.egg-info/
# ── Modèles IA (trop lourds pour git) ───────────────────────────────────────
*.gguf
*.bin
*.safetensors
models/
weights/

7
LICENSE.md Normal file
View File

@@ -0,0 +1,7 @@
Copyright (c) 2011-2019 GitHub Inc.
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

61
README.md Normal file
View File

@@ -0,0 +1,61 @@
# Easy Facial Recognition
Recognition by minimum norm between vectors (128D dlib descriptor)
![Alt Text](readme.gif)
### Prerequisites
#### Install requirements
Make sure to have the following libraries installed in your Python environment:
- opencv
- dlib
- numpy
- imutils
- pillow
#### Setup faces to recognize
Update the `known_faces` directory with images of people you want to detect and be sure to crop around the faces as the Zuckerberg example (if you don't, the program execution might raise an error).
Please only use .jpg or .png image format files in the `known_faces` folder.
For instance, you may have the following files:
```
/known_faces/Zuckerberg.png
/known_faces/YourPicture.jpg
```
Note that the recognition name displayed is taken from the file name (without extension) it matches in the `known_faces` folder.
#### Camera
You need a camera connected to your PC since the program will stream the image of camera on your screen and will recognize the face displayed should the face be part of the `known_faces` folder.
## Run
```
easy_facial_recognition.py --i known_faces
```
## Youtube Video explanation (French only)
Click on the image below:
[![IMAGE ALT TEXT HERE](https://img.youtube.com/vi/54WmrwVWu1w/0.jpg)](https://www.youtube.com/watch?v=54WmrwVWu1w)
## Authors
* **Anis Ayari** - *Lead Data Scientist*
## License
This project is licensed under the MIT License - see the [LICENSE.md](LICENSE.md) file for details
## Windows environment Notes
On Windows, you may have to additionnally install:
- opencv-python
- CMake
- Visual Studio and the extension for C++ so that `dlib` installation completes successfully

115
easy_facial_recognition.py Normal file
View File

@@ -0,0 +1,115 @@
# Code Anis - Defend Intelligence
import cv2
import dlib
import PIL.Image
import numpy as np
from imutils import face_utils
import argparse
from pathlib import Path
import os
import ntpath
parser = argparse.ArgumentParser(description='Easy Facial Recognition App')
parser.add_argument('-i', '--input', type=str, required=True, help='directory of input known faces')
print('[INFO] Starting System...')
print('[INFO] Importing pretrained model..')
pose_predictor_68_point = dlib.shape_predictor("pretrained_model/shape_predictor_68_face_landmarks.dat")
pose_predictor_5_point = dlib.shape_predictor("pretrained_model/shape_predictor_5_face_landmarks.dat")
face_encoder = dlib.face_recognition_model_v1("pretrained_model/dlib_face_recognition_resnet_model_v1.dat")
face_detector = dlib.get_frontal_face_detector()
print('[INFO] Importing pretrained model..')
def transform(image, face_locations):
coord_faces = []
for face in face_locations:
rect = face.top(), face.right(), face.bottom(), face.left()
coord_face = max(rect[0], 0), min(rect[1], image.shape[1]), min(rect[2], image.shape[0]), max(rect[3], 0)
coord_faces.append(coord_face)
return coord_faces
def encode_face(image):
face_locations = face_detector(image, 1)
face_encodings_list = []
landmarks_list = []
for face_location in face_locations:
# DETECT FACES
shape = pose_predictor_68_point(image, face_location)
face_encodings_list.append(np.array(face_encoder.compute_face_descriptor(image, shape, num_jitters=1)))
# GET LANDMARKS
shape = face_utils.shape_to_np(shape)
landmarks_list.append(shape)
face_locations = transform(image, face_locations)
return face_encodings_list, face_locations, landmarks_list
def easy_face_reco(frame, known_face_encodings, known_face_names):
rgb_small_frame = frame[:, :, ::-1]
# ENCODING FACE
face_encodings_list, face_locations_list, landmarks_list = encode_face(rgb_small_frame)
face_names = []
for face_encoding in face_encodings_list:
if len(face_encoding) == 0:
return np.empty((0))
# CHECK DISTANCE BETWEEN KNOWN FACES AND FACES DETECTED
vectors = np.linalg.norm(known_face_encodings - face_encoding, axis=1)
tolerance = 0.6
result = []
for vector in vectors:
if vector <= tolerance:
result.append(True)
else:
result.append(False)
if True in result:
first_match_index = result.index(True)
name = known_face_names[first_match_index]
else:
name = "Unknown"
face_names.append(name)
for (top, right, bottom, left), name in zip(face_locations_list, face_names):
cv2.rectangle(frame, (left, top), (right, bottom), (0, 255, 0), 2)
cv2.rectangle(frame, (left, bottom - 30), (right, bottom), (0, 255, 0), cv2.FILLED)
cv2.putText(frame, name, (left + 2, bottom - 2), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 0), 1)
for shape in landmarks_list:
for (x, y) in shape:
cv2.circle(frame, (x, y), 1, (255, 0, 255), -1)
if __name__ == '__main__':
args = parser.parse_args()
print('[INFO] Importing faces...')
face_to_encode_path = Path(args.input)
files = [file_ for file_ in face_to_encode_path.rglob('*.jpg')]
for file_ in face_to_encode_path.rglob('*.png'):
files.append(file_)
if len(files)==0:
raise ValueError('No faces detect in the directory: {}'.format(face_to_encode_path))
known_face_names = [os.path.splitext(ntpath.basename(file_))[0] for file_ in files]
known_face_encodings = []
for file_ in files:
image = PIL.Image.open(file_)
image = np.array(image)
face_encoded = encode_face(image)[0][0]
known_face_encodings.append(face_encoded)
print('[INFO] Faces well imported')
print('[INFO] Starting Webcam...')
video_capture = cv2.VideoCapture(0)
print('[INFO] Webcam well started')
print('[INFO] Detecting...')
while True:
ret, frame = video_capture.read()
easy_face_reco(frame, known_face_encodings, known_face_names)
cv2.imshow('Easy Facial Recognition App', frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
print('[INFO] Stopping System')
video_capture.release()
cv2.destroyAllWindows()

BIN
known_faces/Zuckerberg.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 131 KiB

Binary file not shown.

Binary file not shown.

BIN
readme.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 MiB