| import cv2 |
| import cv2 as cv |
| import numpy as np |
| from yunet import YuNet |
|
|
|
|
| |
| backend_target_pairs = [ |
| [cv.dnn.DNN_BACKEND_OPENCV, cv.dnn.DNN_TARGET_CPU], |
| [cv.dnn.DNN_BACKEND_CUDA, cv.dnn.DNN_TARGET_CUDA], |
| [cv.dnn.DNN_BACKEND_CUDA, cv.dnn.DNN_TARGET_CUDA_FP16], |
| [cv.dnn.DNN_BACKEND_TIMVX, cv.dnn.DNN_TARGET_NPU], |
| [cv.dnn.DNN_BACKEND_CANN, cv.dnn.DNN_TARGET_NPU], |
| ] |
|
|
|
|
| class ImageResizer: |
| def __init__( |
| self, |
| modelPath, |
| input_size=(320, 320), |
| conf_threshold=0.6, |
| nms_threshold=0.3, |
| top_k=5000, |
| backend_id=0, |
| target_id=0, |
| ): |
| self.model = YuNet( |
| modelPath=modelPath, |
| inputSize=input_size, |
| confThreshold=conf_threshold, |
| nmsThreshold=nms_threshold, |
| topK=top_k, |
| backendId=backend_id, |
| targetId=target_id, |
| ) |
|
|
| def detect(self, image, num_faces=None): |
| |
| if image is not None: |
| h, w, _ = image.shape |
|
|
| |
| self.model.setInputSize([w, h]) |
| results = self.model.infer(image) |
|
|
| faces = results[:num_faces] if num_faces else results |
|
|
| bboxs = [] |
|
|
| for face in faces: |
| bbox = face[0:4].astype(np.int32) |
| x, y, w, h = bbox |
| |
| cv2.rectangle(image, (x, y), (x + w, y + h), (0, 0, 255), 2) |
| bboxs.append(bbox) |
|
|
| return image, bboxs |
|
|
| def resize(self, image, target_size=512, above_head_ratio=0.5): |
| height, width, _c = image.shape |
| ar = width / height |
| |
| if not target_size: |
| target_size = 512 |
| if ar > 1: |
| |
| new_height = target_size |
| new_width = int(target_size * ar) |
| elif ar < 1: |
| |
| new_width = target_size |
| new_height = int(target_size / ar) |
| else: |
| |
| new_width = target_size |
| new_height = target_size |
|
|
| resized = cv2.resize( |
| image, (new_width, new_height), interpolation=cv2.INTER_AREA |
| ) |
|
|
| |
| dt_image, bboxes = self.detect(resized.copy()) |
|
|
| |
| if len(bboxes) >= 1: |
| x, y, w, h = bboxes[0] |
| else: |
| x, y, w, h = 0, 0, target_size, target_size |
| |
| above_head_max = int(target_size * above_head_ratio) |
| x_center = int((x + (x + w)) / 2) |
| y_center = int((y + (y + h)) / 2) |
| |
| top = int(max(0, y_center - above_head_max)) |
| bottom = int(min(top + target_size, resized.shape[0])) |
|
|
| left = int(max(0, x_center - target_size // 2)) |
| right = int(min(x_center + target_size // 2, resized.shape[1])) |
|
|
| |
| _w = right - left |
| if _w != target_size: |
| dx = ( |
| target_size - _w |
| ) |
| nl = max(0, left - dx) |
| dr = dx - nl |
| left = nl |
| right += dr |
|
|
| cropped_image = resized[top:bottom, left:right] |
| return dt_image, cropped_image |
|
|