Это 6-й день моего участия в августовском испытании обновлений.Подробности о мероприятии:Испытание августовского обновления
Программно-аппаратная среда
- ubuntu 18.04 64bit
- GTX 1070Ti
- anaconda with python 3.6
- face_recognition 1.2.3
- dlib
- opencv
Введение в распознавание лиц
face_recognition
Утверждает, что является самым простым в миреpython
Библиотека распознавания лиц находится в знаменитом фреймворке глубокого обучения.dlib
интегрирование сделано выше,dlib
модель вLFW
(с надписью «Лица в дикой природе») имеет точность 99,38. Кроме тогоface_recognition
Предоставляются соответствующие инструменты командной строки, которые могут выполнять распознавание лиц в папке с изображениями через командную строку, что очень здорово.
установить Face_Recognition
годный к употреблениюpip
установить
pip install face_recognition
Или установить из исходников
git clone https://github.com/ageitgey/face_recognition.git
cd face_recognition
python setup.py install
рабочий процесс распознавания лиц
найти лица
Первый шаг - найти расположение всех лиц, содержащихся в данном изображении.
import face_recognition
image = face_recognition.load_image_file("your_file.jpg")
face_locations = face_recognition.face_locations(image)
Точки операционных характеристик
Найдите у всех глаза, нос, рот и челюсть
import face_recognition
image = face_recognition.load_image_file("your_file.jpg")
face_landmarks_list = face_recognition.face_landmarks(image)
идентифицировать
Последний и самый важный шаг — определить, кому принадлежит это лицо.face_recognition
Используется евклидово расстояние (см. другую мою статьюImagination.com/2019/11/30/…), чтобы определить, является ли это одним и тем же лицом.
import face_recognition
known_image = face_recognition.load_image_file("biden.jpg")
unknown_image = face_recognition.load_image_file("unknown.jpg")
biden_encoding = face_recognition.face_encodings(known_image)[0]
unknown_encoding = face_recognition.face_encodings(unknown_image)[0]
results = face_recognition.compare_faces([biden_encoding], unknown_encoding)
инструмент командной строки
face_recognition
Предоставляются 2 инструмента командной строки
-
face_detection
- Узнайте лица в данном изображении или папке с изображением -
face_recognition
- Выполнить распознавание лиц
Как использовать это можно сделать через--help
для просмотра параметров.face_detection
Это относительно просто и не будет обсуждаться здесь.
Инструмент командной строки face_recognition использует
Для выполнения распознавания лиц необходимо предварительно подготовить информацию об известных людях, которая хранится в отдельной папке, напримерknown
, то изображение каждого человека упорядочено по его имени, как вJoe Biden.jpg
,Kobe.jpg
.
Затем поместите фотографии, которые необходимо распознать в другой папке, такой какunknown
, выполните следующую команду, чтобы определить
face_recognition known unknown
По умолчанию, без установки порога, скорость правильного распознавания очень и очень низкая. В реальных ситуациях вам необходимо соответствующим образом настроить порог в соответствии с вашей собственной ситуацией. В той же тестовой среде порог сходства установлен равным 0,38, и результат распознавания правильный.
face_recognition known unknown --tolerance 0.38
печатьunknown_person
показать незнакомца
Еще один полезный параметр--cpus
, если вы используете многоядерныйCPU
, вы можете использовать этот параметр для повышения скорости распознавания.--cpus=-1
значит использовать всеCPU
ядерный.
классификатор КНН
KNN
(K-ближайший сосед) классифицируется путем измерения расстояния между различными собственными значениями. Его идея такова: если большинство из k наиболее похожих выборок в пространстве признаков (то есть ближайших соседей в пространстве признаков) принадлежат к определенной категории, то выборка также принадлежит к этой категории, где K обычно не больше An целое число 20.KNN
В алгоритме выбранными соседями являются все объекты, которые были правильно классифицированы. В решении о классификации этот метод определяет только категорию пробы, подлежащей классификации, в соответствии с категорией ближайшей одной или нескольких проб.
В практических проектах классификатор (classifier
) для хранения данных известных лиц для удобства управления.face_recognition
используется на основеKNN
Классификатор для алгоритма.
сделать классификатор
код отexamples/face_recognition_knn.py
, Заметки очень подробные, поэтому я не буду объяснять их по одному. После тестирования, чем больше фотографий одного и того же человека, тем выше точность распознавания.
def train(train_dir, model_save_path=None, n_neighbors=None, knn_algo='ball_tree', verbose=False):
"""
Trains a k-nearest neighbors classifier for face recognition.
:param train_dir: directory that contains a sub-directory for each known person, with its name.
(View in source code to see train_dir example tree structure)
Structure:
<train_dir>/
├── <person1>/
│ ├── <somename1>.jpeg
│ ├── <somename2>.jpeg
│ ├── ...
├── <person2>/
│ ├── <somename1>.jpeg
│ └── <somename2>.jpeg
└── ...
:param model_save_path: (optional) path to save model on disk
:param n_neighbors: (optional) number of neighbors to weigh in classification. Chosen automatically if not specified
:param knn_algo: (optional) underlying data structure to support knn.default is ball_tree
:param verbose: verbosity of training
:return: returns knn classifier that was trained on the given data.
"""
X = []
y = []
# Loop through each person in the training set
for class_dir in os.listdir(train_dir):
if not os.path.isdir(os.path.join(train_dir, class_dir)):
continue
# Loop through each training image for the current person
for img_path in image_files_in_folder(os.path.join(train_dir, class_dir)):
image = face_recognition.load_image_file(img_path)
face_bounding_boxes = face_recognition.face_locations(image)
if len(face_bounding_boxes) != 1:
# If there are no people (or too many people) in a training image, skip the image.
if verbose:
print("Image {} not suitable for training: {}".format(img_path, "Didn't find a face" if len(face_bounding_boxes) < 1 else "Found more than one face"))
else:
# Add face encoding for current image to the training set
X.append(face_recognition.face_encodings(image, known_face_locations=face_bounding_boxes)[0])
y.append(class_dir)
# Determine how many neighbors to use for weighting in the KNN classifier
if n_neighbors is None:
n_neighbors = int(round(math.sqrt(len(X))))
if verbose:
print("Chose n_neighbors automatically:", n_neighbors)
# Create and train the KNN classifier
knn_clf = neighbors.KNeighborsClassifier(n_neighbors=n_neighbors, algorithm=knn_algo, weights='distance')
knn_clf.fit(X, y)
# Save the trained KNN classifier
if model_save_path is not None:
with open(model_save_path, 'wb') as f:
pickle.dump(knn_clf, f)
return knn_clf
Используйте классификатор
def predict(X_img_path, knn_clf=None, model_path=None, distance_threshold=0.6):
"""
Recognizes faces in given image using a trained KNN classifier
:param X_img_path: path to image to be recognized
:param knn_clf: (optional) a knn classifier object. if not specified, model_save_path must be specified.
:param model_path: (optional) path to a pickled knn classifier. if not specified, model_save_path must be knn_clf.
:param distance_threshold: (optional) distance threshold for face classification. the larger it is, the more chance
of mis-classifying an unknown person as a known one.
:return: a list of names and face locations for the recognized faces in the image: [(name, bounding box), ...].
For faces of unrecognized persons, the name 'unknown' will be returned.
"""
if not os.path.isfile(X_img_path) or os.path.splitext(X_img_path)[1][1:] not in ALLOWED_EXTENSIONS:
raise Exception("Invalid image path: {}".format(X_img_path))
if knn_clf is None and model_path is None:
raise Exception("Must supply knn classifier either thourgh knn_clf or model_path")
# Load a trained KNN model (if one was passed in)
if knn_clf is None:
with open(model_path, 'rb') as f:
knn_clf = pickle.load(f)
# Load image file and find face locations
X_img = face_recognition.load_image_file(X_img_path)
X_face_locations = face_recognition.face_locations(X_img)
# If no faces are found in the image, return an empty result.
if len(X_face_locations) == 0:
return []
# Find encodings for faces in the test iamge
faces_encodings = face_recognition.face_encodings(X_img, known_face_locations=X_face_locations)
# Use the KNN model to find the best matches for the test face
closest_distances = knn_clf.kneighbors(faces_encodings, n_neighbors=1)
are_matches = [closest_distances[0][i][0] <= distance_threshold for i in range(len(X_face_locations))]
# Predict classes and remove classifications that aren't within the threshold
return [(pred, loc) if rec else ("unknown", loc) for pred, loc, rec in zip(knn_clf.predict(faces_encodings), X_face_locations, are_matches)]
CUDA-ускорение
Если вы хотите повысить производительность, вы должны использовать видеокарту, потому чтоface_recognition
зависит отdlib
, поэтому вам нужно сначала установить поддержкуCUDA
изdlib
, вы можете обратиться к другой статьеImagination.com/2019/12/13/…
import face_recognition
image = face_recognition.load_image_file("my_picture.jpg")
face_locations = face_recognition.face_locations(image, model="cnn")
# face_locations is now an array listing the co-ordinates of each face!
Связь с камерой
использовать здесьopencv
реализовать,opencv
Считайте данные каждого кадра камеры, а затемresize
, преобразование цветового пространства (путемopecv
в использованииBGR
преобразовать вface_recognition
в использованииRGB
) и, наконец, выполнить обнаружение и распознавание лиц.
import face_recognition
import cv2
video_capture = cv2.VideoCapture(0)
# Load a sample picture and learn how to recognize it.
obama_image = face_recognition.load_image_file("obama.jpg")
obama_face_encoding = face_recognition.face_encodings(obama_image)[0]
# Load a second sample picture and learn how to recognize it.
biden_image = face_recognition.load_image_file("biden.jpg")
biden_face_encoding = face_recognition.face_encodings(biden_image)[0]
# Create arrays of known face encodings and their names
known_face_encodings = [
obama_face_encoding,
biden_face_encoding
]
known_face_names = [
"Barack Obama",
"Joe Biden"
]
# Initialize some variables
face_locations = []
face_encodings = []
face_names = []
process_this_frame = True
while True:
# Grab a single frame of video
ret, frame = video_capture.read()
# Resize frame of video to 1/4 size for faster face recognition processing
small_frame = cv2.resize(frame, (0, 0), fx=0.25, fy=0.25)
# Convert the image from BGR color (which OpenCV uses) to RGB color (which face_recognition uses)
rgb_small_frame = small_frame[:, :, ::-1]
# Only process every other frame of video to save time
if process_this_frame:
# Find all the faces and face encodings in the current frame of video
face_locations = face_recognition.face_locations(rgb_small_frame)
face_encodings = face_recognition.face_encodings(rgb_small_frame, face_locations)
face_names = []
for face_encoding in face_encodings:
# See if the face is a match for the known face(s)
matches = face_recognition.compare_faces(known_face_encodings, face_encoding)
name = "Unknown"
# If a match was found in known_face_encodings, just use the first one.
if True in matches:
first_match_index = matches.index(True)
name = known_face_names[first_match_index]
face_names.append(name)
process_this_frame = not process_this_frame
# Display the results
for (top, right, bottom, left), name in zip(face_locations, face_names):
# Scale back up face locations since the frame we detected in was scaled to 1/4 size
top *= 4
right *= 4
bottom *= 4
left *= 4
# Draw a box around the face
cv2.rectangle(frame, (left, top), (right, bottom), (0, 0, 255), 2)
# Draw a label with a name below the face
cv2.rectangle(frame, (left, bottom - 35), (right, bottom), (0, 0, 255), cv2.FILLED)
font = cv2.FONT_HERSHEY_DUPLEX
cv2.putText(frame, name, (left + 6, bottom - 6), font, 1.0, (255, 255, 255), 1)
# Display the resulting image
cv2.imshow('Video', frame)
# Hit 'q' on the keyboard to quit!
if cv2.waitKey(1) & 0xFF == ord('q'):
break
# Release handle to the webcam
video_capture.release()
cv2.destroyAllWindows()
Кроме того, локальные видеофайлы, веб-камеры (на основеrtsp
Сцена распознавания видеопотока) очень похожа на обработку локальной камеры, поэтому дальше вставлять сюда код не буду.