From 6ede62f44b8962d9bbd02e3610b626d4fe24edeb Mon Sep 17 00:00:00 2001 From: Anand Baburajan Date: Sat, 29 Jun 2019 09:24:23 +0530 Subject: [PATCH 01/53] Fixed a mistake --- examples/face_recognition_svm.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/face_recognition_svm.py b/examples/face_recognition_svm.py index ea0139476..259e46597 100644 --- a/examples/face_recognition_svm.py +++ b/examples/face_recognition_svm.py @@ -51,7 +51,7 @@ for person_img in pix: # Get the face encodings for the face in each image file face = face_recognition.load_image_file("/train_dir/" + person + "/" + person_img) - face_enc = face_recognition.face_encodings(pic)[0] + face_enc = face_recognition.face_encodings(face)[0] # Add face encoding for current image with corresponding label (name) to the training data encodings.append(face_enc) From 59f4d299b6ae3232a1d8fe5d5d9652bffa17a728 Mon Sep 17 00:00:00 2001 From: Anand Baburajan Date: Thu, 25 Jul 2019 15:14:18 +0530 Subject: [PATCH 02/53] Message if no faces in training image Show a message if a training image contains none or more than one faces --- examples/face_recognition_svm.py | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/examples/face_recognition_svm.py b/examples/face_recognition_svm.py index 259e46597..0f8ed33d9 100644 --- a/examples/face_recognition_svm.py +++ b/examples/face_recognition_svm.py @@ -1,5 +1,5 @@ -# Find all the faces in an image then recognize them using a SVM with scikit-learn -# This allows you to train multiple images per person +# Train multiple images per person +# Find and recognize faces in an image using a SVC with scikit-learn """ Structure: @@ -27,9 +27,6 @@ .jpg """ -# Install scikit-learn if you haven't already with pip -# $ pip3 install scikit-learn - import face_recognition from sklearn import svm import os @@ -46,17 +43,23 @@ # Loop through each person in the training directory for person in train_dir: pix = os.listdir("/train_dir/" + person) - + # Loop through each training image for the current person for person_img in pix: # Get the face encodings for the face in each image file face = face_recognition.load_image_file("/train_dir/" + person + "/" + person_img) - face_enc = face_recognition.face_encodings(face)[0] - - # Add face encoding for current image with corresponding label (name) to the training data - encodings.append(face_enc) - names.append(person) - + face_bounding_boxes = face_recognition.face_locations(face) + + #If training image contains none or more than faces, print an error message and exit + if len(face_bounding_boxes) != 1: + print(person + "/" + person_img + " contains none or more than one faces and can't be used for training.") + exit() + else: + face_enc = face_recognition.face_encodings(face)[0] + # Add face encoding for current image with corresponding label (name) to the training data + encodings.append(face_enc) + names.append(person) + # Create and train the SVC classifier clf = svm.SVC(gamma='scale') clf.fit(encodings,names) @@ -70,7 +73,7 @@ print("Number of faces detected: ", no) # Predict all the faces in the test image using the trained classifier -print("Found: \n") +print("Found:") for i in range(no): test_image_enc = face_recognition.face_encodings(test_image)[i] name = clf.predict([test_image_enc]) From df84e2cd8a225e0f3094bd8cb13172aa9b918f29 Mon Sep 17 00:00:00 2001 From: Adam Geitgey Date: Tue, 20 Aug 2019 12:13:14 +0100 Subject: [PATCH 03/53] Applying changes from #826 by chn-lee-yumi manually due to bad git history in PR --- .../facerec_from_webcam_multiprocessing.py | 39 ++++++++++++------- 1 file changed, 24 insertions(+), 15 deletions(-) diff --git a/examples/facerec_from_webcam_multiprocessing.py b/examples/facerec_from_webcam_multiprocessing.py index 4a960024e..52bec21ad 100644 --- a/examples/facerec_from_webcam_multiprocessing.py +++ b/examples/facerec_from_webcam_multiprocessing.py @@ -1,8 +1,10 @@ import face_recognition import cv2 -from multiprocessing import Process, Manager, cpu_count +from multiprocessing import Process, Manager, cpu_count, set_start_method import time import numpy +import threading +import platform # This is a little bit complicated (but fast) example of running face recognition on live video from your webcam. @@ -14,7 +16,7 @@ # Get next worker's id -def next_id(current_id): +def next_id(current_id, worker_num): if current_id == worker_num: return 1 else: @@ -22,7 +24,7 @@ def next_id(current_id): # Get previous worker's id -def prev_id(current_id): +def prev_id(current_id, worker_num): if current_id == 1: return worker_num else: @@ -30,7 +32,7 @@ def prev_id(current_id): # A subprocess use to capture frames. -def capture(read_frame_list): +def capture(read_frame_list, Global, worker_num): # Get a reference to webcam #0 (the default one) video_capture = cv2.VideoCapture(0) # video_capture.set(3, 640) # Width of the frames in the video stream. @@ -40,11 +42,11 @@ def capture(read_frame_list): while not Global.is_exit: # If it's time to read a frame - if Global.buff_num != next_id(Global.read_num): + if Global.buff_num != next_id(Global.read_num, worker_num): # Grab a single frame of video ret, frame = video_capture.read() read_frame_list[Global.buff_num] = frame - Global.buff_num = next_id(Global.buff_num) + Global.buff_num = next_id(Global.buff_num, worker_num) else: time.sleep(0.01) @@ -53,13 +55,13 @@ def capture(read_frame_list): # Many subprocess use to process frames. -def process(worker_id, read_frame_list, write_frame_list): +def process(worker_id, read_frame_list, write_frame_list, Global, worker_num): known_face_encodings = Global.known_face_encodings known_face_names = Global.known_face_names while not Global.is_exit: # Wait to read - while Global.read_num != worker_id or Global.read_num != prev_id(Global.buff_num): + while Global.read_num != worker_id or Global.read_num != prev_id(Global.buff_num, worker_num): time.sleep(0.01) # Delay to make the video look smoother @@ -69,7 +71,7 @@ def process(worker_id, read_frame_list, write_frame_list): frame_process = read_frame_list[worker_id] # Expect next worker to read frame - Global.read_num = next_id(Global.read_num) + Global.read_num = next_id(Global.read_num, worker_num) # Convert the image from BGR color (which OpenCV uses) to RGB color (which face_recognition uses) rgb_frame = frame_process[:, :, ::-1] @@ -106,11 +108,15 @@ def process(worker_id, read_frame_list, write_frame_list): write_frame_list[worker_id] = frame_process # Expect next worker to write frame - Global.write_num = next_id(Global.write_num) + Global.write_num = next_id(Global.write_num, worker_num) if __name__ == '__main__': + # Fix Bug on MacOS + if platform.system() == 'Darwin': + set_start_method('forkserver') + # Global variables Global = Manager().Namespace() Global.buff_num = 1 @@ -122,13 +128,16 @@ def process(worker_id, read_frame_list, write_frame_list): write_frame_list = Manager().dict() # Number of workers (subprocess use to process frames) - worker_num = cpu_count() + if cpu_count() > 2: + worker_num = cpu_count() - 1 # 1 for capturing frames + else: + worker_num = 2 # Subprocess list p = [] - # Create a subprocess to capture frames - p.append(Process(target=capture, args=(read_frame_list,))) + # Create a thread to capture frames (if uses subprocess, it will crash on Mac) + p.append(threading.Thread(target=capture, args=(read_frame_list, Global, worker_num,))) p[0].start() # Load a sample picture and learn how to recognize it. @@ -151,7 +160,7 @@ def process(worker_id, read_frame_list, write_frame_list): # Create workers for worker_id in range(1, worker_num + 1): - p.append(Process(target=process, args=(worker_id, read_frame_list, write_frame_list))) + p.append(Process(target=process, args=(worker_id, read_frame_list, write_frame_list, Global, worker_num,))) p[worker_id].start() # Start to show video @@ -186,7 +195,7 @@ def process(worker_id, read_frame_list, write_frame_list): Global.frame_delay = 0 # Display the resulting image - cv2.imshow('Video', write_frame_list[prev_id(Global.write_num)]) + cv2.imshow('Video', write_frame_list[prev_id(Global.write_num, worker_num)]) # Hit 'q' on the keyboard to quit! if cv2.waitKey(1) & 0xFF == ord('q'): From a9dd28d5f97e2b5d83791548eeb9c24a807bca73 Mon Sep 17 00:00:00 2001 From: Aliaksei Urbanski Date: Sat, 24 Aug 2019 23:47:23 +0300 Subject: [PATCH 04/53] Update list of supported Python versions The goal of these changes is to provide actual information about supported Python versions. I believe that only versions for those you have tests on CI should be listed as supported. --- setup.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/setup.py b/setup.py index 93d4cdb0a..483d596a2 100644 --- a/setup.py +++ b/setup.py @@ -53,13 +53,12 @@ 'License :: OSI Approved :: MIT License', 'Natural Language :: English', "Programming Language :: Python :: 2", - 'Programming Language :: Python :: 2.6', 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3', - 'Programming Language :: Python :: 3.3', 'Programming Language :: Python :: 3.4', 'Programming Language :: Python :: 3.5', 'Programming Language :: Python :: 3.6', + 'Programming Language :: Python :: 3.7', ], test_suite='tests', tests_require=test_requirements From 826824500fa8510a9aaffbf84573b5882d69686a Mon Sep 17 00:00:00 2001 From: Tejas Shah Date: Mon, 2 Sep 2019 13:36:48 -0700 Subject: [PATCH 05/53] fixed leftover worker processes when user requested to end demo --- examples/facerec_from_webcam_multiprocessing.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/examples/facerec_from_webcam_multiprocessing.py b/examples/facerec_from_webcam_multiprocessing.py index 52bec21ad..a22c31c70 100644 --- a/examples/facerec_from_webcam_multiprocessing.py +++ b/examples/facerec_from_webcam_multiprocessing.py @@ -62,6 +62,10 @@ def process(worker_id, read_frame_list, write_frame_list, Global, worker_num): # Wait to read while Global.read_num != worker_id or Global.read_num != prev_id(Global.buff_num, worker_num): + # If the user has requested to end the app, then stop waiting for webcam frames + if Global.is_exit: + break + time.sleep(0.01) # Delay to make the video look smoother From 54ba5bca01fb3ac26607b0241fc0ee4ba7a786dd Mon Sep 17 00:00:00 2001 From: Alexandr Katsko Date: Sat, 26 Oct 2019 04:36:35 +0700 Subject: [PATCH 06/53] Fix docstring in face_recognition.api.batch_face_locations --- face_recognition/api.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/face_recognition/api.py b/face_recognition/api.py index 5aed5ec0b..c74c5f95c 100644 --- a/face_recognition/api.py +++ b/face_recognition/api.py @@ -138,7 +138,7 @@ def batch_face_locations(images, number_of_times_to_upsample=1, batch_size=128): If you are using a GPU, this can give you much faster results since the GPU can process batches of images at once. If you aren't using a GPU, you don't need this function. - :param img: A list of images (each as a numpy array) + :param images: A list of images (each as a numpy array) :param number_of_times_to_upsample: How many times to upsample the image looking for faces. Higher numbers find smaller faces. :param batch_size: How many images to include in each GPU processing batch. :return: A list of tuples of found face locations in css (top, right, bottom, left) order From a96484edc270697c666c1c32ba5163cf8e71b467 Mon Sep 17 00:00:00 2001 From: Ellie Kang Date: Wed, 13 Nov 2019 17:51:45 +0900 Subject: [PATCH 07/53] Update README_Korean.md revise comments --- README_Korean.md | 74 ++++++++++++++++++++++++------------------------ 1 file changed, 37 insertions(+), 37 deletions(-) diff --git a/README_Korean.md b/README_Korean.md index eeb101273..3af428787 100644 --- a/README_Korean.md +++ b/README_Korean.md @@ -1,12 +1,12 @@ -# Face Recognition +# Face Recognition -_[중국어 简体中文版](https://github.com/ageitgey/face_recognition/blob/master/README_Simplified_Chinese.md) 로 번역된 이 파일을 읽으실 수 있습니다._ +본 문서는 _[중국어 简体中文版](https://github.com/ageitgey/face_recognition/blob/master/README_Simplified_Chinese.md) 로부터 번역되어 한국 사용자들의 기여를 통해 만들어진 문서입니다. -세계에서 가장 간단한 얼굴 인식 라이브러리로, Python 또는 명령 줄에서 얼굴을 인식하고 조작 해 보십시오. +본 라이브러리는 세계에서 가장 간단한 얼굴 인식 라이브러리로, Python 또는 명령 줄(CLI)에서 얼굴을 인식하고 조작해 볼 수 있습니다. -딥 러닝으로 구축된 [dlib](http://dlib.net/)의 최첨단 얼굴 인식 기능을 사용하여 구축되었습니다. 이 모델은 [Labeled Faces in the Wild](http://vis-www.cs.umass.edu/lfw/) 기준으로 99.38%의 정확도를 가집니다. +본 라이브러리는 딥러닝 기반으로 제작된 [dlib](http://dlib.net/)의 최첨단 얼굴 인식 기능을 사용하여 구축되었습니다. 이 모델은 [Labeled Faces in the Wild](http://vis-www.cs.umass.edu/lfw/) 기준으로 99.38%의 정확도를 가집니다. -또한, 명령 줄에서 이미지 폴더 안에 있는 얼굴 인식 기능을 위한 간단한 `face_recognition` 명령 줄 도구를 제공합니다! +또한, 명령 줄(CLI)에서 이미지 폴더 안에 있는 얼굴 인식 기능을 위한 간단한 `face_recognition` 도구를 제공합니다! [![PyPI](https://img.shields.io/pypi/v/face_recognition.svg)](https://pypi.python.org/pypi/face_recognition) @@ -39,11 +39,11 @@ image = face_recognition.load_image_file("your_file.jpg") face_landmarks_list = face_recognition.face_landmarks(image) ``` -얼굴의 특징을 찾는 기능은 여러 중요한 일들에 유용하게 쓰입니다. 하지만 [디지털 메이크업](https://github.com/ageitgey/face_recognition/blob/master/examples/digital_makeup.py) (Meitu 같은 것)을 적용하는 것과 같은 정말 멍청한 것들에도 쓰일 수 있습니다: +얼굴의 특징을 찾는 기능은 여러 중요한 일들에 유용하게 쓰입니다. 예를 들어 [디지털 메이크업](https://github.com/ageitgey/face_recognition/blob/master/examples/digital_makeup.py) (Meitu 같은 것)을 적용하는 것과 같은 정말 멍청한 것들에도 쓰일 수 있습니다: ![](https://cloud.githubusercontent.com/assets/896692/23625283/80638760-025d-11e7-80a2-1d2779f7ccab.png) -#### 사진 속 얼굴의 신원 확인하기 +#### 사진 속 얼굴의 신원 확인하기 각각의 사진에서 누가 등장하였는지 인식합니다. @@ -60,7 +60,7 @@ unknown_encoding = face_recognition.face_encodings(unknown_image)[0] results = face_recognition.compare_faces([biden_encoding], unknown_encoding) ``` -이 라이브러리를 다른 Python 라이브러리와 함께 사용하여 실시간 얼굴 인식을 할 수도 있습니다: +이 라이브러리를 다른 Python 라이브러리와 함께 사용한다면 실시간 얼굴 인식도 가능합니다: ![](https://cloud.githubusercontent.com/assets/896692/24430398/36f0e3f0-13cb-11e7-8258-4d0c9ce1e419.gif) @@ -68,7 +68,7 @@ results = face_recognition.compare_faces([biden_encoding], unknown_encoding) ## 온라인 데모 -Jupyter notebook demo로 공유된 사용자 기여 (공식적인 지원이 아님): [![Deepnote](https://beta.deepnote.org/buttons/try-in-a-jupyter-notebook.svg)](https://beta.deepnote.org/launch?template=face_recognition) +실제 사용자가 공유한 Jupyter notebook demo (공식은 아닙니다): [![Deepnote](https://beta.deepnote.org/buttons/try-in-a-jupyter-notebook.svg)](https://beta.deepnote.org/launch?template=face_recognition) ## 설치 @@ -81,7 +81,7 @@ Jupyter notebook demo로 공유된 사용자 기여 (공식적인 지원이 아 #### Mac 또는 Linux에서의 설치 -우선, 파이썬 바인딩을 통해 dlib이 이미 설치가 되어있는지를 확인해야 합니다: +우선, Python 바인딩을 통해 dlib이 이미 설치가 되어있는지를 확인해야 합니다: * [macOS 또는 Ubuntu에서 소스에서 dlib을 설치하는 방법](https://gist.github.com/ageitgey/629d75c1baac34dfa5ca2a1928a7aeaf) @@ -113,24 +113,24 @@ Windows는 공식적으로 지원하지는 않지만, 친절한 유저들이 이 ### 명령 줄 인터페이스 -`face_recognition`을 설치하면, 두 가지 간단한 명령 줄 프로그램을 얻습니다: +`face_recognition`을 설치하면, 두 가지 간단한 명령 줄(CLI) 프로그램을 얻습니다: -* `face_recognition` - 사진이나 사진으로 가득 찬 폴더의 얼굴을 인식합니다. -* `face_detection` - 사진이나 사진으로 가득 찬 폴더에서 얼굴을 찾습니다. +* `face_recognition` - 사진 혹은 사진이 들어있는 폴더에서, 얼굴을 인식합니다. +* `face_detection` - 사진 혹은 사진이 들어있는 폴더에서, 얼굴을 찾습니다. #### `face_recognition` 명령 줄 도구 -`face_recognition` 명령을 사용하면 사진이나 사진으로 가득 찬 폴더의 얼굴을 인식할 수 있습니다. +`face_recognition` 명령을 사용하면 사진 혹은 사진이 들어있는 폴더에서, 얼굴을 인식할 수 있습니다. -먼저, 이미 알고 있는 각 사람의 사진 한 장이 폴더에 있어야 합니다. 그리고 사진 속에 있는 그 사람의 이름을 딴 이미지 파일이 각각 하나씩 있어야 합니다: +그러기 위해서는 먼저, 이미 알고 있는(인식하고자 하는) 각 사람의 사진 한 장이 폴더에 있어야 합니다. 그리고 사진 속 그 사람의 이름을 딴 이미지 파일이 각각 하나씩 있어야 합니다: ![known](https://cloud.githubusercontent.com/assets/896692/23582466/8324810e-00df-11e7-82cf-41515eba704d.png) -다음으로, 식별할 파일이 있는 두 번째 폴더가 필요합니다: +다음으로, 식별하고 싶은 파일들이 있는 두 번째 폴더가 필요합니다: ![unknown](https://cloud.githubusercontent.com/assets/896692/23582465/81f422f8-00df-11e7-8b0d-75364f641f58.png) -그런 다음, 알고 있는 사람의 폴더와 모르는 사람의 폴더(또는 단일 이미지)를 전달하는 `face_recognition` 명령을 실행하면, 각 이미지에 있는 사람을 알 수 있습니다: +그런 다음, 알고 있는 사람의 폴더와 모르는 사람의 폴더(또는 단일 이미지)를 전달하는 `face_recognition` 명령을 실행하면, 각 이미지에 있는 사람이 누군지 알 수 있습니다: ```bash $ face_recognition ./pictures_of_people_i_know/ ./unknown_pictures/ @@ -139,9 +139,9 @@ $ face_recognition ./pictures_of_people_i_know/ ./unknown_pictures/ /face_recognition_test/unknown_pictures/unknown.jpg,unknown_person ``` -각각의 얼굴의 결과에는 하나의 줄이 있습니다. 데이터는 파일 이름과 찾아낸 사람의 이름으로 쉼표로 구분됩니다. +각각의 얼굴의 결과는 한 줄로 나타납니다. 각 줄은 파일 이름과 식별된 결과인 사람 이름이 쉼표로 구분되어 나타납니다. -`unknown_person`은 이미지 속에 알고 있는 사람의 폴더에 있는 사람과 일치하지 않는 얼굴입니다. +`unknown_person`은 이미지 속에 알고 있는 사람의 폴더에 있는 그 누구와도 일치하지 않는 얼굴임을 의미합니다. #### `face_detection` 명령 줄 도구 @@ -157,13 +157,13 @@ examples/image2.jpg,62,394,211,244 examples/image2.jpg,95,941,244,792 ``` -감지된 각 얼굴에 대해 한 줄씩 인쇄합니다. 보고 된 좌표는 얼굴의 위쪽, 오른쪽, 아래쪽 및 왼쪽 좌표 (픽셀 단위)입니다. +감지된 각 얼굴에 대해 한 줄씩 인쇄합니다. 결과값의 좌표는 각각 얼굴의 위쪽, 오른쪽, 아래쪽 및 왼쪽 좌표 (픽셀 단위)입니다. ##### 오차 조절 / 민감도 -같은 사람에 대해 여러 개의 항목을 얻었다면, 사진에 있는 사람들이 매우 유사하게 보이기 때문이며 얼굴 비교를 더욱 엄격하게 하기 위해 낮은 허용치가 필요합니다. +같은 사람에 대해 여러 개의 항목을 얻었다면, 사진에 있는 사람들이 매우 유사하게 보이기 때문이며 더욱 엄격한 얼굴 비교를 위해 낮은 허용치(tolerance value)가 필요합니다. -`--tolerance` 변수를 이용하여 이를 수행할 수 있습니다. 기본 허용치 값은 0.6이며 숫자가 낮으면 얼굴 비교가 더욱 엄격해집니다: +`--tolerance` 변수를 이용하여 이를 수행할 수 있습니다. 기본 허용치 값은 0.6이며 숫자가 낮으면 더욱 엄격한 얼굴 비교가 가능합니다: ```bash $ face_recognition --tolerance 0.54 ./pictures_of_people_i_know/ ./unknown_pictures/ @@ -172,7 +172,7 @@ $ face_recognition --tolerance 0.54 ./pictures_of_people_i_know/ ./unknown_pictu /face_recognition_test/unknown_pictures/unknown.jpg,unknown_person ``` -관용 설정을 조정하기 위해 계산된 얼굴 거리는 `--show-distance true`를 통해 볼 수 있습니다: +허용치 설정을 조정하기 위해, 각 식별에서의 얼굴 거리를 알고 싶다면 `--show-distance true`를 통해 볼 수 있습니다: ```bash $ face_recognition --show-distance true ./pictures_of_people_i_know/ ./unknown_pictures/ @@ -183,7 +183,7 @@ $ face_recognition --show-distance true ./pictures_of_people_i_know/ ./unknown_p ##### 더 많은 예제들 -각 사진에 있는 사람들의 이름은 알고 싶지만 파일 이름에는 신경 쓰지 않는다면 다음과 같이 할 수 있습니다: +파일 이름은 신경 쓰지 않고 각 사진에 있는 사람들의 이름만을 알고 싶다면 다음과 같이 할 수 있습니다: ```bash $ face_recognition ./pictures_of_people_i_know/ ./unknown_pictures/ | cut -d ',' -f2 @@ -194,19 +194,19 @@ unknown_person ##### 얼굴 인식 속도 향상 -여러 개의 CPU 코어가 있는 컴퓨터를 사용한다면, 얼굴 인식을 동시에 수행 할 수 있습니다. 예를 들면, 4개의 CPU 코어가 있는 환경에서는, 모든 CPU 코어를 병렬로 사용하여 같은 시간 동안 약 4배의 양으로 이미지를 처리할 수 있습니다. +여러 개의 CPU 코어가 있는 컴퓨터를 사용한다면, 얼굴 인식을 동시에 수행할 수 있습니다. 예를 들면, 4개의 CPU 코어가 있는 환경에서는, 모든 CPU 코어를 병렬로 사용하여 같은 시간 동안 약 4배의 이미지들을 처리할 수 있습니다. -Python 3.4 이상을 사용하는 경우 `--cpus ` 매개 변수를 전달하십시오: +Python 3.4 이상을 사용하는 경우 `--cpus ` 에 매개 변수(parameter)를 전달하십시오: ```bash $ face_recognition --cpus 4 ./pictures_of_people_i_know/ ./unknown_pictures/ ``` -`--cpus -1`을 전달하여 시스템의 모든 CPU 코어를 사용할 수도 있습니다. +또한 `--cpus -1`을 전달하여 시스템의 모든 CPU 코어를 사용할 수도 있습니다. #### Python 모듈 -`face_recognition` 모듈을 추가하여 몇 줄의 코드만으로 얼굴 조작을 쉽게 할 수 있습니다. 이는 매우 간단합니다! +`face_recognition` 모듈을 불러와(import) 단 몇 줄의 코드만으로 얼굴 조작을 쉽게 할 수 있습니다. 이는 매우 간단합니다! API 문서: [https://face-recognition.readthedocs.io](https://face-recognition.readthedocs.io/en/latest/face_recognition.html). @@ -225,7 +225,7 @@ face_locations = face_recognition.face_locations(image) 좀 더 정확한 딥 러닝 기반의 얼굴 탐지 모델을 채택할 수도 있습니다. -참고: 이 모델의 성능을 높이려면 (NVidia의 CUDA 라이브러리를 통한)GPU 가속이 필요합니다. 또한 `dlib`을 컴파일링할 때 CUDA 지원을 활성화 할 수 있습니다. +참고: 이 모델의 성능을 높이려면 (NVidia의 CUDA 라이브러리를 통한) GPU 가속이 필요합니다. 또한 `dlib`을 컴파일링할 때 CUDA 지원(support)을 활성화 할 수 있습니다. ```python import face_recognition @@ -240,7 +240,7 @@ face_locations = face_recognition.face_locations(image, model="cnn") 이미지와 GPU가 둘 다 많은 경우, [얼굴을 일괄적으로 찾을](https://github.com/ageitgey/face_recognition/blob/master/examples/find_faces_in_batches.py) 수도 있습니다. -##### 이미지에서 사람의 얼굴 특징으로 자동으로 찾기 +##### 이미지에서 자동으로 사람의 얼굴 특징 찾기 ```python import face_recognition @@ -262,12 +262,12 @@ import face_recognition picture_of_me = face_recognition.load_image_file("me.jpg") my_face_encoding = face_recognition.face_encodings(picture_of_me)[0] -# my_face_encoding now contains a universal 'encoding' of my facial features that can be compared to any other picture of a face! +# my_face_encoding은 이제 어느 얼굴과도 비교할 수 있는 내가 가진 얼굴 특징의 보편적인 인코딩을 포함하게 되었습니다. unknown_picture = face_recognition.load_image_file("unknown.jpg") unknown_face_encoding = face_recognition.face_encodings(unknown_picture)[0] -# Now we can see the two face encodings are of the same person with `compare_faces`! +# 이제 `compare_faces`를 통해 두 얼굴이 같은 얼굴인지 비교할 수 있습니다! results = face_recognition.compare_faces([my_face_encoding], unknown_face_encoding) @@ -320,7 +320,7 @@ else: - Adrian Rosebrock의 [Raspberry Pi 얼굴 인식](https://www.pyimagesearch.com/2018/06/25/raspberry-pi-face-recognition/) - Raspberry Pi에서 어떻게 사용하는지 - Adrian Rosebrock의 [Python 얼굴 클러스터링](https://www.pyimagesearch.com/2018/07/09/face-clustering-with-python/) by Adrian Rosebrock - - 자율적 학습을 사용하여 각 사진에 나타나는 사람을 기반으로 사진을 클러스터하는 방법 + - 비지도 학습을 사용하여 각 사진에 나타나는 사람을 기반으로 사진을 자동 클러스터하는 방법 ## 얼굴 인식이 작동하는지 @@ -328,14 +328,14 @@ black box 라이브러리에 의존하는 대신 얼굴 위치와 인식이 어 ## 주의 사항 -* 얼굴 인식의 모델은 성인에 대한 교육을 받았으며 어린이는 잘 적용이 되지 않습니다. 이는 0.6의 임계 값을 사용하여 어린이들을 아주 쉽게 뒤죽박죽으로 만드는 경향이 있습니다. +* 얼굴 인식의 모델은 성인에 대한 데이터를 통해 훈련이 되었으며 따라서 어린이의 경우에는 잘 적용이 되지 않습니다. 0.6의 기본 임계 값을 사용한다면 어린이들의 얼굴을 구분하지 못하는 경향이 있습니다. * 소수 민족마다 정확성이 다를 수 있습니다. 자세한 내용은 [이 위키 페이지](https://github.com/ageitgey/face_recognition/wiki/Face-Recognition-Accuracy-Problems#question-face-recognition-works-well-with-european-individuals-but-overall-accuracy-is-lower-with-asian-individuals) 를 참조하십시오. ## 클라우드 호스트에 배포 (Heroku, AWS, 기타 등) `face_recognition`은 C++로 작성된 `dlib`에 의존하기 때문에, Heroku 또는 AWS와 같은 클라우드 호스팅 제공 업체에 이를 사용하는 앱을 배포하는 것은 까다로울 수 있습니다. -작업을 쉽게하기 위해, [Docker](https://www.docker.com/) container에서 `face_recognition`으로 빌드 된 앱을 실행하는 방법을 보여주는 이 repo의 Dockerfile 예제가 있습니다. 이를 통해 Docker 이미지를 지원하는 모든 서비스에 배포 할 수 있어야합니다. +더 쉬운 작업을 위해, [Docker](https://www.docker.com/) container에서 `face_recognition`으로 빌드 된 앱을 실행하는 방법을 보여주는 이 repo의 Dockerfile 예제가 있습니다. 이를 통해 Docker 이미지를 지원하는 모든 서비스에 배포할 수 있어야합니다. 다음을 실행하여 Docker 이미지를 로컬로 시도 할 수 있습니다: `docker-compose up --build` @@ -347,8 +347,8 @@ GPU (드라이버 >= 384.81) 및 [Nvidia-Docker](https://github.com/NVIDIA/nvidi ## 감사의 말 -* `dlib`를 만들고 이 라이브러리에 사용된 얼굴 인식 기능과 얼굴 인코딩 모델을 제공 한 [Davis King](https://github.com/davisking) ([@nulhom](https://twitter.com/nulhom)) 에게 많은 감사를 드립니다. 얼굴 인코딩을 지원하는 ResNet에 대한 자세한 내용은 [블로그 게시물](http://blog.dlib.net/2017/02/high-quality-face-recognition-with-deep.html) 을 확인하십시오. +* `dlib`를 만들고 이 라이브러리에 사용된 얼굴 인식 기능과 얼굴 인코딩 모델을 제공한 [Davis King](https://github.com/davisking) ([@nulhom](https://twitter.com/nulhom)) 에게 많은 감사를 드립니다. 얼굴 인코딩을 지원하는 ResNet에 대한 자세한 내용은 [블로그 게시물](http://blog.dlib.net/2017/02/high-quality-face-recognition-with-deep.html) 을 확인하십시오. * numpy, scipy, scikit-image, pillow 등의 모든 멋진 파이썬 데이터 과학 라이브러리에서 일하는 모든 사람들에게 감사합니다. 이런 종류의 것들을 파이썬에서 쉽고 재미있게 만듭니다. * [Cookiecutter](https://github.com/audreyr/cookiecutter) 와 [audreyr/cookiecutter-pypackage](https://github.com/audreyr/cookiecutter-pypackage) - 프로젝트 템플릿 덕분에 파이썬 프로젝트 패키징 방식이 웬만큼 괜찮아 졌습니다. + 프로젝트 템플릿 덕분에 파이썬 프로젝트 패키징 방식이 더 괜찮아 졌습니다. From 4d7bc049468ee78c971c2609af8979f1ab092584 Mon Sep 17 00:00:00 2001 From: Tejas Shah Date: Mon, 2 Sep 2019 14:11:26 -0700 Subject: [PATCH 08/53] allowed face_encodings to accept either 'large' or 'small' model --- face_recognition/api.py | 5 +++-- tests/test_face_recognition.py | 7 +++++++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/face_recognition/api.py b/face_recognition/api.py index c74c5f95c..9df9e6e6d 100644 --- a/face_recognition/api.py +++ b/face_recognition/api.py @@ -200,16 +200,17 @@ def face_landmarks(face_image, face_locations=None, model="large"): raise ValueError("Invalid landmarks model type. Supported models are ['small', 'large'].") -def face_encodings(face_image, known_face_locations=None, num_jitters=1): +def face_encodings(face_image, known_face_locations=None, num_jitters=1, model="small"): """ Given an image, return the 128-dimension face encoding for each face in the image. :param face_image: The image that contains one or more faces :param known_face_locations: Optional - the bounding boxes of each face if you already know them. :param num_jitters: How many times to re-sample the face when calculating encoding. Higher is more accurate, but slower (i.e. 100 is 100x slower) + :param model: Optional - which model to use. "large" (default) or "small" which only returns 5 points but is faster. :return: A list of 128-dimensional face encodings (one for each face in the image) """ - raw_landmarks = _raw_face_landmarks(face_image, known_face_locations, model="small") + raw_landmarks = _raw_face_landmarks(face_image, known_face_locations, model) return [np.array(face_encoder.compute_face_descriptor(face_image, raw_landmark_set, num_jitters)) for raw_landmark_set in raw_landmarks] diff --git a/tests/test_face_recognition.py b/tests/test_face_recognition.py index c0e550057..8eee9bb02 100644 --- a/tests/test_face_recognition.py +++ b/tests/test_face_recognition.py @@ -152,6 +152,13 @@ def test_face_encodings(self): self.assertEqual(len(encodings), 1) self.assertEqual(len(encodings[0]), 128) + def test_face_encodings_large_model(self): + img = api.load_image_file(os.path.join(os.path.dirname(__file__), 'test_images', 'obama.jpg')) + encodings = api.face_encodings(img, model='large') + + self.assertEqual(len(encodings), 1) + self.assertEqual(len(encodings[0]), 128) + def test_face_distance(self): img_a1 = api.load_image_file(os.path.join(os.path.dirname(__file__), 'test_images', 'obama.jpg')) img_a2 = api.load_image_file(os.path.join(os.path.dirname(__file__), 'test_images', 'obama2.jpg')) From f737853707abe5997020d02032a30030e73f70e1 Mon Sep 17 00:00:00 2001 From: Anand Baburajan Date: Sun, 1 Dec 2019 15:59:41 +0530 Subject: [PATCH 09/53] Skip a pic if it has none or more than one face --- examples/face_recognition_svm.py | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/examples/face_recognition_svm.py b/examples/face_recognition_svm.py index 0f8ed33d9..822a4ccfe 100644 --- a/examples/face_recognition_svm.py +++ b/examples/face_recognition_svm.py @@ -50,11 +50,8 @@ face = face_recognition.load_image_file("/train_dir/" + person + "/" + person_img) face_bounding_boxes = face_recognition.face_locations(face) - #If training image contains none or more than faces, print an error message and exit - if len(face_bounding_boxes) != 1: - print(person + "/" + person_img + " contains none or more than one faces and can't be used for training.") - exit() - else: + #If training image contains exactly one face + if len(face_bounding_boxes) == 1: face_enc = face_recognition.face_encodings(face)[0] # Add face encoding for current image with corresponding label (name) to the training data encodings.append(face_enc) From 5fe85a1a8cbd1b994b505464b555d12cd25eee5f Mon Sep 17 00:00:00 2001 From: Anand Baburajan Date: Tue, 3 Dec 2019 16:53:45 +0530 Subject: [PATCH 10/53] Prints skipped training images --- examples/face_recognition_svm.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/examples/face_recognition_svm.py b/examples/face_recognition_svm.py index 822a4ccfe..8cc268402 100644 --- a/examples/face_recognition_svm.py +++ b/examples/face_recognition_svm.py @@ -56,6 +56,8 @@ # Add face encoding for current image with corresponding label (name) to the training data encodings.append(face_enc) names.append(person) + else: + print(person + "/" + person_img + " was skipped and can't be used for training") # Create and train the SVC classifier clf = svm.SVC(gamma='scale') From b66dbd969b3b4423a6831ba72b8571b454d64553 Mon Sep 17 00:00:00 2001 From: Jason Koo Date: Wed, 25 Dec 2019 12:27:55 -0800 Subject: [PATCH 11/53] Dockerfile example libatlas-dev ref updated --- Dockerfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index 3072e09b5..d8171fc6a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -12,7 +12,7 @@ RUN apt-get install -y --fix-missing \ curl \ graphicsmagick \ libgraphicsmagick1-dev \ - libatlas-dev \ + libatlas-base-dev \ libavcodec-dev \ libavformat-dev \ libgtk2.0-dev \ @@ -47,4 +47,4 @@ RUN cd /root/face_recognition && \ python3 setup.py install CMD cd /root/face_recognition/examples && \ - python3 recognize_faces_in_pictures.py \ No newline at end of file + python3 recognize_faces_in_pictures.py From d621bb4c4c06e696085d998a7a646d107b693ac0 Mon Sep 17 00:00:00 2001 From: Santiago Castro Date: Tue, 4 Feb 2020 20:16:54 -0500 Subject: [PATCH 12/53] Use GitHub Actions for CI --- .github/workflows/main.yml | 24 ++++++++++++++++++++++++ .travis.yml | 26 -------------------------- tox.ini | 4 +++- 3 files changed, 27 insertions(+), 27 deletions(-) create mode 100644 .github/workflows/main.yml delete mode 100644 .travis.yml diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml new file mode 100644 index 000000000..a5961dd92 --- /dev/null +++ b/.github/workflows/main.yml @@ -0,0 +1,24 @@ +name: CI +on: push +jobs: + build: + runs-on: ubuntu-latest + strategy: + matrix: + python-version: [2.7, 3.4, 3.5, 3.6, 3.7] + steps: + - name: Checkout + uses: actions/checkout@v2 + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v1 + with: + python-version: ${{ matrix.python-version }} + - name: Install dependencies + run: | + pip install setuptools wheel + pip install . + pip install tox-gh-actions + - name: Check package setup + run: python setup.py check + - name: Test + run: tox diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 6bb102ab7..000000000 --- a/.travis.yml +++ /dev/null @@ -1,26 +0,0 @@ -dist: trusty -sudo: required -language: python -python: - - "2.7" - - "3.4" - - "3.5" - - "3.6" - -before_install: -- sudo apt-get -qq update -- sudo apt-get install -qq cmake python-numpy python-scipy libboost-python-dev -- pip install git+https://github.com/ageitgey/face_recognition_models - -install: - - pip install -r requirements.txt - - pip install tox-travis - -script: tox - -# Temporary for Python 3.7 -matrix: - include: - - python: 3.7 - dist: xenial - sudo: true diff --git a/tox.ini b/tox.ini index 03799ea76..96f789154 100644 --- a/tox.ini +++ b/tox.ini @@ -4,15 +4,17 @@ envlist = py34 py35 py36 + py37 flake8 -[travis] +[gh-actions] python = 2.7: py27, flake8 3.4: py34, flake8 3.5: py35, flake8 3.6: py36, flake8 + 3.7: py37, flake8 [testenv] From e4e18ec2682cfd890ef569d63d5cd52cde236bc3 Mon Sep 17 00:00:00 2001 From: Santiago Castro Date: Tue, 4 Feb 2020 20:26:50 -0500 Subject: [PATCH 13/53] Drop support for Python 3.4 and add 3.8 --- .github/workflows/main.yml | 2 +- CONTRIBUTING.rst | 2 +- setup.py | 2 +- tox.ini | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index a5961dd92..dee6d6491 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -5,7 +5,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - python-version: [2.7, 3.4, 3.5, 3.6, 3.7] + python-version: [2.7, 3.5, 3.6, 3.7, 3.8] steps: - name: Checkout uses: actions/checkout@v2 diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst index 8498ebdd1..e74c2e313 100644 --- a/CONTRIBUTING.rst +++ b/CONTRIBUTING.rst @@ -82,7 +82,7 @@ Before you submit a pull request, check that it meets these guidelines: 2. If the pull request adds functionality, the docs should be updated. Put your new functionality into a function with a docstring, and add the feature to the list in README.rst. -3. The pull request should work for Python 2.6, 2.7, 3.3, 3.4 and 3.5, and for PyPy. Check +3. The pull request should work for Python 2.7, 3.5, 3.6, 3.7 and 3.8, and for PyPy. Check https://travis-ci.org/ageitgey/face_recognition/pull_requests and make sure that the tests pass for all supported Python versions. diff --git a/setup.py b/setup.py index 483d596a2..86087afe4 100644 --- a/setup.py +++ b/setup.py @@ -55,10 +55,10 @@ "Programming Language :: Python :: 2", 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3', - 'Programming Language :: Python :: 3.4', 'Programming Language :: Python :: 3.5', 'Programming Language :: Python :: 3.6', 'Programming Language :: Python :: 3.7', + 'Programming Language :: Python :: 3.8', ], test_suite='tests', tests_require=test_requirements diff --git a/tox.ini b/tox.ini index 96f789154..ad181d22b 100644 --- a/tox.ini +++ b/tox.ini @@ -1,20 +1,20 @@ [tox] envlist = py27 - py34 py35 py36 py37 + py38 flake8 [gh-actions] python = 2.7: py27, flake8 - 3.4: py34, flake8 3.5: py35, flake8 3.6: py36, flake8 3.7: py37, flake8 + 3.8: py38, flake8 [testenv] From ee6c7eb6616225e5fccc26cd49181173d012c970 Mon Sep 17 00:00:00 2001 From: Santiago Castro Date: Tue, 4 Feb 2020 20:56:01 -0500 Subject: [PATCH 14/53] Unpin flake8 so it supports Python 3.8 --- requirements_dev.txt | 2 +- setup.py | 2 +- tox.ini | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/requirements_dev.txt b/requirements_dev.txt index e4dda8584..ff7da8df9 100644 --- a/requirements_dev.txt +++ b/requirements_dev.txt @@ -2,7 +2,7 @@ pip==8.1.2 bumpversion==0.5.3 wheel==0.29.0 watchdog==0.8.3 -flake8==2.6.0 +flake8 tox==2.3.1 coverage==4.1 Sphinx==1.4.8 diff --git a/setup.py b/setup.py index 86087afe4..0a81e953f 100644 --- a/setup.py +++ b/setup.py @@ -19,7 +19,7 @@ test_requirements = [ 'tox', - 'flake8==2.6.0' + 'flake8' ] setup( diff --git a/tox.ini b/tox.ini index ad181d22b..02284ff71 100644 --- a/tox.ini +++ b/tox.ini @@ -24,7 +24,7 @@ commands = [testenv:flake8] deps = - flake8==2.6.0 + flake8 commands = flake8 From 267571c362a0c3738f4e1223c11b52b2c63cd58b Mon Sep 17 00:00:00 2001 From: kdesai2018 Date: Thu, 13 Feb 2020 15:03:13 -0600 Subject: [PATCH 15/53] added blink detection example --- examples/blink_detection.py | 103 ++++++++++++++++++++++++++++++++++++ 1 file changed, 103 insertions(+) create mode 100644 examples/blink_detection.py diff --git a/examples/blink_detection.py b/examples/blink_detection.py new file mode 100644 index 000000000..dd7db2d0d --- /dev/null +++ b/examples/blink_detection.py @@ -0,0 +1,103 @@ +#!/usr/bin/env python3 + + +# This is a demo of detecting eye status from the users camera. If the users eyes are closed for EYES_CLOSED seconds, the system will start printing out "EYES CLOSED" +# to the terminal until the user presses and holds the spacebar to acknowledge + +# this demo must be run with sudo privileges for the keyboard module to work + +# PLEASE NOTE: This example requires OpenCV (the `cv2` library) to be installed only to read from your webcam. +# OpenCV is *not* required to use the face_recognition library. It's only required if you want to run this +# specific demo. If you have trouble installing it, try any of the other demos that don't require it instead. + +# imports +import face_recognition +import cv2 +import time +from scipy.spatial import distance as dist +import keyboard as kb + +EYES_CLOSED_SECONDS = 5 + +def main(): + closed_count = 0 + video_capture = cv2.VideoCapture(0) + + ret, frame = video_capture.read(0) + # cv2.VideoCapture.release() + small_frame = cv2.resize(frame, (0, 0), fx=0.25, fy=0.25) + rgb_small_frame = small_frame[:, :, ::-1] + + face_landmarks_list = face_recognition.face_landmarks(rgb_small_frame) + process = True + + while True: + ret, frame = video_capture.read(0) + + # get it into the correct format + small_frame = cv2.resize(frame, (0, 0), fx=0.25, fy=0.25) + rgb_small_frame = small_frame[:, :, ::-1] + + + + # get the correct face landmarks + + if process: + face_landmarks_list = face_recognition.face_landmarks(rgb_small_frame) + + # get eyes + for face_landmark in face_landmarks_list: + left_eye = face_landmark['left_eye'] + right_eye = face_landmark['right_eye'] + + + color = (255,0,0) + thickness = 2 + + cv2.rectangle(small_frame, left_eye[0], right_eye[-1], color, thickness) + + cv2.imshow('Video', small_frame) + cv2.waitKey(1) + + ear_left = get_ear(left_eye) + ear_right = get_ear(right_eye) + + closed = ear_left < 0.2 and ear_right < 0.2 + + if (closed): + closed_count += 1 + + else: + closed_count = 0 + + if (closed_count >= EYES_CLOSED_SECONDS): + asleep = True + while (asleep): #continue this loop until they wake up and acknowledge music + print("EYES CLOSED") + + if (kb.is_pressed('space')): + asleep = False + closed_count = 0 + + process = not process + +def get_ear(eye): + + # compute the euclidean distances between the two sets of + # vertical eye landmarks (x, y)-coordinates + A = dist.euclidean(eye[1], eye[5]) + B = dist.euclidean(eye[2], eye[4]) + + # compute the euclidean distance between the horizontal + # eye landmark (x, y)-coordinates + C = dist.euclidean(eye[0], eye[3]) + + # compute the eye aspect ratio + ear = (A + B) / (2.0 * C) + + # return the eye aspect ratio + return ear + +if __name__ == "__main__": + main() + From dc76b351c0ac5e567c0abf2750c9b4ec78b1d1fc Mon Sep 17 00:00:00 2001 From: Emanuel Haupt Date: Mon, 10 Feb 2020 14:59:12 +0100 Subject: [PATCH 16/53] Add instructions for FreeBSD --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README.md b/README.md index e58e3d4fd..d35272d79 100644 --- a/README.md +++ b/README.md @@ -110,6 +110,12 @@ If you are having trouble with installation, you can also try out a * [Raspberry Pi 2+ installation instructions](https://gist.github.com/ageitgey/1ac8dbe8572f3f533df6269dab35df65) +#### Installing on FreeBSD + +```bash +pkg install graphics/py-face_recognition +``` + #### Installing on Windows While Windows isn't officially supported, helpful users have posted instructions on how to install this library: From 69c8a0b7b84017b37958d8efa275c6cbc4dfcdba Mon Sep 17 00:00:00 2001 From: Santiago Castro Date: Tue, 4 Feb 2020 19:19:33 -0500 Subject: [PATCH 17/53] Add build-system dependencies --- pyproject.toml | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 pyproject.toml diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 000000000..9787c3bdf --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,3 @@ +[build-system] +requires = ["setuptools", "wheel"] +build-backend = "setuptools.build_meta" From 2a883cb683441664bd71c15fc1394d173912a1a4 Mon Sep 17 00:00:00 2001 From: Santiago Castro Date: Tue, 4 Feb 2020 19:39:50 -0500 Subject: [PATCH 18/53] Remove unnecessary entry --- pyproject.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 9787c3bdf..d1e6ae6e5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,3 +1,2 @@ [build-system] requires = ["setuptools", "wheel"] -build-backend = "setuptools.build_meta" From d708bedc9f5c838fe95b3c8aa1e5ad749b67e21f Mon Sep 17 00:00:00 2001 From: Miki Date: Sun, 2 Feb 2020 19:08:50 +0900 Subject: [PATCH 19/53] create Japanese translation --- README_Japanese.md | 365 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 365 insertions(+) create mode 100644 README_Japanese.md diff --git a/README_Japanese.md b/README_Japanese.md new file mode 100644 index 000000000..7931e57e3 --- /dev/null +++ b/README_Japanese.md @@ -0,0 +1,365 @@ + +# Face Recognition + +_このファイルは [英語(オリジナル) in English](https://github.com/ageitgey/face_recognition/blob/master/README.md)、 [中国語 简体中文版](https://github.com/ageitgey/face_recognition/blob/master/README_Simplified_Chinese.md) 、 [韓国語 한국어](https://github.com/ageitgey/face_recognition/blob/master/README_Korean.md)で読むこともできます。_ + + +世界で最もシンプルな顔認識ライブラリを使って、Pythonやコマンドラインで顔を認識・操作することができるライブラリです。 + +[dlib](http://dlib.net/)のディープラーニングを用いた最先端の顔認識を使用して構築されており、このモデルは[Labeled Faces in the Wild](http://vis-www.cs.umass.edu/lfw/)ベンチマークにて99.38%の正解率を記録しています。 + +シンプルな`face_recognition`コマンドラインツールも用意しており、コマンドラインでフォルダ内の画像を顔認識することもできます。 + +[![PyPI](https://img.shields.io/pypi/v/face_recognition.svg)](https://pypi.python.org/pypi/face_recognition) +[![Build Status](https://travis-ci.org/ageitgey/face_recognition.svg?branch=master)](https://travis-ci.org/ageitgey/face_recognition) +[![Documentation Status](https://readthedocs.org/projects/face-recognition/badge/?version=latest)](http://face-recognition.readthedocs.io/en/latest/?badge=latest) + +## 特徴 + +#### 画像から顔を探す + +画像に写っているすべての顔を探します。 + +![](https://cloud.githubusercontent.com/assets/896692/23625227/42c65360-025d-11e7-94ea-b12f28cb34b4.png) + +```python +import face_recognition +image = face_recognition.load_image_file("your_file.jpg") +face_locations = face_recognition.face_locations(image) +``` +#### 画像から顔の特徴を取得する + +画像の中の顔から目、鼻、口、あごの場所と輪郭を得ることができます。 + +![](https://cloud.githubusercontent.com/assets/896692/23625282/7f2d79dc-025d-11e7-8728-d8924596f8fa.png) + +```python +import face_recognition +image = face_recognition.load_image_file("your_file.jpg") +face_landmarks_list = face_recognition.face_landmarks(image) +``` + +顔の特徴を見つけることは多くの重要なことに役立ちますが、[デジタルメイクアップ](https://github.com/ageitgey/face_recognition/blob/master/examples/digital_makeup.py) のようにさほど重要ではないことにも使うことができます。 + +![](https://cloud.githubusercontent.com/assets/896692/23625283/80638760-025d-11e7-80a2-1d2779f7ccab.png) + +#### 画像の中の顔を特定する + +それぞれの画像に写っている人物を認識します。 + +![](https://cloud.githubusercontent.com/assets/896692/23625229/45e049b6-025d-11e7-89cc-8a71cf89e713.png) + +```python +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) +``` + +他のPythonライブラリと一緒に用いてリアルタイムに顔認識することも可能です。 + +![](https://cloud.githubusercontent.com/assets/896692/24430398/36f0e3f0-13cb-11e7-8258-4d0c9ce1e419.gif) + +試す場合は[こちらのサンプルコード](https://github.com/ageitgey/face_recognition/blob/master/examples/facerec_from_webcam_faster.py) を参照してください。 + +## デモ + +ユーザーがコントリビュートした共有のJupyter notebookのデモがあります。(公式なサポートはありません)[![Deepnote](https://beta.deepnote.org/buttons/try-in-a-jupyter-notebook.svg)](https://beta.deepnote.org/launch?template=face_recognition) + +## インストール + +### 必要なもの + + * Python 3.3+ もしくは Python 2.7 + * macOS もしくは Linux (Windowsは公式にはサポートしていませんが動くかもしれません) + +### インストールオプション: + +#### MacもしくはLinuxにインストール + +はじめに、dlibをインストールします。(Pythonの拡張機能も有効にします) + + * [macOSもしくはUbuntuにdlibをソースコードからインストールする方法](https://gist.github.com/ageitgey/629d75c1baac34dfa5ca2a1928a7aeaf) + +次に、このモジュールをpypiから`pip3`(Python2の場合は`pip2`)を使ってインストールします。 + +```bash +pip3 install face_recognition +``` + +あるいは、[Docker](https://www.docker.com/)でこのライブラリを試すこともできます。詳しくは [こちらのセクション](#deployment)を参照してください。 + +もし、インストールが上手くいかない場合は、すでに用意されているVMイメージで試すこともできます。詳しくは[事前構成済みのVM](https://medium.com/@ageitgey/try-deep-learning-in-python-now-with-a-fully-pre-configured-vm-1d97d4c3e9b)を参照してください。(VMware Player もしくは VirtualBoxが対象) + +#### Nvidia Jetson Nanoボードにインストール + + * [Jetson Nanoインストール手順](https://medium.com/@ageitgey/build-a-hardware-based-face-recognition-system-for-150-with-the-nvidia-jetson-nano-and-python-a25cb8c891fd) + * この記事の手順通りにインストールを行ってください。現在、Jetson NanoのCUDAライブラリにはバグがあり、記事の手順通りにdlibの一行をコメントアウトし再コンパイルしないと失敗する恐れがあります。 + +#### Raspberry Pi 2+にインストール + + * [Raspberry Pi 2+インストール手順](https://gist.github.com/ageitgey/1ac8dbe8572f3f533df6269dab35df65) + +#### Windowsにインストール + +Windowsは公式サポートされていませんが、役立つインストール手順が投稿されています。 + + * [@masoudr's Windows 10 インストールガイド (dlib + face_recognition)](https://github.com/ageitgey/face_recognition/issues/175#issue-257710508) + + + +## 使用方法 + +### コマンドライン + +`face_recognition`をインストールすると、2つのシンプルなコマンドラインがついてきます。 + +* `face_recognition` - 画像もしくはフォルダの中の複数の画像から顔を認識します + +* `face_detection` - 画像もしくはフォルダの中の複数の画像から顔を検出します + +#### `face_recognition` コマンドラインツール + +`face_recognition` コマンドによって、画像もしくはフォルダの中の複数の画像から顔を認識することができます。 + +まずは、フォルダに知っている人たちの画像を一枚ずつ入れます。一人につき1枚の画像ファイルを用意し、画像のファイル名はその画像に写っている人物の名前にします。 + +![知っている人](https://cloud.githubusercontent.com/assets/896692/23582466/8324810e-00df-11e7-82cf-41515eba704d.png) + +次に、2つ目のフォルダに特定したい画像を入れます。 + +![知らない人](https://cloud.githubusercontent.com/assets/896692/23582465/81f422f8-00df-11e7-8b0d-75364f641f58.png) + +そして、`face_recognition`コマンドを実行し、知っている人の画像を入れたフォルダのパスと特定したい画像のフォルダ(もしくは画像ファイル)のパスを渡すと、それぞれの画像に誰がいるのかが分かります。 + +```bash +$ face_recognition ./pictures_of_people_i_know/ ./unknown_pictures/ + +/unknown_pictures/unknown.jpg,Barack Obama +/face_recognition_test/unknown_pictures/unknown.jpg,unknown_person +``` + +一つの顔につき一行が出力され、ファイル名と特定した人物の名前がカンマ区切りで表示されます。 + +`unknown_person`は知っている人の画像の中の誰ともマッチしなかった顔です。 + +#### `face_detection` コマンドラインツール + +`face_detection` コマンドによって、画像の中にある顔の位置(ピクセル座標)を検出することができます。 + +`face_detection` コマンドを実行し、顔を検出したい画像を入れたフォルダ(もしくは画像ファイル)のパスを渡してあげるだけです。 + +```bash +$ face_detection ./folder_with_pictures/ + +examples/image1.jpg,65,215,169,112 +examples/image2.jpg,62,394,211,244 +examples/image2.jpg,95,941,244,792 +``` + +検出された顔一つにつき一行が出力され、顔の上・右・下・左の座標(ピクセル単位)が表示されます。 + +##### 許容誤差の調整 / 感度 + +もし同一人物に対して複数の一致があった場合、画像の中に写っている人たちの顔が非常に似ている可能性があるので、顔の比較をより厳しくするために許容誤差の値を下げる必要があります。 + +`--tolerance` コマンドによってそれが可能になります。デフォルトの許容誤差の値(tolerance value)を0.6よりも低くすると、より厳密に顔の比較をすることができます。 + +```bash +$ face_recognition --tolerance 0.54 ./pictures_of_people_i_know/ ./unknown_pictures/ + +/unknown_pictures/unknown.jpg,Barack Obama +/face_recognition_test/unknown_pictures/unknown.jpg,unknown_person +``` + +もし許容誤差の設定を調整するために一致した顔の距離値(face distance)を確認したい場合は `--show-distance true` を使ってください。 + +```bash +$ face_recognition --show-distance true ./pictures_of_people_i_know/ ./unknown_pictures/ + +/unknown_pictures/unknown.jpg,Barack Obama,0.378542298956785 +/face_recognition_test/unknown_pictures/unknown.jpg,unknown_person,None +``` + +##### その他の例 + +ファイル名は出力せずに人物の名前だけを表示することもできます。 + +```bash +$ face_recognition ./pictures_of_people_i_know/ ./unknown_pictures/ | cut -d ',' -f2 + +Barack Obama +unknown_person +``` + +##### Face Recognition の高速化 + +マルチコア搭載コンピューターの場合は並列で実行することも可能です。例えば4CPUコアの場合、同じ時間で約4倍の画像を処理することができます。 + +Python 3.4 以上を使っている場合は`--cpus ` パラメータを渡します。 + +```bash +$ face_recognition --cpus 4 ./pictures_of_people_i_know/ ./unknown_pictures/ +``` + +`--cpus -1` のパラメータを渡すことで、システムのすべてのCPUコアを使うことも可能です。 + +#### Pythonモジュール + +`face_recognition` モジュールをインポートすると、数行のコードでとても簡単に操作を行うことができます。 + +API Docs: [https://face-recognition.readthedocs.io](https://face-recognition.readthedocs.io/en/latest/face_recognition.html). + +##### 自動的に画像の中のすべての顔を見つける + +```python +import face_recognition + +image = face_recognition.load_image_file("my_picture.jpg") +face_locations = face_recognition.face_locations(image) + +# face_locations is now an array listing the co-ordinates of each face! +``` + +試す場合は[こちらのサンプルコード](https://github.com/ageitgey/face_recognition/blob/master/examples/find_faces_in_picture.py)を参照してください。 + +さらに正確でディープラーニングをもとにした顔検出モデルを選択することも可能です。 + +注意:このモデルで良いパフォーマンスを出すにはGPUアクセラレーション(NVidiaのCUDAライブラリ経由)が必要です。また、`dlib` をコンパイルする際にCUDAサポートを有効にする必要あります。 + +```python +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! +``` + +試す場合は[こちらのサンプルコード](https://github.com/ageitgey/face_recognition/blob/master/examples/find_faces_in_picture_cnn.py)を参照してください。 + +大量の画像をGPUを使って処理する場合は、[こちらのサンプルコード](https://github.com/ageitgey/face_recognition/blob/master/examples/find_faces_in_batches.py)のようにバッチ処理することも可能です。 + +##### 自動的に画像の中の顔特徴を見つける + +```python +import face_recognition + +image = face_recognition.load_image_file("my_picture.jpg") +face_landmarks_list = face_recognition.face_landmarks(image) + +# face_landmarks_list is now an array with the locations of each facial feature in each face. +# face_landmarks_list[0]['left_eye'] would be the location and outline of the first person's left eye. +``` + +試す場合は[こちらのサンプルコード](https://github.com/ageitgey/face_recognition/blob/master/examples/find_facial_features_in_picture.py)を参照してください。 + +##### 画像の中の顔を認識し、その人物を特定する + +```python +import face_recognition + +picture_of_me = face_recognition.load_image_file("me.jpg") +my_face_encoding = face_recognition.face_encodings(picture_of_me)[0] + +# my_face_encoding now contains a universal 'encoding' of my facial features that can be compared to any other picture of a face! + +unknown_picture = face_recognition.load_image_file("unknown.jpg") +unknown_face_encoding = face_recognition.face_encodings(unknown_picture)[0] + +# Now we can see the two face encodings are of the same person with `compare_faces`! + +results = face_recognition.compare_faces([my_face_encoding], unknown_face_encoding) + +if results[0] == True: + print("It's a picture of me!") +else: + print("It's not a picture of me!") +``` + +試す場合は[こちらのサンプルコード](https://github.com/ageitgey/face_recognition/blob/master/examples/recognize_faces_in_pictures.py)を参照してください。 + +## Pythonコードのサンプル + +すべてのサンプルは[こちら](https://github.com/ageitgey/face_recognition/tree/master/examples)で見ることができます。 + +#### 顔検出 + +* [画像から顔を見つける](https://github.com/ageitgey/face_recognition/blob/master/examples/find_faces_in_picture.py) +* [画像から顔を見つける(ディープラーニングを使用する)](https://github.com/ageitgey/face_recognition/blob/master/examples/find_faces_in_picture_cnn.py) +* [大量の画像からGPUを用いて顔を見つける(ディープラーニングを使用する)](https://github.com/ageitgey/face_recognition/blob/master/examples/find_faces_in_batches.py) +* [WEBカメラによるライブ動画のすべての顔をぼかす(OpenCVのインストールが必要)](https://github.com/ageitgey/face_recognition/blob/master/examples/blur_faces_on_webcam.py) + +#### 顔の特徴 + +* [画像から顔の特徴を特定する](https://github.com/ageitgey/face_recognition/blob/master/examples/find_facial_features_in_picture.py) +* [デジタルメイクアップを施す](https://github.com/ageitgey/face_recognition/blob/master/examples/digital_makeup.py) + +#### 顔認識 + +* [知っている人の画像をもとに画像の中の知らない顔を発見する](https://github.com/ageitgey/face_recognition/blob/master/examples/recognize_faces_in_pictures.py) +* [画像の中の顔を四角で囲む](https://github.com/ageitgey/face_recognition/blob/master/examples/identify_and_draw_boxes_on_faces.py) +* [顔の距離値(face distance)によって比較する](https://github.com/ageitgey/face_recognition/blob/master/examples/face_distance.py) +* [WEBカメラによるライブ動画で顔認識する シンプル/低速バージョン (OpenCVのインストールが必要)](https://github.com/ageitgey/face_recognition/blob/master/examples/facerec_from_webcam.py) +* [WEBカメラによるライブ動画で顔認識する - 高速バージョン (OpenCVのインストールが必要)](https://github.com/ageitgey/face_recognition/blob/master/examples/facerec_from_webcam_faster.py) +* [動画ファイルを顔認識して新しいファイルに書き出す (OpenCVのインストールが必要)](https://github.com/ageitgey/face_recognition/blob/master/examples/facerec_from_video_file.py) +* [カメラ付きのRaspberry Piによって顔認識する](https://github.com/ageitgey/face_recognition/blob/master/examples/facerec_on_raspberry_pi.py) +* [顔認識ウェブサービスをHTTP経由で実行する(Flaskのインストールが必要)](https://github.com/ageitgey/face_recognition/blob/master/examples/web_service_example.py) +* [k近傍法で顔認識する](https://github.com/ageitgey/face_recognition/blob/master/examples/face_recognition_knn.py) +* [人物ごとに複数の画像をトレーニングし、SVM(サポートベクターマシン)を用いて顔認識する](https://github.com/ageitgey/face_recognition/blob/master/examples/face_recognition_svm.py) + +## スタンドアロンの実行ファイルの作成 + +`python` や `face_recognition`のインストールをせずに実行することができるスタンドアロンの実行ファイルを作る場合は、[PyInstaller](https://github.com/pyinstaller/pyinstaller)を使います。しかし、このライブラリを使用するにはカスタム設定が必要です。 + +## `face_recognition`をカバーする記事とガイド + +- 顔認識の仕組みについての記事: [ディープラーニングによる最新の顔認識](https://medium.com/@ageitgey/machine-learning-is-fun-part-4-modern-face-recognition-with-deep-learning-c3cffc121d78) + - アルゴリズムとそれらがどのように動くかを取り上げています。 +- Adrian Rosebrock氏の [OpenCV、Python、ディープラーニングによる顔認識](https://www.pyimagesearch.com/2018/06/18/face-recognition-with-opencv-python-and-deep-learning/) + - 実際に顔認識を使用する方法について取り上げています。 +- Adrian Rosebrock氏の [Raspberry Pi 顔認識](https://www.pyimagesearch.com/2018/06/25/raspberry-pi-face-recognition/) + - Raspberry Piで使用する方法について取り上げています。 +- Adrian Rosebrock氏の [Pythonによる顔のクラスタリング](https://www.pyimagesearch.com/2018/07/09/face-clustering-with-python/) + - それぞれの画像に出現する人物に基づき、教師なし学習を用いて自動的に画像をクラスター化する方法について取り上げています。 + +## 顔認識の仕組み + +ブラックボックスライブラリに依存せず、顔の位置や認識の仕組みを知りたい方は[こちらの記事](https://medium.com/@ageitgey/machine-learning-is-fun-part-4-modern-face-recognition-with-deep-learning-c3cffc121d78)を読んでください。 + +## 注意事項 + +* この顔認識モデルは大人でトレーニングされており、子どもではあまり上手く機能しません。比較する閾値をデフォルト(0.6)のままで使用すると子どもを混同しやすくなります。 + +* 精度は民族グループによって異なる可能性があります。詳しくは[こちらのwikiページ](https://github.com/ageitgey/face_recognition/wiki/Face-Recognition-Accuracy-Problems#question-face-recognition-works-well-with-european-individuals-but-overall-accuracy-is-lower-with-asian-individuals)を参照してください。 + +## クラウドにデプロイ (Heroku, AWSなど) + +`face_recognition`はC++で書かれた`dlib`に依存しているため、HerokuやAWSのようなクラウドサーバにこれらを使ったアプリをデプロイするのは難しい場合があります。 + +それを簡単にするために、このレポジトリには[Docker](https://www.docker.com/)コンテナ内で`face_recognition`のビルドされたアプリを実行する方法を示したサンプルDockerfileがあります。これによって、Dockerイメージをサポートしているすべてのサービスにデプロイできるようになるはずです。 + +コマンドを実行し、ローカルでDockerイメージを試すことができます。: `docker-compose up --build` + +GPU (drivers >= 384.81) および [Nvidia-Docker](https://github.com/NVIDIA/nvidia-docker) がインストールされているLinuxユーザーはGPUでサンプルを実行することができます。[docker-compose.yml](docker-compose.yml) を開き、`dockerfile: Dockerfile.gpu`と`runtime: nvidia`の行をコメントアウトしてください。 + +## なにか問題が発生したら + +もし問題が発生した場合はGitHubにIssueをあげる前に、まずはwikiの[よくあるエラー](https://github.com/ageitgey/face_recognition/wiki/Common-Errors)をお読みください + +## 謝意 + +* dlibを作り、このライブラリで使っているトレーニングされた顔の特徴検出とフェイスエンコーディングモデルを提供してくれた[Davis King](https://github.com/davisking) ([@nulhom](https://twitter.com/nulhom))、本当にありがとうございます。 + フェイスエンコーディングを動かしているResNetについての情報は彼の[ブログ](http://blog.dlib.net/2017/02/high-quality-face-recognition-with-deep.html)を見てください。 + +* このようなライブラリがPythonで簡単に楽しくできるためのnumpy, scipy, scikit-image, pillow など全ての素晴らしいPythonデータサイエンスライブラリに取り組んでいる人たちに感謝しています。 + +* Pythonプロジェクトのパッケージングをより易しくする[Cookiecutter](https://github.com/audreyr/cookiecutter)と[audreyr/cookiecutter-pypackage](https://github.com/audreyr/cookiecutter-pypackage)に感謝しています。 \ No newline at end of file From 2d3c0ea1b7097f755ab525d488a2c485d4ea49cb Mon Sep 17 00:00:00 2001 From: Miki Date: Sun, 2 Feb 2020 19:14:12 +0900 Subject: [PATCH 20/53] add Japanese translation --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d35272d79..e07c74911 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Face Recognition -_You can also read a translated version of this file [in Chinese 简体中文版](https://github.com/ageitgey/face_recognition/blob/master/README_Simplified_Chinese.md) or [in Korean 한국어](https://github.com/ageitgey/face_recognition/blob/master/README_Korean.md)._ +_You can also read a translated version of this file [in Chinese 简体中文版](https://github.com/ageitgey/face_recognition/blob/master/README_Simplified_Chinese.md) or [in Korean 한국어](https://github.com/ageitgey/face_recognition/blob/master/README_Korean.md) or [in Japanese 日本語](https://github.com/m-i-k-i/face_recognition/blob/master/README_Japanese.md)._ Recognize and manipulate faces from Python or from the command line with the world's simplest face recognition library. From efbb40f2235d64f0d38d2eb6cebc238df57c250f Mon Sep 17 00:00:00 2001 From: Abdolkarim Saeedi Date: Sun, 19 Jan 2020 11:12:59 +0330 Subject: [PATCH 21/53] Add files via upload Real time fast face recognition on ip cameras using knn. --- examples/facerec_ipcamera_knn.py | 214 +++++++++++++++++++++++++++++++ 1 file changed, 214 insertions(+) create mode 100644 examples/facerec_ipcamera_knn.py diff --git a/examples/facerec_ipcamera_knn.py b/examples/facerec_ipcamera_knn.py new file mode 100644 index 000000000..038dac01f --- /dev/null +++ b/examples/facerec_ipcamera_knn.py @@ -0,0 +1,214 @@ +""" +This is an example of using the k-nearest-neighbors (KNN) algorithm for face recognition. + +When should I use this example? +This example is useful when you wish to recognize a large set of known people, +and make a prediction for an unknown person in a feasible computation time. + +Algorithm Description: +The knn classifier is first trained on a set of labeled (known) faces and can then predict the person +in a live stream by finding the k most similar faces (images with closet face-features under eucledian distance) +in its training set, and performing a majority vote (possibly weighted) on their label. + +For example, if k=3, and the three closest face images to the given image in the training set are one image of Biden +and two images of Obama, The result would be 'Obama'. + +* This implementation uses a weighted vote, such that the votes of closer-neighbors are weighted more heavily. + +Usage: + +1. Prepare a set of images of the known people you want to recognize. Organize the images in a single directory + with a sub-directory for each known person. + +2. Then, call the 'train' function with the appropriate parameters. Make sure to pass in the 'model_save_path' if you + want to save the model to disk so you can re-use the model without having to re-train it. + +3. Call 'predict' and pass in your trained model to recognize the people in a live video stream. + +NOTE: This example requires scikit-learn, opencv and numpy to be installed! You can install it with pip: + +$ pip3 install scikit-learn +$ pip3 install numpy +$ pip3 install opencv-contrib-python + +""" + +import cv2 +import math +from sklearn import neighbors +import os +import os.path +import pickle +from PIL import Image, ImageDraw +import face_recognition +from face_recognition.face_recognition_cli import image_files_in_folder +import numpy as np + + +ALLOWED_EXTENSIONS = {'png', 'jpg', 'jpeg', 'JPG'} + + +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: + / + ├── / + │ ├── .jpeg + │ ├── .jpeg + │ ├── ... + ├── / + │ ├── .jpeg + │ └── .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_frame, knn_clf=None, model_path=None, distance_threshold=0.5): + """ + Recognizes faces in given image using a trained KNN classifier + + :param X_frame: frame to do the prediction on. + :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 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) + + X_face_locations = face_recognition.face_locations(X_frame) + + # 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 image + faces_encodings = face_recognition.face_encodings(X_frame, 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)] + + +def show_prediction_labels_on_image(frame, predictions): + """ + Shows the face recognition results visually. + + :param frame: frame to show the predictions on + :param predictions: results of the predict function + :return opencv suited image to be fitting with cv2.imshow fucntion: + """ + pil_image = Image.fromarray(frame) + draw = ImageDraw.Draw(pil_image) + + for name, (top, right, bottom, left) in predictions: + # enlarge the predictions for the full sized image. + top *= 2 + right *= 2 + bottom *= 2 + left *= 2 + # Draw a box around the face using the Pillow module + draw.rectangle(((left, top), (right, bottom)), outline=(0, 0, 255)) + + # There's a bug in Pillow where it blows up with non-UTF-8 text + # when using the default bitmap font + name = name.encode("UTF-8") + + # Draw a label with a name below the face + text_width, text_height = draw.textsize(name) + draw.rectangle(((left, bottom - text_height - 10), (right, bottom)), fill=(0, 0, 255), outline=(0, 0, 255)) + draw.text((left + 6, bottom - text_height - 5), name, fill=(255, 255, 255, 255)) + + # Remove the drawing library from memory as per the Pillow docs. + del draw + # Save image in open-cv format to be able to show it. + + opencvimage = np.array(pil_image) + return opencvimage + + +if __name__ == "__main__": + print("Training KNN classifier...") + classifier = train("knn_examples/train", model_save_path="trained_knn_model.clf", n_neighbors=2) + print("Training complete!") + # process one frame in every 30 frames for speed + process_this_frame = 29 + print('Setting cameras up...') + # multiple cameras can be used with the format url = 'http://username:password@camera_ip:port' + url1 = 'http://admin:admin@192.168.0.106:8081/' + cap1 = cv2.VideoCapture(url1) + while 1 > 0: + ret1, frame1 = cap1.read() + if ret1: + # Different resizing options can be chosen based on desired program runtime. + img1 = cv2.resize(frame1, (0, 0), fx=0.5, fy=0.5) + process_this_frame = process_this_frame + 1 + if process_this_frame % 30 == 0: + predictions1 = predict(img1, model_path="trained_knn_model.clf") + # Image resizing for more stable streaming + frame1 = show_prediction_labels_on_image(frame1, predictions1) + cv2.imshow('camera1', frame1) + if ord('q') == cv2.waitKey(10): + cap1.release() + cv2.destroyAllWindows() + exit(0) From 9fbab17b5716425817251e9343fb80a44a75e521 Mon Sep 17 00:00:00 2001 From: Abdolkarim Saeedi Date: Sun, 19 Jan 2020 11:13:42 +0330 Subject: [PATCH 22/53] Delete facerec_ipcamera_knn.py --- examples/facerec_ipcamera_knn.py | 214 ------------------------------- 1 file changed, 214 deletions(-) delete mode 100644 examples/facerec_ipcamera_knn.py diff --git a/examples/facerec_ipcamera_knn.py b/examples/facerec_ipcamera_knn.py deleted file mode 100644 index 038dac01f..000000000 --- a/examples/facerec_ipcamera_knn.py +++ /dev/null @@ -1,214 +0,0 @@ -""" -This is an example of using the k-nearest-neighbors (KNN) algorithm for face recognition. - -When should I use this example? -This example is useful when you wish to recognize a large set of known people, -and make a prediction for an unknown person in a feasible computation time. - -Algorithm Description: -The knn classifier is first trained on a set of labeled (known) faces and can then predict the person -in a live stream by finding the k most similar faces (images with closet face-features under eucledian distance) -in its training set, and performing a majority vote (possibly weighted) on their label. - -For example, if k=3, and the three closest face images to the given image in the training set are one image of Biden -and two images of Obama, The result would be 'Obama'. - -* This implementation uses a weighted vote, such that the votes of closer-neighbors are weighted more heavily. - -Usage: - -1. Prepare a set of images of the known people you want to recognize. Organize the images in a single directory - with a sub-directory for each known person. - -2. Then, call the 'train' function with the appropriate parameters. Make sure to pass in the 'model_save_path' if you - want to save the model to disk so you can re-use the model without having to re-train it. - -3. Call 'predict' and pass in your trained model to recognize the people in a live video stream. - -NOTE: This example requires scikit-learn, opencv and numpy to be installed! You can install it with pip: - -$ pip3 install scikit-learn -$ pip3 install numpy -$ pip3 install opencv-contrib-python - -""" - -import cv2 -import math -from sklearn import neighbors -import os -import os.path -import pickle -from PIL import Image, ImageDraw -import face_recognition -from face_recognition.face_recognition_cli import image_files_in_folder -import numpy as np - - -ALLOWED_EXTENSIONS = {'png', 'jpg', 'jpeg', 'JPG'} - - -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: - / - ├── / - │ ├── .jpeg - │ ├── .jpeg - │ ├── ... - ├── / - │ ├── .jpeg - │ └── .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_frame, knn_clf=None, model_path=None, distance_threshold=0.5): - """ - Recognizes faces in given image using a trained KNN classifier - - :param X_frame: frame to do the prediction on. - :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 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) - - X_face_locations = face_recognition.face_locations(X_frame) - - # 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 image - faces_encodings = face_recognition.face_encodings(X_frame, 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)] - - -def show_prediction_labels_on_image(frame, predictions): - """ - Shows the face recognition results visually. - - :param frame: frame to show the predictions on - :param predictions: results of the predict function - :return opencv suited image to be fitting with cv2.imshow fucntion: - """ - pil_image = Image.fromarray(frame) - draw = ImageDraw.Draw(pil_image) - - for name, (top, right, bottom, left) in predictions: - # enlarge the predictions for the full sized image. - top *= 2 - right *= 2 - bottom *= 2 - left *= 2 - # Draw a box around the face using the Pillow module - draw.rectangle(((left, top), (right, bottom)), outline=(0, 0, 255)) - - # There's a bug in Pillow where it blows up with non-UTF-8 text - # when using the default bitmap font - name = name.encode("UTF-8") - - # Draw a label with a name below the face - text_width, text_height = draw.textsize(name) - draw.rectangle(((left, bottom - text_height - 10), (right, bottom)), fill=(0, 0, 255), outline=(0, 0, 255)) - draw.text((left + 6, bottom - text_height - 5), name, fill=(255, 255, 255, 255)) - - # Remove the drawing library from memory as per the Pillow docs. - del draw - # Save image in open-cv format to be able to show it. - - opencvimage = np.array(pil_image) - return opencvimage - - -if __name__ == "__main__": - print("Training KNN classifier...") - classifier = train("knn_examples/train", model_save_path="trained_knn_model.clf", n_neighbors=2) - print("Training complete!") - # process one frame in every 30 frames for speed - process_this_frame = 29 - print('Setting cameras up...') - # multiple cameras can be used with the format url = 'http://username:password@camera_ip:port' - url1 = 'http://admin:admin@192.168.0.106:8081/' - cap1 = cv2.VideoCapture(url1) - while 1 > 0: - ret1, frame1 = cap1.read() - if ret1: - # Different resizing options can be chosen based on desired program runtime. - img1 = cv2.resize(frame1, (0, 0), fx=0.5, fy=0.5) - process_this_frame = process_this_frame + 1 - if process_this_frame % 30 == 0: - predictions1 = predict(img1, model_path="trained_knn_model.clf") - # Image resizing for more stable streaming - frame1 = show_prediction_labels_on_image(frame1, predictions1) - cv2.imshow('camera1', frame1) - if ord('q') == cv2.waitKey(10): - cap1.release() - cv2.destroyAllWindows() - exit(0) From c4106ce83575938268c12a9492b15658c2a573b2 Mon Sep 17 00:00:00 2001 From: Abdolkarim Saeedi Date: Sun, 19 Jan 2020 11:15:18 +0330 Subject: [PATCH 23/53] Add facerec_ipcamera_knn.py example Real time facial recognition on ip cameras using knn. --- examples/facerec_ipcamera_knn.py | 214 +++++++++++++++++++++++++++++++ 1 file changed, 214 insertions(+) create mode 100644 examples/facerec_ipcamera_knn.py diff --git a/examples/facerec_ipcamera_knn.py b/examples/facerec_ipcamera_knn.py new file mode 100644 index 000000000..038dac01f --- /dev/null +++ b/examples/facerec_ipcamera_knn.py @@ -0,0 +1,214 @@ +""" +This is an example of using the k-nearest-neighbors (KNN) algorithm for face recognition. + +When should I use this example? +This example is useful when you wish to recognize a large set of known people, +and make a prediction for an unknown person in a feasible computation time. + +Algorithm Description: +The knn classifier is first trained on a set of labeled (known) faces and can then predict the person +in a live stream by finding the k most similar faces (images with closet face-features under eucledian distance) +in its training set, and performing a majority vote (possibly weighted) on their label. + +For example, if k=3, and the three closest face images to the given image in the training set are one image of Biden +and two images of Obama, The result would be 'Obama'. + +* This implementation uses a weighted vote, such that the votes of closer-neighbors are weighted more heavily. + +Usage: + +1. Prepare a set of images of the known people you want to recognize. Organize the images in a single directory + with a sub-directory for each known person. + +2. Then, call the 'train' function with the appropriate parameters. Make sure to pass in the 'model_save_path' if you + want to save the model to disk so you can re-use the model without having to re-train it. + +3. Call 'predict' and pass in your trained model to recognize the people in a live video stream. + +NOTE: This example requires scikit-learn, opencv and numpy to be installed! You can install it with pip: + +$ pip3 install scikit-learn +$ pip3 install numpy +$ pip3 install opencv-contrib-python + +""" + +import cv2 +import math +from sklearn import neighbors +import os +import os.path +import pickle +from PIL import Image, ImageDraw +import face_recognition +from face_recognition.face_recognition_cli import image_files_in_folder +import numpy as np + + +ALLOWED_EXTENSIONS = {'png', 'jpg', 'jpeg', 'JPG'} + + +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: + / + ├── / + │ ├── .jpeg + │ ├── .jpeg + │ ├── ... + ├── / + │ ├── .jpeg + │ └── .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_frame, knn_clf=None, model_path=None, distance_threshold=0.5): + """ + Recognizes faces in given image using a trained KNN classifier + + :param X_frame: frame to do the prediction on. + :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 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) + + X_face_locations = face_recognition.face_locations(X_frame) + + # 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 image + faces_encodings = face_recognition.face_encodings(X_frame, 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)] + + +def show_prediction_labels_on_image(frame, predictions): + """ + Shows the face recognition results visually. + + :param frame: frame to show the predictions on + :param predictions: results of the predict function + :return opencv suited image to be fitting with cv2.imshow fucntion: + """ + pil_image = Image.fromarray(frame) + draw = ImageDraw.Draw(pil_image) + + for name, (top, right, bottom, left) in predictions: + # enlarge the predictions for the full sized image. + top *= 2 + right *= 2 + bottom *= 2 + left *= 2 + # Draw a box around the face using the Pillow module + draw.rectangle(((left, top), (right, bottom)), outline=(0, 0, 255)) + + # There's a bug in Pillow where it blows up with non-UTF-8 text + # when using the default bitmap font + name = name.encode("UTF-8") + + # Draw a label with a name below the face + text_width, text_height = draw.textsize(name) + draw.rectangle(((left, bottom - text_height - 10), (right, bottom)), fill=(0, 0, 255), outline=(0, 0, 255)) + draw.text((left + 6, bottom - text_height - 5), name, fill=(255, 255, 255, 255)) + + # Remove the drawing library from memory as per the Pillow docs. + del draw + # Save image in open-cv format to be able to show it. + + opencvimage = np.array(pil_image) + return opencvimage + + +if __name__ == "__main__": + print("Training KNN classifier...") + classifier = train("knn_examples/train", model_save_path="trained_knn_model.clf", n_neighbors=2) + print("Training complete!") + # process one frame in every 30 frames for speed + process_this_frame = 29 + print('Setting cameras up...') + # multiple cameras can be used with the format url = 'http://username:password@camera_ip:port' + url1 = 'http://admin:admin@192.168.0.106:8081/' + cap1 = cv2.VideoCapture(url1) + while 1 > 0: + ret1, frame1 = cap1.read() + if ret1: + # Different resizing options can be chosen based on desired program runtime. + img1 = cv2.resize(frame1, (0, 0), fx=0.5, fy=0.5) + process_this_frame = process_this_frame + 1 + if process_this_frame % 30 == 0: + predictions1 = predict(img1, model_path="trained_knn_model.clf") + # Image resizing for more stable streaming + frame1 = show_prediction_labels_on_image(frame1, predictions1) + cv2.imshow('camera1', frame1) + if ord('q') == cv2.waitKey(10): + cap1.release() + cv2.destroyAllWindows() + exit(0) From 5e8114686e8f8c7e125d79e9367efb11c693c975 Mon Sep 17 00:00:00 2001 From: Abdolkarim Saeedi Date: Sun, 19 Jan 2020 12:02:09 +0330 Subject: [PATCH 24/53] Update facerec_ipcamera_knn.py --- examples/facerec_ipcamera_knn.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/examples/facerec_ipcamera_knn.py b/examples/facerec_ipcamera_knn.py index 038dac01f..352efdbcd 100644 --- a/examples/facerec_ipcamera_knn.py +++ b/examples/facerec_ipcamera_knn.py @@ -195,19 +195,19 @@ def show_prediction_labels_on_image(frame, predictions): process_this_frame = 29 print('Setting cameras up...') # multiple cameras can be used with the format url = 'http://username:password@camera_ip:port' - url1 = 'http://admin:admin@192.168.0.106:8081/' - cap1 = cv2.VideoCapture(url1) + url = 'http://admin:admin@192.168.0.106:8081/' + cap = cv2.VideoCapture(url) while 1 > 0: - ret1, frame1 = cap1.read() - if ret1: + ret, frame = cap.read() + if ret: # Different resizing options can be chosen based on desired program runtime. - img1 = cv2.resize(frame1, (0, 0), fx=0.5, fy=0.5) + # Image resizing for more stable streaming + img = cv2.resize(frame, (0, 0), fx=0.5, fy=0.5) process_this_frame = process_this_frame + 1 if process_this_frame % 30 == 0: - predictions1 = predict(img1, model_path="trained_knn_model.clf") - # Image resizing for more stable streaming - frame1 = show_prediction_labels_on_image(frame1, predictions1) - cv2.imshow('camera1', frame1) + predictions = predict(img, model_path="trained_knn_model.clf") + frame = show_prediction_labels_on_image(frame, predictions) + cv2.imshow('camera', frame) if ord('q') == cv2.waitKey(10): cap1.release() cv2.destroyAllWindows() From da03f6ea24208939b5aed0c3eae705370970317a Mon Sep 17 00:00:00 2001 From: Adam Geitgey Date: Thu, 20 Feb 2020 14:17:57 +0000 Subject: [PATCH 25/53] Update CI badge --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index e07c74911..764c2dc22 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ you do face recognition on a folder of images from the command line! [![PyPI](https://img.shields.io/pypi/v/face_recognition.svg)](https://pypi.python.org/pypi/face_recognition) -[![Build Status](https://travis-ci.org/ageitgey/face_recognition.svg?branch=master)](https://travis-ci.org/ageitgey/face_recognition) +[![Build Status](https://github.com/ageitgey/face_recognition/workflows/CI/badge.svg?branch=master&event=push)](https://github.com/ageitgey/face_recognition/actions?query=workflow%3ACI) [![Documentation Status](https://readthedocs.org/projects/face-recognition/badge/?version=latest)](http://face-recognition.readthedocs.io/en/latest/?badge=latest) ## Features From e70f97e4a146e105228953a75f4919d10c6e0fff Mon Sep 17 00:00:00 2001 From: Adam Geitgey Date: Thu, 20 Feb 2020 14:19:46 +0000 Subject: [PATCH 26/53] Bump version in setup.py --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 0a81e953f..3a1e8e115 100644 --- a/setup.py +++ b/setup.py @@ -24,7 +24,7 @@ setup( name='face_recognition', - version='1.2.3', + version='1.3.0', description="Recognize faces from Python or from the command line", long_description=readme + '\n\n' + history, author="Adam Geitgey", From d34c622bf42e2c619505a4884017051ecf61ac77 Mon Sep 17 00:00:00 2001 From: Adam Geitgey Date: Thu, 20 Feb 2020 14:20:21 +0000 Subject: [PATCH 27/53] Update setup.cfg --- setup.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.cfg b/setup.cfg index 9d5ddc947..569ed72b9 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 1.2.1 +current_version = 1.3.0 commit = True tag = True From a1fe6c4229e537c9f6d821c37643176ee725bf8d Mon Sep 17 00:00:00 2001 From: Marcos Benevides Date: Sun, 19 Apr 2020 11:51:53 -0300 Subject: [PATCH 28/53] Fix docstrings in api.py --- face_recognition/api.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/face_recognition/api.py b/face_recognition/api.py index 9df9e6e6d..58cc48826 100644 --- a/face_recognition/api.py +++ b/face_recognition/api.py @@ -65,7 +65,7 @@ def face_distance(face_encodings, face_to_compare): Given a list of face encodings, compare them to a known face encoding and get a euclidean distance for each comparison face. The distance tells you how similar the faces are. - :param faces: List of face encodings to compare + :param face_encodings: List of face encodings to compare :param face_to_compare: A face encoding to compare against :return: A numpy ndarray with the distance for each face in the same order as the 'faces' array """ @@ -125,7 +125,7 @@ def _raw_face_locations_batched(images, number_of_times_to_upsample=1, batch_siz """ Returns an 2d array of dlib rects of human faces in a image using the cnn face detector - :param img: A list of images (each as a numpy array) + :param images: A list of images (each as a numpy array) :param number_of_times_to_upsample: How many times to upsample the image looking for faces. Higher numbers find smaller faces. :return: A list of dlib 'rect' objects of found face locations """ From dd9d080cda9a4454b43da3b0aa9d805a37c96d77 Mon Sep 17 00:00:00 2001 From: Aref Ariyapour Date: Wed, 22 Apr 2020 13:39:19 +0200 Subject: [PATCH 29/53] Fix exit key in blink detection example Set q for exiting the program. Move cv2.waitKey() outside the for loop that detects face landmarks. --- examples/blink_detection.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/examples/blink_detection.py b/examples/blink_detection.py index dd7db2d0d..a6c3568b1 100644 --- a/examples/blink_detection.py +++ b/examples/blink_detection.py @@ -57,7 +57,6 @@ def main(): cv2.rectangle(small_frame, left_eye[0], right_eye[-1], color, thickness) cv2.imshow('Video', small_frame) - cv2.waitKey(1) ear_left = get_ear(left_eye) ear_right = get_ear(right_eye) @@ -80,6 +79,9 @@ def main(): closed_count = 0 process = not process + key = cv2.waitKey(1) & 0xFF + if key == ord("q"): + break def get_ear(eye): From 15ab2fae584e0fe327135470b49d3463d94e6666 Mon Sep 17 00:00:00 2001 From: Aref Ariyapour Date: Wed, 22 Apr 2020 13:54:56 +0200 Subject: [PATCH 30/53] Fix error caused by keyboard module in blink detection example Using the keyboard module in linux requires root permission and if virtual envs are used to run the script, it will produce the following error: ImportError(You must be root to use this library on linux.) To solve this, use OpenCV waitKey() functionality. --- examples/blink_detection.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/blink_detection.py b/examples/blink_detection.py index a6c3568b1..bd5bbb624 100644 --- a/examples/blink_detection.py +++ b/examples/blink_detection.py @@ -15,7 +15,6 @@ import cv2 import time from scipy.spatial import distance as dist -import keyboard as kb EYES_CLOSED_SECONDS = 5 @@ -74,8 +73,9 @@ def main(): while (asleep): #continue this loop until they wake up and acknowledge music print("EYES CLOSED") - if (kb.is_pressed('space')): + if cv2.waitKey(1) == 32: #Wait for space key asleep = False + print("EYES OPENED") closed_count = 0 process = not process From 35a3f9f983c3b028f1d56fcb9223dab109ad9a80 Mon Sep 17 00:00:00 2001 From: zhulinpinyu Date: Wed, 1 Jul 2020 15:40:52 +0800 Subject: [PATCH 31/53] fix annotation --- face_recognition/api.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/face_recognition/api.py b/face_recognition/api.py index 9df9e6e6d..e42d39e91 100644 --- a/face_recognition/api.py +++ b/face_recognition/api.py @@ -65,7 +65,7 @@ def face_distance(face_encodings, face_to_compare): Given a list of face encodings, compare them to a known face encoding and get a euclidean distance for each comparison face. The distance tells you how similar the faces are. - :param faces: List of face encodings to compare + :param face_encodings: List of face encodings to compare :param face_to_compare: A face encoding to compare against :return: A numpy ndarray with the distance for each face in the same order as the 'faces' array """ From 876ebaaf034273708cb362914051b330661d747a Mon Sep 17 00:00:00 2001 From: Vishnu Mohandas Date: Thu, 16 Jul 2020 04:17:01 +0530 Subject: [PATCH 32/53] Fix minor error in documentation detailing the default model in use for face_encodings --- face_recognition/api.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/face_recognition/api.py b/face_recognition/api.py index 9df9e6e6d..ccabaee38 100644 --- a/face_recognition/api.py +++ b/face_recognition/api.py @@ -207,7 +207,7 @@ def face_encodings(face_image, known_face_locations=None, num_jitters=1, model=" :param face_image: The image that contains one or more faces :param known_face_locations: Optional - the bounding boxes of each face if you already know them. :param num_jitters: How many times to re-sample the face when calculating encoding. Higher is more accurate, but slower (i.e. 100 is 100x slower) - :param model: Optional - which model to use. "large" (default) or "small" which only returns 5 points but is faster. + :param model: Optional - which model to use. "large" or "small" (default) which only returns 5 points but is faster. :return: A list of 128-dimensional face encodings (one for each face in the image) """ raw_landmarks = _raw_face_landmarks(face_image, known_face_locations, model) From 13ba6a759a46f73d4f59d2f35b4234bb793ca00d Mon Sep 17 00:00:00 2001 From: Alex Daly <11139509+azdaly@users.noreply.github.com> Date: Sun, 9 Aug 2020 06:55:40 -0500 Subject: [PATCH 33/53] Adding a fix for a common macOS failure mode --- README.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 764c2dc22..df0e0f17d 100644 --- a/README.md +++ b/README.md @@ -89,8 +89,12 @@ User-contributed shared Jupyter notebook demo (not officially supported): [![Dee First, make sure you have dlib already installed with Python bindings: * [How to install dlib from source on macOS or Ubuntu](https://gist.github.com/ageitgey/629d75c1baac34dfa5ca2a1928a7aeaf) + +Then, make sure you have cmake installed: + +```brew install cmake``` -Then, install this module from pypi using `pip3` (or `pip2` for Python 2): +Finally, install this module from pypi using `pip3` (or `pip2` for Python 2): ```bash pip3 install face_recognition From 8057a2cf250601c5edb03dc0faf15f6c72c68909 Mon Sep 17 00:00:00 2001 From: Tim Gates Date: Sat, 12 Sep 2020 07:29:50 +1000 Subject: [PATCH 34/53] docs: Fix simple typo, eucledian -> euclidean There is a small typo in examples/face_recognition_knn.py, examples/facerec_ipcamera_knn.py. Should read `euclidean` rather than `eucledian`. --- examples/face_recognition_knn.py | 2 +- examples/facerec_ipcamera_knn.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/face_recognition_knn.py b/examples/face_recognition_knn.py index d99b760b5..b16c46d9d 100644 --- a/examples/face_recognition_knn.py +++ b/examples/face_recognition_knn.py @@ -7,7 +7,7 @@ Algorithm Description: The knn classifier is first trained on a set of labeled (known) faces and can then predict the person -in an unknown image by finding the k most similar faces (images with closet face-features under eucledian distance) +in an unknown image by finding the k most similar faces (images with closet face-features under euclidean distance) in its training set, and performing a majority vote (possibly weighted) on their label. For example, if k=3, and the three closest face images to the given image in the training set are one image of Biden diff --git a/examples/facerec_ipcamera_knn.py b/examples/facerec_ipcamera_knn.py index 352efdbcd..ae9223416 100644 --- a/examples/facerec_ipcamera_knn.py +++ b/examples/facerec_ipcamera_knn.py @@ -7,7 +7,7 @@ Algorithm Description: The knn classifier is first trained on a set of labeled (known) faces and can then predict the person -in a live stream by finding the k most similar faces (images with closet face-features under eucledian distance) +in a live stream by finding the k most similar faces (images with closet face-features under euclidean distance) in its training set, and performing a majority vote (possibly weighted) on their label. For example, if k=3, and the three closest face images to the given image in the training set are one image of Biden From 3337c1e0505bef73840690807d99101656995152 Mon Sep 17 00:00:00 2001 From: osthafen Date: Thu, 17 Sep 2020 10:12:38 +0200 Subject: [PATCH 35/53] Make --upsample a parameter for command line face_recognition Otherwise smaller faces can't be located via command line --- face_recognition/face_detection_cli.py | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/face_recognition/face_detection_cli.py b/face_recognition/face_detection_cli.py index 595636c06..bf7f65e22 100644 --- a/face_recognition/face_detection_cli.py +++ b/face_recognition/face_detection_cli.py @@ -14,9 +14,9 @@ def print_result(filename, location): print("{},{},{},{},{}".format(filename, top, right, bottom, left)) -def test_image(image_to_check, model): +def test_image(image_to_check, model, upsample): unknown_image = face_recognition.load_image_file(image_to_check) - face_locations = face_recognition.face_locations(unknown_image, number_of_times_to_upsample=0, model=model) + face_locations = face_recognition.face_locations(unknown_image, number_of_times_to_upsample=upsample, model=model) for face_location in face_locations: print_result(image_to_check, face_location) @@ -26,7 +26,7 @@ def image_files_in_folder(folder): return [os.path.join(folder, f) for f in os.listdir(folder) if re.match(r'.*\.(jpg|jpeg|png)', f, flags=re.I)] -def process_images_in_process_pool(images_to_check, number_of_cpus, model): +def process_images_in_process_pool(images_to_check, number_of_cpus, model, upsample): if number_of_cpus == -1: processes = None else: @@ -42,6 +42,7 @@ def process_images_in_process_pool(images_to_check, number_of_cpus, model): function_parameters = zip( images_to_check, itertools.repeat(model), + itertools.repeat(upsample), ) pool.starmap(test_image, function_parameters) @@ -51,7 +52,8 @@ def process_images_in_process_pool(images_to_check, number_of_cpus, model): @click.argument('image_to_check') @click.option('--cpus', default=1, help='number of CPU cores to use in parallel. -1 means "use all in system"') @click.option('--model', default="hog", help='Which face detection model to use. Options are "hog" or "cnn".') -def main(image_to_check, cpus, model): +@click.option('--upsample', default=0, help='How many times to upsample the image looking for faces. Higher numbers find smaller faces.') +def main(image_to_check, cpus, model, upsample): # Multi-core processing only supported on Python 3.4 or greater if (sys.version_info < (3, 4)) and cpus != 1: click.echo("WARNING: Multi-processing support requires Python 3.4 or greater. Falling back to single-threaded processing!") @@ -59,11 +61,11 @@ def main(image_to_check, cpus, model): if os.path.isdir(image_to_check): if cpus == 1: - [test_image(image_file, model) for image_file in image_files_in_folder(image_to_check)] + [test_image(image_file, model, upsample) for image_file in image_files_in_folder(image_to_check)] else: - process_images_in_process_pool(image_files_in_folder(image_to_check), cpus, model) + process_images_in_process_pool(image_files_in_folder(image_to_check), cpus, model, upsample) else: - test_image(image_to_check, model) + test_image(image_to_check, model, upsample) if __name__ == "__main__": From e0addfcb0d8f72f91ff3b5198bd7fa66c186f83d Mon Sep 17 00:00:00 2001 From: Adam Geitgey Date: Thu, 20 Feb 2020 14:26:53 +0000 Subject: [PATCH 36/53] Fix pypi upload for new releases --- Makefile | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 5af87c9f6..5e90960b1 100644 --- a/Makefile +++ b/Makefile @@ -75,8 +75,9 @@ servedocs: docs ## compile the docs watching for changes watchmedo shell-command -p '*.rst' -c '$(MAKE) -C docs html' -R -D . release: clean ## package and upload a release - python3 setup.py sdist upload - python3 setup.py bdist_wheel upload + python3 setup.py sdist + python3 setup.py bdist_wheel + twine upload dist/* dist: clean ## builds source and wheel package python3 setup.py sdist From 8f332778240a9c794f10eadc3067225efe61244b Mon Sep 17 00:00:00 2001 From: Adam Geitgey Date: Sat, 26 Sep 2020 16:12:53 +0100 Subject: [PATCH 37/53] Drop Python 2.x support and bump version --- .github/workflows/main.yml | 2 +- HISTORY.rst | 13 +++++++++++++ face_recognition/__init__.py | 2 +- setup.cfg | 2 +- setup.py | 4 +--- tox.ini | 3 +-- 6 files changed, 18 insertions(+), 8 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index dee6d6491..d299fc19b 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -5,7 +5,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - python-version: [2.7, 3.5, 3.6, 3.7, 3.8] + python-version: [3.5, 3.6, 3.7, 3.8] steps: - name: Checkout uses: actions/checkout@v2 diff --git a/HISTORY.rst b/HISTORY.rst index 9e9cb843d..f970c2ee0 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -1,6 +1,19 @@ History ======= +1.4.0 (2020-09-26) +------------------ + +* Dropping support for Python 2.x +* --upsample a parameter for command line face_recognition + +1.3.0 (2020-02-20) +------------------ + +* Drop support for Python 3.4 and add 3.8 +* Blink detection example + + 1.2.3 (2018-08-21) ------------------ diff --git a/face_recognition/__init__.py b/face_recognition/__init__.py index 5c96187e0..6e91db046 100644 --- a/face_recognition/__init__.py +++ b/face_recognition/__init__.py @@ -2,6 +2,6 @@ __author__ = """Adam Geitgey""" __email__ = 'ageitgey@gmail.com' -__version__ = '1.2.3' +__version__ = '1.4.0' from .api import load_image_file, face_locations, batch_face_locations, face_landmarks, face_encodings, compare_faces, face_distance diff --git a/setup.cfg b/setup.cfg index 569ed72b9..623cf4d46 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 1.3.0 +current_version = 1.4.0 commit = True tag = True diff --git a/setup.py b/setup.py index 3a1e8e115..aa1233a0a 100644 --- a/setup.py +++ b/setup.py @@ -24,7 +24,7 @@ setup( name='face_recognition', - version='1.3.0', + version='1.4.0', description="Recognize faces from Python or from the command line", long_description=readme + '\n\n' + history, author="Adam Geitgey", @@ -52,8 +52,6 @@ 'Intended Audience :: Developers', 'License :: OSI Approved :: MIT License', 'Natural Language :: English', - "Programming Language :: Python :: 2", - 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3', 'Programming Language :: Python :: 3.5', 'Programming Language :: Python :: 3.6', diff --git a/tox.ini b/tox.ini index 02284ff71..014075705 100644 --- a/tox.ini +++ b/tox.ini @@ -10,7 +10,6 @@ envlist = [gh-actions] python = - 2.7: py27, flake8 3.5: py35, flake8 3.6: py36, flake8 3.7: py37, flake8 @@ -19,7 +18,7 @@ python = [testenv] commands = - python setup.py test + python -m unittest discover [testenv:flake8] From 613fd783514a5f4b45904a13dd6a7313e9d56818 Mon Sep 17 00:00:00 2001 From: Dylann Orozco <40942105+dorozcom@users.noreply.github.com> Date: Sun, 4 Oct 2020 12:54:31 -0600 Subject: [PATCH 38/53] Update Dockerfile Add pip3 install opencv-python==4.1.2.30 if you want to run the live webcam examples --- Dockerfile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Dockerfile b/Dockerfile index d8171fc6a..3be875e83 100644 --- a/Dockerfile +++ b/Dockerfile @@ -46,5 +46,7 @@ RUN cd /root/face_recognition && \ pip3 install -r requirements.txt && \ python3 setup.py install +# Add pip3 install opencv-python==4.1.2.30 if you want to run the live webcam examples + CMD cd /root/face_recognition/examples && \ python3 recognize_faces_in_pictures.py From d50353fdcb2f0b7180281ede9121810323ca9e37 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 27 Oct 2020 21:07:20 +0000 Subject: [PATCH 39/53] Bump cryptography from 1.7 to 3.2 Bumps [cryptography](https://github.com/pyca/cryptography) from 1.7 to 3.2. - [Release notes](https://github.com/pyca/cryptography/releases) - [Changelog](https://github.com/pyca/cryptography/blob/master/CHANGELOG.rst) - [Commits](https://github.com/pyca/cryptography/compare/1.7...3.2) Signed-off-by: dependabot[bot] --- requirements_dev.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements_dev.txt b/requirements_dev.txt index ff7da8df9..f39b3d2a2 100644 --- a/requirements_dev.txt +++ b/requirements_dev.txt @@ -6,7 +6,7 @@ flake8 tox==2.3.1 coverage==4.1 Sphinx==1.4.8 -cryptography==1.7 +cryptography==3.2 pyyaml>=4.2b1 face_recognition_models Click>=6.0 From ded327cd9e96258ec46c8a96d6c562b4f03fa8c7 Mon Sep 17 00:00:00 2001 From: Kshitiz Arya Date: Sun, 7 Feb 2021 19:57:21 +0530 Subject: [PATCH 40/53] There is a typo in face_recognition/example/facerec_ipcamera_knn.py The third last line is written as cap1.release(). It should be cap.release instead. cap1.release() > cap.release() --- examples/facerec_ipcamera_knn.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/facerec_ipcamera_knn.py b/examples/facerec_ipcamera_knn.py index ae9223416..55623ed8f 100644 --- a/examples/facerec_ipcamera_knn.py +++ b/examples/facerec_ipcamera_knn.py @@ -209,6 +209,6 @@ def show_prediction_labels_on_image(frame, predictions): frame = show_prediction_labels_on_image(frame, predictions) cv2.imshow('camera', frame) if ord('q') == cv2.waitKey(10): - cap1.release() + cap.release() cv2.destroyAllWindows() exit(0) From 0f3af010b7a6b233da3f38208a8358ed4d80cf9a Mon Sep 17 00:00:00 2001 From: Corban Villa Date: Sat, 13 Feb 2021 14:50:33 -0700 Subject: [PATCH 41/53] docker refactor --- README.md | 2 + docker/Dockerfile-python-example | 17 +++++ docker/README.md | 56 +++++++++++++++ docker/cpu-jupyter-kubeflow/Dockerfile | 15 ++++ docker/cpu/Dockerfile | 74 ++++++++++++++++++++ docker/gpu-jupyter-kubeflow/Dockerfile | 15 ++++ docker/gpu/Dockerfile | 97 ++++++++++++++++++++++++++ 7 files changed, 276 insertions(+) create mode 100644 docker/Dockerfile-python-example create mode 100644 docker/README.md create mode 100644 docker/cpu-jupyter-kubeflow/Dockerfile create mode 100644 docker/cpu/Dockerfile create mode 100644 docker/gpu-jupyter-kubeflow/Dockerfile create mode 100644 docker/gpu/Dockerfile diff --git a/README.md b/README.md index df0e0f17d..23ac8647d 100644 --- a/README.md +++ b/README.md @@ -394,6 +394,8 @@ to any service that supports Docker images. You can try the Docker image locally by running: `docker-compose up --build` +There are also [several prebuilt Docker images.](docker/README.md) + Linux users with a GPU (drivers >= 384.81) and [Nvidia-Docker](https://github.com/NVIDIA/nvidia-docker) installed can run the example on the GPU: Open the [docker-compose.yml](docker-compose.yml) file and uncomment the `dockerfile: Dockerfile.gpu` and `runtime: nvidia` lines. ## Having problems? diff --git a/docker/Dockerfile-python-example b/docker/Dockerfile-python-example new file mode 100644 index 000000000..159fab37f --- /dev/null +++ b/docker/Dockerfile-python-example @@ -0,0 +1,17 @@ +FROM animcogn/face_recognition:cpu + +# The rest of this file just runs an example script. + +# If you wanted to use this Dockerfile to run your own app instead, maybe you would do this: +# COPY . /root/your_app_or_whatever +# RUN cd /root/your_app_or_whatever && \ +# pip3 install -r requirements.txt +# RUN whatever_command_you_run_to_start_your_app + +COPY . /root/face_recognition +RUN cd /root/face_recognition && \ + pip3 install -r requirements.txt && \ + python3 setup.py install + +CMD cd /root/face_recognition/examples && \ + python3 recognize_faces_in_pictures.py diff --git a/docker/README.md b/docker/README.md new file mode 100644 index 000000000..6feffe1e4 --- /dev/null +++ b/docker/README.md @@ -0,0 +1,56 @@ +# Docker Builds + +If you've never used Docker before, check out the [getting started guide.](https://docs.docker.com/get-started/) + +Up-to-date prebuilt images can be found [on Docker hub.](https://hub.docker.com/repository/docker/animcogn/face_recognition) + +## CPU Images + +- [`cpu-latest`, `cpu`, `cpu-0.1`, `latest`](cpu/Dockerfile) +- [`cpu-jupyter-kubeflow-latest`, `cpu-jupyter-kubeflow`, `cpu-jupyter-kubeflow-0.1`](cpu-jupyter-kubeflow/Dockerfile) + +### GPU Images +- [`gpu-latest`, `gpu`, `gpu-0.1`](gpu/Dockerfile) +- [`gpu-jupyter-kubeflow-latest`, `gpu-jupyter-kubeflow`, `gpu-jupyter-kubeflow-0.1`](gpu-jupyter-kubeflow/Dockerfile) + +The CPU images should run out of the box without any driver prerequisites. + +## GPU Images + +### Prerequisites + +To use the GPU images, you need to have: +- [The Nvidia drivers](https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/install-guide.html#nvidia-drivers) +- [The Nvidia-docker container runtime](https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/install-guide.html#setting-up-nvidia-container-toolkit) +- [Docker configured to use the Nvidia container runtime](https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/user-guide.html#daemon-configuration-file) + +Once you have those installed, you should be ready to start running the GPU instances. + +### Testing GPUs + +To make sure your GPU instance is setup correctly, run the following in a container: + +```python3 +import dlib +print(dlib.cuda.get_num_devices()) +``` + +## Jupyter Images + +The Jupyter images are built to be deployed on [Kubeflow](https://www.kubeflow.org/). However, if you just want to run a normal Jupyter instance, they're a great template to build your own. + +## Example Dockerfile + +Here's an example Dockerfile using the prebuilt images: + +```Dockerfile +FROM animcogn/face_recognition:gpu + +COPY requirements.txt requirements.txt + +RUN pip3 install -r ./requirements.txt + +COPY my_app /my_app + +CMD [ "python3", "/my_app/my_app.py" ] +``` diff --git a/docker/cpu-jupyter-kubeflow/Dockerfile b/docker/cpu-jupyter-kubeflow/Dockerfile new file mode 100644 index 000000000..9979c548a --- /dev/null +++ b/docker/cpu-jupyter-kubeflow/Dockerfile @@ -0,0 +1,15 @@ +FROM animcogn/face_recognition:cpu + +RUN useradd -ms /bin/bash jovyan && \ + chown -R jovyan:jovyan /opt/venv && \ + echo 'PATH="/opt/venv/bin:$PATH"' >> /home/jovyan/.bashrc + +USER jovyan + +ENV PATH="/opt/venv/bin:$PATH" + +RUN pip3 install jupyterlab + +ENV NB_PREFIX / + +CMD ["sh", "-c", "jupyter lab --notebook-dir=/home/jovyan --ip=0.0.0.0 --no-browser --allow-root --port=8888 --NotebookApp.token='' --NotebookApp.password='' --NotebookApp.allow_origin='*' --NotebookApp.base_url=${NB_PREFIX}"] diff --git a/docker/cpu/Dockerfile b/docker/cpu/Dockerfile new file mode 100644 index 000000000..08a40e25c --- /dev/null +++ b/docker/cpu/Dockerfile @@ -0,0 +1,74 @@ +# Builder Image +FROM python:3.8-slim-buster AS compile + +# Install Dependencies +RUN apt-get -y update && apt-get install -y --fix-missing \ + build-essential \ + cmake \ + gfortran \ + git \ + wget \ + curl \ + graphicsmagick \ + libgraphicsmagick1-dev \ + libatlas-base-dev \ + libavcodec-dev \ + libavformat-dev \ + libgtk2.0-dev \ + libjpeg-dev \ + liblapack-dev \ + libswscale-dev \ + pkg-config \ + python3-dev \ + python3-numpy \ + software-properties-common \ + zip \ + && apt-get clean && rm -rf /tmp/* /var/tmp/* + +# Virtual Environment +ENV VIRTUAL_ENV=/opt/venv +RUN python3 -m venv $VIRTUAL_ENV +ENV PATH="$VIRTUAL_ENV/bin:$PATH" + +# Install Dlib +ENV CFLAGS=-static +RUN pip3 install --upgrade pip && \ + git clone -b 'v19.21' --single-branch https://github.com/davisking/dlib.git && \ + cd dlib/ && \ + python3 setup.py install --set BUILD_SHARED_LIBS=OFF + +RUN pip3 install face_recognition + + +# Runtime Image +FROM python:3.8-slim-buster + +COPY --from=compile /opt/venv /opt/venv +COPY --from=compile \ + # Sources + /lib/x86_64-linux-gnu/libpthread.so.0 \ + /lib/x86_64-linux-gnu/libz.so.1 \ + /lib/x86_64-linux-gnu/libm.so.6 \ + /lib/x86_64-linux-gnu/libgcc_s.so.1 \ + /lib/x86_64-linux-gnu/libc.so.6 \ + /lib/x86_64-linux-gnu/libdl.so.2 \ + /lib/x86_64-linux-gnu/librt.so.1 \ + # Destination + /lib/x86_64-linux-gnu/ + +COPY --from=compile \ + # Sources + /usr/lib/x86_64-linux-gnu/libX11.so.6 \ + /usr/lib/x86_64-linux-gnu/libXext.so.6 \ + /usr/lib/x86_64-linux-gnu/libpng16.so.16 \ + /usr/lib/x86_64-linux-gnu/libjpeg.so.62 \ + /usr/lib/x86_64-linux-gnu/libstdc++.so.6 \ + /usr/lib/x86_64-linux-gnu/libxcb.so.1 \ + /usr/lib/x86_64-linux-gnu/libXau.so.6 \ + /usr/lib/x86_64-linux-gnu/libXdmcp.so.6 \ + /usr/lib/x86_64-linux-gnu/libbsd.so.0 \ + # Destination + /usr/lib/x86_64-linux-gnu/ + +# Add our packages +ENV PATH="/opt/venv/bin:$PATH" diff --git a/docker/gpu-jupyter-kubeflow/Dockerfile b/docker/gpu-jupyter-kubeflow/Dockerfile new file mode 100644 index 000000000..df0aa8ac8 --- /dev/null +++ b/docker/gpu-jupyter-kubeflow/Dockerfile @@ -0,0 +1,15 @@ +FROM animcogn/face_recognition:gpu + +RUN useradd -ms /bin/bash jovyan && \ + chown -R jovyan:jovyan /opt/venv && \ + echo 'PATH="/opt/venv/bin:$PATH"' >> /home/jovyan/.bashrc + +USER jovyan + +ENV PATH="/opt/venv/bin:$PATH" + +RUN pip3 install jupyterlab + +ENV NB_PREFIX / + +CMD ["sh", "-c", "jupyter lab --notebook-dir=/home/jovyan --ip=0.0.0.0 --no-browser --allow-root --port=8888 --NotebookApp.token='' --NotebookApp.password='' --NotebookApp.allow_origin='*' --NotebookApp.base_url=${NB_PREFIX}"] diff --git a/docker/gpu/Dockerfile b/docker/gpu/Dockerfile new file mode 100644 index 000000000..8ece32dec --- /dev/null +++ b/docker/gpu/Dockerfile @@ -0,0 +1,97 @@ +FROM nvidia/cuda:11.2.0-cudnn8-devel AS compile + +# Install dependencies +ENV DEBIAN_FRONTEND=noninteractive +RUN apt-get update -y && apt-get install -y \ + git \ + cmake \ + libsm6 \ + libxext6 \ + libxrender-dev \ + python3 \ + python3-pip \ + python3-venv \ + python3-dev \ + python3-numpy \ + gcc \ + build-essential \ + gfortran \ + wget \ + curl \ + graphicsmagick \ + libgraphicsmagick1-dev \ + libatlas-base-dev \ + libavcodec-dev \ + libavformat-dev \ + libgtk2.0-dev \ + libjpeg-dev \ + liblapack-dev \ + libswscale-dev \ + pkg-config \ + software-properties-common \ + zip \ + && apt-get clean && rm -rf /tmp/* /var/tmp/* + + +# Virtual Environment +ENV VIRTUAL_ENV=/opt/venv +RUN python3 -m venv $VIRTUAL_ENV +ENV PATH="$VIRTUAL_ENV/bin:$PATH" + +# Scikit learn +RUN pip3 install --upgrade pip && \ + pip3 install scikit-build + +# Install dlib +ENV CFLAGS=-static +RUN git clone -b 'v19.21' --single-branch https://github.com/davisking/dlib.git dlib/ && \ + mkdir -p /dlib/build && \ + cmake -H/dlib -B/dlib/build -DDLIB_USE_CUDA=1 -DUSE_AVX_INSTRUCTIONS=1 && \ + cmake --build /dlib/build && \ + cd /dlib && \ + python3 /dlib/setup.py install --set BUILD_SHARED_LIBS=OFF + +# Install face recognition +RUN pip3 install face_recognition + +# Runtime Image +FROM nvidia/cuda:11.2.0-cudnn8-runtime + +# Install requirements +RUN apt-get update && apt-get install -y \ + python3 \ + python3-distutils + +# Copy in libs +COPY --from=compile /opt/venv /opt/venv +COPY --from=compile \ + # Sources + /lib/x86_64-linux-gnu/libpthread.so.0 \ + /lib/x86_64-linux-gnu/libdl.so.2 \ + /lib/x86_64-linux-gnu/librt.so.1 \ + /lib/x86_64-linux-gnu/libX11.so.6 \ + /lib/x86_64-linux-gnu/libpng16.so.16 \ + /lib/x86_64-linux-gnu/libjpeg.so.8 \ + /lib/x86_64-linux-gnu/libcudnn.so.8 \ + /lib/x86_64-linux-gnu/libstdc++.so.6 \ + /lib/x86_64-linux-gnu/libm.so.6 \ + /lib/x86_64-linux-gnu/libgcc_s.so.1 \ + /lib/x86_64-linux-gnu/libc.so.6 \ + /lib/x86_64-linux-gnu/libxcb.so.1 \ + /lib/x86_64-linux-gnu/libz.so.1 \ + /lib/x86_64-linux-gnu/libXau.so.6 \ + /lib/x86_64-linux-gnu/libXdmcp.so.6 \ + /lib/x86_64-linux-gnu/libbsd.so.0 \ + # Destination + /lib/x86_64-linux-gnu/ +COPY --from=compile \ + # Sources + /usr/local/cuda/lib64/libcublas.so.11 \ + /usr/local/cuda/lib64/libcurand.so.10 \ + /usr/local/cuda/lib64/libcusolver.so.11 \ + /usr/local/cuda/lib64/libcublasLt.so.11 \ + # Destination + /usr/local/cuda/lib64/ + +# Add our packages +ENV PATH="/opt/venv/bin:$PATH" From a1239034d9968820645c49d9707626dd6c908cb1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 9 Jun 2021 17:39:13 +0000 Subject: [PATCH 42/53] Bump pip from 8.1.2 to 19.2 Bumps [pip](https://github.com/pypa/pip) from 8.1.2 to 19.2. - [Release notes](https://github.com/pypa/pip/releases) - [Changelog](https://github.com/pypa/pip/blob/main/NEWS.rst) - [Commits](https://github.com/pypa/pip/compare/8.1.2...19.2) --- updated-dependencies: - dependency-name: pip dependency-type: direct:development ... Signed-off-by: dependabot[bot] --- requirements_dev.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements_dev.txt b/requirements_dev.txt index ff7da8df9..890742f30 100644 --- a/requirements_dev.txt +++ b/requirements_dev.txt @@ -1,4 +1,4 @@ -pip==8.1.2 +pip==19.2 bumpversion==0.5.3 wheel==0.29.0 watchdog==0.8.3 From b829c293f16684a3af42331e890c55109d4c4202 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 14 Jun 2021 10:08:21 +0000 Subject: [PATCH 43/53] Bump cryptography from 3.2 to 3.3.2 Bumps [cryptography](https://github.com/pyca/cryptography) from 3.2 to 3.3.2. - [Release notes](https://github.com/pyca/cryptography/releases) - [Changelog](https://github.com/pyca/cryptography/blob/main/CHANGELOG.rst) - [Commits](https://github.com/pyca/cryptography/compare/3.2...3.3.2) --- updated-dependencies: - dependency-name: cryptography dependency-type: direct:development ... Signed-off-by: dependabot[bot] --- requirements_dev.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements_dev.txt b/requirements_dev.txt index 929eda1d1..16ff43196 100644 --- a/requirements_dev.txt +++ b/requirements_dev.txt @@ -6,7 +6,7 @@ flake8 tox==2.3.1 coverage==4.1 Sphinx==1.4.8 -cryptography==3.2 +cryptography==3.3.2 pyyaml>=4.2b1 face_recognition_models Click>=6.0 From 0ee5edd8ba77fa16320f4f3b941570bd47bc87df Mon Sep 17 00:00:00 2001 From: Daniil Okhlopkov <5613295+ohld@users.noreply.github.com> Date: Mon, 16 Aug 2021 18:57:55 +0300 Subject: [PATCH 44/53] Update LICENSE --- LICENSE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LICENSE b/LICENSE index 696d0ce72..6e055ca1e 100644 --- a/LICENSE +++ b/LICENSE @@ -1,7 +1,7 @@ MIT License -Copyright (c) 2017, Adam Geitgey +Copyright (c) 2021, Adam Geitgey 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: From 70d8dc52c8574fb371bb0df2c05c60cf5e5f6211 Mon Sep 17 00:00:00 2001 From: Anurag Kumar Date: Wed, 8 Sep 2021 21:08:38 +0530 Subject: [PATCH 45/53] Update setup.py updated classifiers --- setup.py | 1 + 1 file changed, 1 insertion(+) diff --git a/setup.py b/setup.py index aa1233a0a..63b2bb35a 100644 --- a/setup.py +++ b/setup.py @@ -57,6 +57,7 @@ 'Programming Language :: Python :: 3.6', 'Programming Language :: Python :: 3.7', 'Programming Language :: Python :: 3.8', + 'Programming Language :: Python :: 3.9', ], test_suite='tests', tests_require=test_requirements From d28e460219740e04fd72b8d163a878e520c13e32 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 15 Nov 2021 17:47:04 +0000 Subject: [PATCH 46/53] Bump pip from 19.2 to 21.1 Bumps [pip](https://github.com/pypa/pip) from 19.2 to 21.1. - [Release notes](https://github.com/pypa/pip/releases) - [Changelog](https://github.com/pypa/pip/blob/main/NEWS.rst) - [Commits](https://github.com/pypa/pip/compare/19.2...21.1) --- updated-dependencies: - dependency-name: pip dependency-type: direct:development ... Signed-off-by: dependabot[bot] --- requirements_dev.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements_dev.txt b/requirements_dev.txt index 16ff43196..638e2b36d 100644 --- a/requirements_dev.txt +++ b/requirements_dev.txt @@ -1,4 +1,4 @@ -pip==19.2 +pip==21.1 bumpversion==0.5.3 wheel==0.29.0 watchdog==0.8.3 From 0861ddad106e8fe3cc872114b6e12aab0fff0978 Mon Sep 17 00:00:00 2001 From: Dustin Wyatt Date: Fri, 26 Nov 2021 17:11:40 -0600 Subject: [PATCH 47/53] No need to resize if not processing frame --- examples/facerec_from_webcam_faster.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/examples/facerec_from_webcam_faster.py b/examples/facerec_from_webcam_faster.py index 7428da14c..e4a7bbd47 100644 --- a/examples/facerec_from_webcam_faster.py +++ b/examples/facerec_from_webcam_faster.py @@ -42,14 +42,14 @@ # 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: + # 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] + # 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) From 2dc095903d0b8c72f1eca291c7d96e4ee73f4b30 Mon Sep 17 00:00:00 2001 From: snyk-bot Date: Mon, 20 Dec 2021 14:42:18 +0000 Subject: [PATCH 48/53] fix: Dockerfile to reduce vulnerabilities The following vulnerabilities are fixed with an upgrade: - https://snyk.io/vuln/SNYK-DEBIAN9-GLIBC-356851 - https://snyk.io/vuln/SNYK-DEBIAN9-GLIBC-356851 - https://snyk.io/vuln/SNYK-DEBIAN9-GLIBC-356851 - https://snyk.io/vuln/SNYK-DEBIAN9-OPENSSL-1569399 - https://snyk.io/vuln/SNYK-DEBIAN9-TAR-312293 --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index d8171fc6a..ecd3ae8b0 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,6 +1,6 @@ # This is a sample Dockerfile you can modify to deploy your own app based on face_recognition -FROM python:3.6-slim-stretch +FROM python:3.9.7-slim-bullseye RUN apt-get -y update RUN apt-get install -y --fix-missing \ From 2b560b8b143353c323f870ed03a830fe03cfde41 Mon Sep 17 00:00:00 2001 From: snyk-bot Date: Sun, 27 Mar 2022 02:09:23 +0000 Subject: [PATCH 49/53] fix: Dockerfile to reduce vulnerabilities The following vulnerabilities are fixed with an upgrade: - https://snyk.io/vuln/SNYK-DEBIAN11-EXPAT-2403512 - https://snyk.io/vuln/SNYK-DEBIAN11-EXPAT-2406127 - https://snyk.io/vuln/SNYK-DEBIAN11-OPENSSL-2388380 - https://snyk.io/vuln/SNYK-DEBIAN11-OPENSSL-2426309 - https://snyk.io/vuln/SNYK-DEBIAN11-OPENSSL-2426309 --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index ecd3ae8b0..fa9209129 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,6 +1,6 @@ # This is a sample Dockerfile you can modify to deploy your own app based on face_recognition -FROM python:3.9.7-slim-bullseye +FROM python:3.10.3-slim-bullseye RUN apt-get -y update RUN apt-get install -y --fix-missing \ From 588e619c8f8a376f061e84527a1fc8c87ac4397c Mon Sep 17 00:00:00 2001 From: Adam Geitgey Date: Thu, 9 Jun 2022 18:09:15 +0100 Subject: [PATCH 50/53] Bump python version in CI --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index d299fc19b..aaf0e30a7 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -5,7 +5,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - python-version: [3.5, 3.6, 3.7, 3.8] + python-version: [3.8, 3.9, 3.10] steps: - name: Checkout uses: actions/checkout@v2 From 964e5b531752efece61bfe0201ff1fc934f62dad Mon Sep 17 00:00:00 2001 From: Adam Geitgey Date: Thu, 9 Jun 2022 18:10:03 +0100 Subject: [PATCH 51/53] Update main.yml --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index aaf0e30a7..273a41471 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -5,7 +5,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - python-version: [3.8, 3.9, 3.10] + python-version: [3.8, 3.9, "3.10"] steps: - name: Checkout uses: actions/checkout@v2 From 2c5247763b520f87bb165d652c54b47170022db8 Mon Sep 17 00:00:00 2001 From: 17x <220817687+17X61@users.noreply.github.com> Date: Tue, 5 May 2026 22:24:58 +0800 Subject: [PATCH 52/53] Fix dead LFW benchmark link --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 23ac8647d..01b6a07bd 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ the world's simplest face recognition library. Built using [dlib](http://dlib.net/)'s state-of-the-art face recognition built with deep learning. The model has an accuracy of 99.38% on the -[Labeled Faces in the Wild](http://vis-www.cs.umass.edu/lfw/) benchmark. +[Labeled Faces in the Wild](https://people.cs.umass.edu/~elm/papers/lfw.pdf) benchmark. This also provides a simple `face_recognition` command line tool that lets you do face recognition on a folder of images from the command line! From b483acefc150ee98248aeddea5469ff8c762560e Mon Sep 17 00:00:00 2001 From: Adam Geitgey Date: Thu, 25 Jun 2026 12:12:41 +0100 Subject: [PATCH 53/53] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 01b6a07bd..2b198de18 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ the world's simplest face recognition library. Built using [dlib](http://dlib.net/)'s state-of-the-art face recognition built with deep learning. The model has an accuracy of 99.38% on the -[Labeled Faces in the Wild](https://people.cs.umass.edu/~elm/papers/lfw.pdf) benchmark. +Labeled Faces in the Wild benchmark (see the [LFW paper (PDF)](https://people.cs.umass.edu/~elm/papers/lfw.pdf)). This also provides a simple `face_recognition` command line tool that lets you do face recognition on a folder of images from the command line!