HungKhoi's picture
Update
3846274
Raw
History Blame Contribute Delete
7.76 kB
# Copyright (c) OpenMMLab. All rights reserved.
from typing import List, Tuple, Dict
import numpy as np
from models.base.onnx_base import ONNX_Base
from models.base.trt_base import TRT_Base
from models.engine.utils import *
class RTMPose():
def __init__(self,
use_torch: bool=False) -> None:
self.use_torch = use_torch
def preprocess(self,
input_data: np.ndarray,
input_size: Tuple[int, int] = (192, 256)) -> Tuple[np.ndarray, np.ndarray, np.ndarray]:
"""Do preprocessing for RTMPose model inference.
Args:
img (np.ndarray): Input image in shape.
input_size (tuple): Input image size in shape (w, h).
Returns:
tuple:
- resized_img (np.ndarray): Preprocessed image.
- center (np.ndarray): Center of image.
- scale (np.ndarray): Scale of image.
"""
tensor_data = []
# get shape of image
scales =[]
centers = []
for i in range(len(input_data)):
img = input_data[i]
img_shape = img.shape[:2]
bbox = np.array([0, 0, img_shape[1], img_shape[0]])
# get center and scale
center, scale = bbox_xyxy2cs(bbox, padding=1.25)
# do affine transformation
resized_img, scale = top_down_affine(input_size, scale, center, img)
# normalize image
mean = np.array([123.675, 116.28, 103.53])
std = np.array([58.395, 57.12, 57.375])
resized_img = (resized_img - mean) / std
centers.append(center)
scales.append(scale)
if self.use_torch:
tensor_data.append(torch.from_numpy(resized_img).to(self.device))
else:
tensor_data.append(resized_img.transpose(2, 0, 1))
if self.use_torch:
tensor_data = torch.stack(tensor_data, dim=0)[:, :, :, [2, 1, 0]].permute(0, 3, 1, 2).float().contiguous()
else:
tensor_data = np.stack(tensor_data, axis=0)
return tensor_data, centers, scales
def postprocess(self, outputs: List[np.ndarray],
model_input_size: Tuple[int, int],
centers: List[np.ndarray],
scales: List[np.ndarray],
simcc_split_ratio: float = 2.0,
use_torch=False
) -> Tuple[np.ndarray, np.ndarray]:
"""Postprocess for RTMPose model output.
Args:
outputs (np.ndarray): Output of RTMPose model.
model_input_size (tuple): RTMPose model Input image size.
center List[tuple(int,int)]: List of Center of bbox in shape (x, y).
scale List[tuple(int,int)]: List of Scales of bbox in shape (w, h).
simcc_split_ratio (float): Split ratio of simcc.
Returns:
tuple:
- keypoints (np.ndarray): Rescaled keypoints.
- scores (np.ndarray): Model predict scores.
"""
# use simcc to decode
simcc_x, simcc_y = outputs
tensor_keypoints = []
tensor_scores = []
assert simcc_x.shape[0] == simcc_y.shape[0]
for i in range(simcc_x.shape[0]):
simcc_x_3d = simcc_x[i][np.newaxis, :, :]
simcc_y_3d = simcc_y[i][np.newaxis, :, :]
keypoints, scores = decode(simcc_x_3d, simcc_y_3d, simcc_split_ratio, use_torch=use_torch)
# rescale keypoints
keypoints = keypoints / model_input_size * scales[i] + centers[i] - scales[i] / 2
tensor_keypoints.append(keypoints)
tensor_scores.append(scores)
tensor_keypoints = np.vstack(tensor_keypoints)
tensor_scores = np.vstack(tensor_scores)
return tensor_keypoints, tensor_scores
def crop_objects(self, image: np.ndarray, bounding_boxes: np.ndarray):
""" Function to crop objects in input image.
Args:
image (np.ndarray): input image with shape (H, W, C).
bounding_boxes (np.ndarray): Array with shape Nx4 with N is the number of objects.
"""
max_h, max_w = image.shape[:2]
cropped_images = []
for box in bounding_boxes:
x_top, y_top, x_bottom, y_bottom, _ = box.astype(int).tolist()
x_top = max(0, x_top)
y_top = max(0, y_top)
x_bottom = min(x_bottom, max_w)
y_bottom = min(y_bottom, max_h)
cropped_image = image[y_top:y_bottom, x_top:x_bottom]
cropped_images.append(cropped_image)
return cropped_images
class RTMPoseONNX(ONNX_Base, RTMPose):
def __init__(self,
use_torch,
img_shape: Tuple[int, int, int]=(3, 256, 192),
batch_size: int=32,
model_path: str="",
device: str='0'):
#/home/ccvn/Workspace/haimd/CC-Demo-Collection/end2end.onnx
"""_summary_
RTMPose ONNX class for inference, which is base on ONNX_BASE and RTMPose
Args:
use_torch (_type_): use torch tensor or numpy array in preprocess and postprocess function.
img_shape (Tuple[int, int], optional): _description_. Defaults to (640, 640).
batch_size (int, optional): _description_. Defaults to 32.
model_path (str, optional): _description_. Defaults to "".
device (str, optional): _description_. Defaults to '0'.
"""
self.img_shape = img_shape
self.batch_size = batch_size
input_shape = (self.batch_size, *self.img_shape)
super().__init__(input_shape, model_path, device)
RTMPose.__init__(self,
use_torch=use_torch)
def infer_batch(self, image_batch: np.ndarray):
h, w = self.session.get_inputs()[0].shape[2:]
model_input_size = (w, h)
numpy_array_data, centers, scales = self.preprocess(image_batch, model_input_size)
numpy_array_data = numpy_array_data.astype(np.float32)
results = super().infer_batch(numpy_array_data)
keypoints, scores = self.postprocess(results, model_input_size, centers, scales)
return {'keypoints':keypoints, 'scores': scores}
class RTMPoseTRT(TRT_Base, RTMPose):
def __init__(self,
use_torch,
img_shape: Tuple[int, int, int]=(3, 256, 192),
batch_size: int=1,
model_path: str="",
device: str='0',):
""" RTMPoseTRT class for inference, which is based on TRT_Base and RTMPose.
"""
self.img_shape = img_shape
self.batch_size = batch_size
input_shape = (self.batch_size, *self.img_shape)
super().__init__(input_shape, model_path, device)
RTMPose.__init__(self,
use_torch=use_torch)
def infer_batch(self, image_batch: np.ndarray):
model_input_size = (self.img_shape[-1], self.img_shape[1])
tensor_data, centers, scales = self.preprocess(image_batch, model_input_size)
self.change_runtime_dimension(input_shape=(len(tensor_data), 3, model_input_size[1], model_input_size[0]))
self.model['binding_addrs']['input'] = int(tensor_data.data_ptr())
self.model['context'].execute_v2(list(self.model['binding_addrs'].values()))
simcc_x = self.model['bindings']['simcc_x'].data.cpu()
simcc_y = self.model['bindings']['simcc_y'].data.cpu()
results = (simcc_x, simcc_y)
keypoints, scores = self.postprocess(results, model_input_size, centers, scales, use_torch=self.use_torch)
return {'keypoints':keypoints, 'scores': scores}