Spaces:
Runtime error
Runtime error
File size: 5,765 Bytes
f2dbf59 |
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 |
import os
import onnx
import onnxruntime
import cv2
import numpy as np
from collections import namedtuple
Face = namedtuple('Face',
[
'bounding_box',
'landmarks',
'scores',
])
class YoloFaceOnnx:
def __init__(self, model_path, providers):
self.session = onnxruntime.InferenceSession(model_path, providers=providers)
inputs = self.session.get_inputs()
self.input_size = (inputs[0].shape[2], inputs[0].shape[3])
self.input_name = inputs[0].name
def pre_process(self, image):
img = cv2.resize(image, self.input_size)
img = (img - 127.5) / 128.0
img = np.expand_dims(img.transpose(2, 0, 1), axis = 0).astype(np.float32)
return img
def post_process(self, size, bounding_box_list, face_landmark_5_list, score_list):
sort_indices = np.argsort(-np.array(score_list))
bounding_box_list = [ bounding_box_list[index] for index in sort_indices ]
face_landmark_5_list = [face_landmark_5_list[index] for index in sort_indices]
score_list = [ score_list[index] for index in sort_indices ]
face_list = []
keep_indices = self.apply_nms(bounding_box_list, 0.4)
for index in keep_indices:
bounding_box = bounding_box_list[index]
face_landmark = face_landmark_5_list[index]
score = score_list[index],
#print(f'bounding_box >> : {bounding_box}')
face_list.append(Face(
bounding_box = self.expand_bounding_box(size, bounding_box),
landmarks = face_landmark,
scores = score,
))
return face_list
def apply_nms(self, bounding_box_list, iou_threshold):
keep_indices = []
dimension_list = np.reshape(bounding_box_list, (-1, 4))
x1 = dimension_list[:, 0]
y1 = dimension_list[:, 1]
x2 = dimension_list[:, 2]
y2 = dimension_list[:, 3]
areas = (x2 - x1 + 1) * (y2 - y1 + 1)
indices = np.arange(len(bounding_box_list))
while indices.size > 0:
index = indices[0]
remain_indices = indices[1:]
keep_indices.append(index)
xx1 = np.maximum(x1[index], x1[remain_indices])
yy1 = np.maximum(y1[index], y1[remain_indices])
xx2 = np.minimum(x2[index], x2[remain_indices])
yy2 = np.minimum(y2[index], y2[remain_indices])
width = np.maximum(0, xx2 - xx1 + 1)
height = np.maximum(0, yy2 - yy1 + 1)
iou = width * height / (areas[index] + areas[remain_indices] - width * height)
indices = indices[np.where(iou <= iou_threshold)[0] + 1]
return keep_indices
def expand_bounding_box(self, size, bbox, expansion=32):
"""
根据给定的 bbox,在四个边各扩展一定像素。
:param image: 输入的图像
:param bbox: 原始边界框,格式为 (x1, y1, x2, y2)
:param expansion: 每个边扩展的像素数
:return: 扩展后的图像
"""
x1, y1, x2, y2 = bbox
# 扩展边界框
x1_expanded = max(x1 - expansion, 0) # 保证不越界
y1_expanded = max(y1 - expansion, 0)
x2_expanded = min(x2 + expansion, size[1]) # 保证不越界
y2_expanded = min(y2 + expansion, size[0])
return [x1_expanded, y1_expanded, x2_expanded, y2_expanded]
def detect(self, image, conf):
img = self.pre_process(image)
ratio_height = image.shape[0] / img.shape[2]
ratio_width = image.shape[1] / img.shape[3]
outputs = self.session.run(None, {self.input_name: img})
outputs = np.squeeze(outputs).T
bounding_box_raw, score_raw, face_landmark_5_raw = np.split(outputs, [ 4, 5 ], axis = 1)
bounding_box_list = []
face_landmark_5_list = []
score_list = []
keep_indices = np.where(score_raw > conf)[0]
if keep_indices.any():
bounding_box_raw, face_landmark_5_raw, score_raw = bounding_box_raw[keep_indices], face_landmark_5_raw[keep_indices], score_raw[keep_indices]
for bounding_box in bounding_box_raw:
bounding_box_list.append(np.array(
[
(bounding_box[0] - bounding_box[2] / 2) * ratio_width,
(bounding_box[1] - bounding_box[3] / 2) * ratio_height,
(bounding_box[0] + bounding_box[2] / 2) * ratio_width,
(bounding_box[1] + bounding_box[3] / 2) * ratio_height
]))
face_landmark_5_raw[:, 0::3] = (face_landmark_5_raw[:, 0::3]) * ratio_width
face_landmark_5_raw[:, 1::3] = (face_landmark_5_raw[:, 1::3]) * ratio_height
for face_landmark_5 in face_landmark_5_raw:
face_landmark_5_list.append(np.array(face_landmark_5.reshape(-1, 3)[:, :2]))
score_list = score_raw.ravel().tolist()
return self.post_process(image.shape, bounding_box_list, face_landmark_5_list, score_list)
if __name__ == "__main__":
model_path = '/Users/wadahana/workspace/AI/sd/ComfyUI/models/facefusion/yoloface_8n.onnx'
providers=['CPUExecutionProvider']
detector = YoloFaceOnnx(model_path=model_path, providers=providers)
image = cv2.imread('/Users/wadahana/Desktop/test4.jpg')
face_list = detector.detect(image=image, conf=0.7)
face = face_list[0]
pt1 = (int(face.bounding_box[0]), int(face.bounding_box[1])) # 左上角 (x1, y1)
pt2 = (int(face.bounding_box[2]), int(face.bounding_box[3])) # 右下角 (x2, y2)
cv2.rectangle(image, pt1, pt2, (255, 0, 0), 1)
print(f'face_list: {face_list}')
cv2.imwrite('/Users/wadahana/Desktop/output.jpg', image)
|