Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
zpc421126
face_recognition
提交
efbb40f2
F
face_recognition
项目概览
zpc421126
/
face_recognition
与 Fork 源项目一致
从无法访问的项目Fork
通知
2
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
F
face_recognition
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
前往新版Gitcode,体验更适合开发者的 AI 搜索 >>
提交
efbb40f2
编写于
1月 19, 2020
作者:
A
Abdolkarim Saeedi
提交者:
Adam Geitgey
2月 20, 2020
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Add files via upload
Real time fast face recognition on ip cameras using knn.
上级
2d3c0ea1
变更
1
隐藏空白更改
内联
并排
Showing
1 changed file
with
214 addition
and
0 deletion
+214
-0
examples/facerec_ipcamera_knn.py
examples/facerec_ipcamera_knn.py
+214
-0
未找到文件。
examples/facerec_ipcamera_knn.py
0 → 100644
浏览文件 @
efbb40f2
"""
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:
<train_dir>/
├── <person1>/
│ ├── <somename1>.jpeg
│ ├── <somename2>.jpeg
│ ├── ...
├── <person2>/
│ ├── <somename1>.jpeg
│ └── <somename2>.jpeg
└── ...
:param model_save_path: (optional) path to save model on disk
:param n_neighbors: (optional) number of neighbors to weigh in classification. Chosen automatically if not specified
:param knn_algo: (optional) underlying data structure to support knn.default is ball_tree
:param verbose: verbosity of training
:return: returns knn classifier that was trained on the given data.
"""
X
=
[]
y
=
[]
# Loop through each person in the training set
for
class_dir
in
os
.
listdir
(
train_dir
):
if
not
os
.
path
.
isdir
(
os
.
path
.
join
(
train_dir
,
class_dir
)):
continue
# Loop through each training image for the current person
for
img_path
in
image_files_in_folder
(
os
.
path
.
join
(
train_dir
,
class_dir
)):
image
=
face_recognition
.
load_image_file
(
img_path
)
face_bounding_boxes
=
face_recognition
.
face_locations
(
image
)
if
len
(
face_bounding_boxes
)
!=
1
:
# If there are no people (or too many people) in a training image, skip the image.
if
verbose
:
print
(
"Image {} not suitable for training: {}"
.
format
(
img_path
,
"Didn't find a face"
if
len
(
face_bounding_boxes
)
<
1
else
"Found more than one face"
))
else
:
# Add face encoding for current image to the training set
X
.
append
(
face_recognition
.
face_encodings
(
image
,
known_face_locations
=
face_bounding_boxes
)[
0
])
y
.
append
(
class_dir
)
# Determine how many neighbors to use for weighting in the KNN classifier
if
n_neighbors
is
None
:
n_neighbors
=
int
(
round
(
math
.
sqrt
(
len
(
X
))))
if
verbose
:
print
(
"Chose n_neighbors automatically:"
,
n_neighbors
)
# Create and train the KNN classifier
knn_clf
=
neighbors
.
KNeighborsClassifier
(
n_neighbors
=
n_neighbors
,
algorithm
=
knn_algo
,
weights
=
'distance'
)
knn_clf
.
fit
(
X
,
y
)
# Save the trained KNN classifier
if
model_save_path
is
not
None
:
with
open
(
model_save_path
,
'wb'
)
as
f
:
pickle
.
dump
(
knn_clf
,
f
)
return
knn_clf
def
predict
(
X_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
)
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录