Skip to content

Commit

Permalink
face recognizer support yolov8-face detector
Browse files Browse the repository at this point in the history
  • Loading branch information
Neutree committed Oct 25, 2024
1 parent f233947 commit d12df85
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 10 deletions.
15 changes: 11 additions & 4 deletions docs/doc/en/vision/face_recognition.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,17 @@ from maix import nn, camera, display, image
import os
import math

recognizer = nn.FaceRecognizer(detect_model="/root/models/retinaface.mud", feature_model = "/root/models/face_feature.mud", dual_buff = True)
recognizer = nn.FaceRecognizer(detect_model="/root/models/yolov8n_face.mud", feature_model = "/root/models/insghtface_webface_r50.mud", dual_buff=True)
# recognizer = nn.FaceRecognizer(detect_model="/root/models/retinaface.mud", feature_model = "/root/models/face_feature.mud", dual_buff=True)

if os.path.exists("/root/faces.bin"):
recognizer.load_faces("/root/faces.bin")
cam = camera.Camera(recognizer.input_width(), recognizer.input_height(), recognizer.input_format())
dis = display.Display()

while 1:
img = cam.read()
faces = recognizer.recognize(img, 0.5, 0.45, 0.8)
faces = recognizer.recognize(img, 0.5, 0.45, 0.85)
for obj in faces:
img.draw_rect(obj.x, obj.y, obj.w, obj.h, color = image.COLOR_RED)
radius = math.ceil(obj.w / 10)
Expand All @@ -51,7 +53,7 @@ When you first run this code, it can detect faces but will not recognize them. W
For example, you can learn faces when a user presses a button:
```python
faces = recognizer.recognize(img, 0.5, 0.45, True)
faces = recognizer.recognize(img, 0.5, 0.45, 0.85, True)
for face in faces:
print(face)
# This accounts for the scenario where multiple faces are present in one scene; obj.class_id of 0 means the face is not registered
Expand All @@ -61,6 +63,10 @@ for face in faces:
recognizer.save_faces("/root/faces.bin")
```

Here, `0.5` is the threshold for face detection, where a higher value indicates stricter detection. `0.45` is the `IOU` threshold, used to filter overlapping face results. `0.85` is the threshold for face comparison, indicating similarity with stored faces in the database. If a face comparison score exceeds this threshold, it is considered a match. A higher threshold improves filtering accuracy, while a lower threshold increases the risk of misidentification and can be adjusted according to practical needs.

The detection model here supports three types: `yolov8n_face`, `retinaface`, and `face_detector`, each differing slightly in speed and accuracy, allowing for selection based on specific requirements.

## Complete Example

