|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
""" |
|
This script demonstrates how to use the Calibrator API provided by Polygraphy |
|
to calibrate a TensorRT engine to run in INT8 precision. |
|
""" |
|
import numpy as np |
|
from polygraphy.backend.trt import Calibrator, CreateConfig, EngineFromNetwork, NetworkFromOnnxPath, TrtRunner, save_engine, load_plugins, Profile |
|
from polygraphy.logger import G_LOGGER |
|
from termcolor import cprint |
|
load_plugins(plugins=['libmmdeploy_tensorrt_ops.so']) |
|
import cv2 |
|
import argparse |
|
|
|
G_LOGGER.severity = G_LOGGER.EXTRA_VERBOSE |
|
PREVIEW_CALIBRATOR_OUTPUT = True |
|
|
|
def calib_data_from_video(batch_size=1): |
|
|
|
|
|
def preprocess(img: np.ndarray): |
|
"""Do preprocessing for RTMPose model inference. |
|
|
|
Args: |
|
img (np.ndarray): Input image in shape. |
|
|
|
Returns: |
|
tuple: |
|
- resized_img (np.ndarray): Preprocessed image. |
|
- center (np.ndarray): Center of image. |
|
- scale (np.ndarray): Scale of image. |
|
""" |
|
if len(img.shape) == 3: |
|
padded_img = np.ones( |
|
(MODEL_INPUT_SIZE[0], MODEL_INPUT_SIZE[1], 3), |
|
dtype=np.uint8) * 114 |
|
else: |
|
padded_img = np.ones(MODEL_INPUT_SIZE, dtype=np.uint8) * 114 |
|
|
|
ratio = min(MODEL_INPUT_SIZE[0] / img.shape[0], |
|
MODEL_INPUT_SIZE[1] / img.shape[1]) |
|
resized_img = cv2.resize( |
|
img, |
|
(int(img.shape[1] * ratio), int(img.shape[0] * ratio)), |
|
interpolation=cv2.INTER_LINEAR, |
|
).astype(np.uint8) |
|
padded_shape = (int(img.shape[0] * ratio), int(img.shape[1] * ratio)) |
|
padded_img[:padded_shape[0], :padded_shape[1]] = resized_img |
|
|
|
return padded_img, ratio |
|
|
|
cap = cv2.VideoCapture(filename=VIDEO_PATH) |
|
imgs = [] |
|
while cap.isOpened(): |
|
|
|
success, frame = cap.read() |
|
if success: |
|
img, ratio = preprocess(frame) |
|
img = img.transpose(2, 0, 1) |
|
img = np.ascontiguousarray(img, dtype=np.float32) |
|
img = img[None, :, :, :] |
|
|
|
imgs.append(img) |
|
if len(imgs) == batch_size: |
|
batch_img = np.vstack(imgs) |
|
yield {"input": batch_img} |
|
imgs = [] |
|
|
|
else: |
|
break |
|
|
|
cap.release() |
|
|
|
def main(onnx_path, engine_path, batch_size): |
|
|
|
|
|
|
|
|
|
|
|
|
|
if batch_size < 1: |
|
|
|
profiles = [ |
|
|
|
Profile().add("input", |
|
min=(1, 3, MODEL_INPUT_SIZE[0], MODEL_INPUT_SIZE[1]), |
|
opt=(4, 3, MODEL_INPUT_SIZE[0], MODEL_INPUT_SIZE[1]), |
|
max=(9, 3, MODEL_INPUT_SIZE[0], MODEL_INPUT_SIZE[1])), |
|
] |
|
|
|
else: |
|
profiles = [ |
|
|
|
Profile().add("input", |
|
min=(batch_size, 3, MODEL_INPUT_SIZE[0], MODEL_INPUT_SIZE[1]), |
|
opt=(batch_size, 3, MODEL_INPUT_SIZE[0], MODEL_INPUT_SIZE[1]), |
|
max=(batch_size, 3, MODEL_INPUT_SIZE[0], MODEL_INPUT_SIZE[1])), |
|
] |
|
|
|
opt_batch_size = profiles[0]['input'].opt[0] |
|
calibrator = Calibrator(data_loader=calib_data_from_video(opt_batch_size)) |
|
|
|
|
|
build_engine = EngineFromNetwork( |
|
NetworkFromOnnxPath(f"{onnx_path}"), config=CreateConfig( |
|
use_dla=False, |
|
tf32=True, |
|
fp16=True, |
|
int8=True, |
|
precision_constraints="prefer", |
|
sparse_weights=True, |
|
calibrator=calibrator, |
|
profiles=profiles, |
|
max_workspace_size = 2 * 1024 * 1024 * 1024, |
|
allow_gpu_fallback=True, |
|
) |
|
) |
|
|
|
|
|
|
|
save_engine(build_engine, f'{engine_path}') |
|
|
|
if __name__ == "__main__": |
|
|
|
parser = argparse.ArgumentParser(description="Process a video file.") |
|
parser.add_argument("video_path", type=str, help="The path to the video file used to calibrate int8 engine") |
|
parser.add_argument("onnx_path", type=str, help="The path to the input ONNX model file") |
|
parser.add_argument("engine_path", type=str, help="The path to the exported TensorRT Engine model file") |
|
parser.add_argument("--batch_size", type=int, default=-1, help="Input batch size (not specified if dynamic)") |
|
args = parser.parse_args() |
|
VIDEO_PATH = args.video_path |
|
MODEL_INPUT_SIZE=(416,416) if 'rtmo-t' in args.onnx_path else (640,640) |
|
|
|
if PREVIEW_CALIBRATOR_OUTPUT: |
|
cprint('You are previwing video used to calibrate TensorRT int8 engine model ...', 'yellow') |
|
for output_dict in calib_data_from_video(): |
|
if output_dict: |
|
image = output_dict['input'] |
|
image_to_show = image.squeeze(0).transpose(1, 2, 0) / 255.0 |
|
cv2.imshow(VIDEO_PATH,image_to_show) |
|
if cv2.waitKey(1) & 0xFF == ord('q'): |
|
break |
|
cv2.destroyAllWindows() |
|
|
|
main(args.onnx_path, args.engine_path, args.batch_size) |
|
|