Initial commit
This commit is contained in:
50
.gitignore
vendored
Normal file
50
.gitignore
vendored
Normal 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
7
LICENSE.md
Normal 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
61
README.md
Normal file
@@ -0,0 +1,61 @@
|
||||
# Easy Facial Recognition
|
||||
|
||||
Recognition by minimum norm between vectors (128D dlib descriptor)
|
||||

|
||||
|
||||
|
||||
### 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:
|
||||
|
||||
[](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
115
easy_facial_recognition.py
Normal 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
BIN
known_faces/Zuckerberg.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 131 KiB |
BIN
pretrained_model/dlib_face_recognition_resnet_model_v1.dat
Normal file
BIN
pretrained_model/dlib_face_recognition_resnet_model_v1.dat
Normal file
Binary file not shown.
BIN
pretrained_model/shape_predictor_5_face_landmarks.dat
Normal file
BIN
pretrained_model/shape_predictor_5_face_landmarks.dat
Normal file
Binary file not shown.
BIN
pretrained_model/shape_predictor_68_face_landmarks.dat
Normal file
BIN
pretrained_model/shape_predictor_68_face_landmarks.dat
Normal file
Binary file not shown.
BIN
readme.gif
Normal file
BIN
readme.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 12 MiB |
Reference in New Issue
Block a user