A complete example is provided for recording unknown faces and recognizing faces with a button press. This can be found in the [MaixPy example directory](https://github.com/sipeed/MaixPy/tree/main/examples) under `nn_face_recognize.py`.
Expand All @@ -72,5 +78,6 @@ You may have noticed that the model initialization uses `dual_buff` (which defau

## Replacing Other Default Recognition Models

The current recognition model (used to distinguish different individuals) is based on the MobileNetV2 model. If its accuracy does not meet your requirements, you can replace it with another model, such as the [Insight Face ResNet50](https://maixhub.com/model/zoo/462) model. Of course, you can also train your own model or find other pre-trained models and convert them into a format supported by MaixCAM. For the conversion method, refer to the [MaixCAM Model Conversion Documentation](../ai_model_converter/maixcam.md), and you can write the mud file based on existing examples.
The recognition model (for distinguishing different individuals) uses `mobilenetv2` and the [insight face resnet50](https://maixhub.com/model/zoo/462) model. If these do not meet accuracy requirements, other models can be substituted. You may need to train a new model or find a pre-trained model compatible with MaixCAM, such as other models from [insightface](https://github.com/deepinsight/insightface). For conversion instructions, refer to the [MaixCAM model conversion documentation](../ai_model_converter/maixcam.md), and follow existing `.mud` files as examples.


15 changes: 11 additions & 4 deletions docs/doc/zh/vision/face_recognition.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,15 +29,17 @@ from maix import nn, camera, display, image
import os
import math

recognizer = nn.FaceRecognizer(detect_model="/root/models/retinaface.mud", feature_model = "/root/models/face_feature.mud", dual_buff=True)
recognizer = nn.FaceRecognizer(detect_model="/root/models/yolov8n_face.mud", feature_model = "/root/models/insghtface_webface_r50.mud", dual_buff=True)
# recognizer = nn.FaceRecognizer(detect_model="/root/models/retinaface.mud", feature_model = "/root/models/face_feature.mud", dual_buff=True)

if os.path.exists("/root/faces.bin"):
recognizer.load_faces("/root/faces.bin")
cam = camera.Camera(recognizer.input_width(), recognizer.input_height(), recognizer.input_format())
dis = display.Display()

while 1:
img = cam.read()
faces = recognizer.recognize(img, 0.5, 0.45, 0.8)
faces = recognizer.recognize(img, 0.5, 0.45, 0.85)
for obj in faces:
img.draw_rect(obj.x, obj.y, obj.w, obj.h, color = image.COLOR_RED)
radius = math.ceil(obj.w / 10)
Expand All @@ -53,7 +55,7 @@ while 1:
比如可以在用户按下按键的时候学习人脸:
```python
faces = recognizer.recognize(img, 0.5, 0.45, True)
faces = recognizer.recognize(img, 0.5, 0.45, 0.85, True)
for face in faces:
print(face)
# 这里考虑到了一个画面中有多个人脸的情况, obj.class_id 为 0 代表是没有录入的人脸
Expand All @@ -63,6 +65,11 @@ for face in faces:
recognizer.save_faces("/root/faces.bin")
```

这里 `0.5` 是检测人脸的阈值,越大越严格, `0.45``IOU`阈值,用来过滤多个重合的人脸结果;
`0.85`是人脸对比阈值, 即和库中存好的人脸对比相似度,某个人脸对比分数大于这个阈值就认为是这个人。值越大过滤效果越好,值越小越容易误识别,可以根据实际情况调整。

检测模型这里支持`yolov8n_face`/`retinaface`/`face_detector`三种,速度和精度略微区别,可以根据实际情况选择使用。

## 完整例程

这里提供一个按键录入未知人脸,以及人脸识别的例程,可以在[MaixPy 的 example 目录](https://github.com/sipeed/MaixPy/tree/main/examples) 找到`nn_face_recognize.py`
Expand All @@ -74,6 +81,6 @@ recognizer.save_faces("/root/faces.bin")

## 更换其它默认识别模型

这里识别模型(区分不同人)用了 mobilenetv2 模型,如果不满足精度要求,可以更换成其它模型,比如[insight face resnet50](https://maixhub.com/model/zoo/462) 模型,当然你也可以自己训练或者找其它训练好的模型转换成 MaixCAM 支持的模型即可,转换方法看[MaixCAM 模型转换文档](../ai_model_converter/maixcam.md), mud 文件参考以有的文件写即可。
这里识别模型(区分不同人)用了 `mobilenetv2`[insight face resnet50](https://maixhub.com/model/zoo/462) 模型,如果不满足精度要求,可以更换成其它模型,需要自己训练或者找其它训练好的模型转换成 MaixCAM 支持的模型即可,比如 [insightface](https://github.com/deepinsight/insightface)的其它模型, 转换方法看[MaixCAM 模型转换文档](../ai_model_converter/maixcam.md), mud 文件参考以有的文件写即可。


13 changes: 11 additions & 2 deletions projects/app_face_recognizer/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,16 @@

def main(disp):
global pressed_flag, learn_id
recognizer = nn.FaceRecognizer(detect_model="/root/models/retinaface.mud", feature_model = "/root/models/face_feature.mud", dual_buff = True)
img = image.Image(disp.width(), disp.height())
msg = "loading ..."
size = image.string_size(msg, scale=2, thickness=2)
img.draw_string((img.width() - size.width()) // 2, (img.height() - size.height()) // 2, msg, color=image.COLOR_WHITE, scale=2, thickness=2)
disp.show(img)

# yolov8-face + insightface resnet50, slower but more precisely
recognizer = nn.FaceRecognizer(detect_model="/root/models/yolov8n_face.mud", feature_model = "/root/models/insghtface_webface_r50.mud", dual_buff=True)
# Retinaface + mobilenetv2-face, faster but lower precese.
# recognizer = nn.FaceRecognizer(detect_model="/root/models/retinaface.mud", feature_model = "/root/models/face_feature.mud", dual_buff = True)

# if os.path.exists("/root/faces.bin"):
# recognizer.load_faces("/root/faces.bin")
Expand Down Expand Up @@ -74,7 +83,7 @@ def on_touch(x, y, pressed):
for i in range(len(recognizer.labels) - 1):
recognizer.remove_face(0)
img = cam.read()
faces = recognizer.recognize(img, 0.5, 0.45, 0.8, learn, learn)
faces = recognizer.recognize(img, 0.5, 0.45, 0.85, learn, learn)
for obj in faces:
color = image.COLOR_RED if obj.class_id == 0 else image.COLOR_GREEN
img.draw_rect(obj.x, obj.y, obj.w, obj.h, color = color)
Expand Down

0 comments on commit d12df85

Please sign in to comment.