Spaces:
Running
Running
File size: 5,812 Bytes
ca46a75 402b504 ca46a75 23cd1cf 402b504 23cd1cf ca46a75 23cd1cf ca46a75 402b504 ca46a75 23cd1cf ca46a75 23cd1cf ca46a75 23cd1cf ca46a75 23cd1cf ca46a75 23cd1cf 06fbec3 23cd1cf 402b504 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 |
#!/usr/bin/env python
# -*- coding: utf-8 -*-
r"""
@DATE: 2024/9/5 19:32
@File: face_detector.py
@IDE: pycharm
@Description:
人脸检测器
"""
try:
from mtcnnruntime import MTCNN
except ImportError:
raise ImportError(
"Please install mtcnn-runtime by running `pip install mtcnn-runtime`"
)
from .context import Context
from hivision.error import FaceError, APIError
from hivision.utils import resize_image_to_kb_base64
from hivision.creator.retinaface import retinaface_detect_faces
import requests
import cv2
import os
mtcnn = None
base_dir = os.path.dirname(os.path.abspath(__file__))
RETINAFCE_SESS = None
def detect_face_mtcnn(ctx: Context, scale: int = 2):
"""
基于MTCNN模型的人脸检测处理器,只进行人脸数量的检测
:param ctx: 上下文,此时已获取到原始图和抠图结果,但是我们只需要原始图
:param scale: 最大边长缩放比例,原图:缩放图 = 1:scale
:raise FaceError: 人脸检测错误,多个人脸或者没有人脸
"""
global mtcnn
if mtcnn is None:
mtcnn = MTCNN()
image = cv2.resize(
ctx.origin_image,
(ctx.origin_image.shape[1] // scale, ctx.origin_image.shape[0] // scale),
interpolation=cv2.INTER_AREA,
)
faces, _ = mtcnn.detect(image, thresholds=[0.8, 0.8, 0.8])
# print(len(faces))
if len(faces) != 1:
# 保险措施,如果检测到多个人脸或者没有人脸,用原图再检测一次
faces, _ = mtcnn.detect(ctx.origin_image)
else:
# 如果只有一个人脸,将人脸坐标放大
for item, param in enumerate(faces[0]):
faces[0][item] = param * 2
if len(faces) != 1:
raise FaceError("Expected 1 face, but got {}".format(len(faces)), len(faces))
left = faces[0][0]
top = faces[0][1]
width = faces[0][2] - left + 1
height = faces[0][3] - top + 1
ctx.face = (left, top, width, height)
def detect_face_face_plusplus(ctx: Context):
"""
基于Face++ API接口的人脸检测处理器,只进行人脸数量的检测
:param ctx: 上下文,此时已获取到原始图和抠图结果,但是我们只需要原始图
:param scale: 最大边长缩放比例,原图:缩放图 = 1:scale
:raise FaceError: 人脸检测错误,多个人脸或者没有人脸
"""
url = "https://api-cn.faceplusplus.com/facepp/v3/detect"
api_key = os.getenv("FACE_PLUS_API_KEY")
api_secret = os.getenv("FACE_PLUS_API_SECRET")
print("调用了face++")
image = ctx.origin_image
# 将图片转为 base64, 且不大于2MB(Face++ API接口限制)
image_base64 = resize_image_to_kb_base64(image, 2000, mode="max")
files = {
"api_key": (None, api_key),
"api_secret": (None, api_secret),
"image_base64": (None, image_base64),
}
# 发送 POST 请求
response = requests.post(url, files=files)
# 获取响应状态码
status_code = response.status_code
response_json = response.json()
if status_code == 200:
face_num = response_json["face_num"]
if face_num == 1:
face_rectangle = response_json["faces"][0]["face_rectangle"]
ctx.face = (
face_rectangle["left"],
face_rectangle["top"],
face_rectangle["width"],
face_rectangle["height"],
)
else:
raise FaceError(
"Expected 1 face, but got {}".format(face_num), len(face_num)
)
elif status_code == 401:
raise APIError(
f"Face++ Status code {status_code} Authentication error: API key and secret do not match.",
status_code,
)
elif status_code == 403:
reason = response_json.get("error_message", "Unknown authorization error.")
raise APIError(
f"Authorization error: {reason}",
status_code,
)
elif status_code == 400:
error_message = response_json.get("error_message", "Bad request.")
raise APIError(
f"Bad request error: {error_message}",
status_code,
)
elif status_code == 413:
raise APIError(
f"Face++ Status code {status_code} Request entity too large: The image exceeds the 2MB limit.",
status_code,
)
def detect_face_retinaface(ctx: Context):
"""
基于RetinaFace模型的人脸检测处理器,只进行人脸数量的检测
:param ctx: 上下文,此时已获取到原始图和抠图结果,但是我们只需要原始图
:raise FaceError: 人脸检测错误,多个人脸或者没有人脸
"""
from time import time
global RETINAFCE_SESS
if RETINAFCE_SESS is None:
print("首次加载RetinaFace模型...")
# 计算用时
tic = time()
faces_dets, sess = retinaface_detect_faces(
ctx.origin_image,
os.path.join(base_dir, "retinaface/weights/retinaface-resnet50.onnx"),
sess=None,
)
RETINAFCE_SESS = sess
print("首次RetinaFace模型推理用时: {:.4f}s".format(time() - tic))
else:
tic = time()
faces_dets, _ = retinaface_detect_faces(
ctx.origin_image,
os.path.join(base_dir, "retinaface/weights/retinaface-resnet50.onnx"),
sess=RETINAFCE_SESS,
)
print("二次RetinaFace模型推理用时: {:.4f}s".format(time() - tic))
faces_num = len(faces_dets)
if faces_num != 1:
raise FaceError("Expected 1 face, but got {}".format(faces_num), faces_num)
face_det = faces_dets[0]
ctx.face = (
face_det[0],
face_det[1],
face_det[2] - face_det[0] + 1,
face_det[3] - face_det[1] + 1,
)
|