Files
Rajeev Rao aff45dd565 TensorRT OSS 8.0 release
Signed-off-by: Rajeev Rao <rajeevrao@nvidia.com>
2021-07-02 16:35:44 -07:00

187 lines
6.9 KiB
Python
Executable File

#!/usr/bin/env python3
#
# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
import argparse
import os
import time
import numpy as np
import pycuda.autoinit
import tensorrt as trt
import utils.boxes as boxes_utils # Drawing bounding boxes
import utils.coco as coco_utils # COCO dataset descriptors
from utils.inference_trt import TRTInference # TRT inference wrappers
from PIL import Image
from utils.paths import PATHS # Path management
# COCO label list
COCO_LABELS = coco_utils.COCO_CLASSES_LIST
# Model used for inference
MODEL_NAME = 'ssd_inception_v2_coco_2017_11_17'
# Confidence threshold for drawing bounding box
VISUALIZATION_THRESHOLD = 0.5
# Precision command line argument -> TRT Engine datatype
TRT_PRECISION_TO_DATATYPE = {
16: trt.DataType.HALF,
32: trt.DataType.FLOAT
}
# Layout of TensorRT network output metadata
TRT_PREDICTION_LAYOUT = {
"image_id": 0,
"label": 1,
"confidence": 2,
"xmin": 3,
"ymin": 4,
"xmax": 5,
"ymax": 6
}
def fetch_prediction_field(field_name, detection_out, pred_start_idx):
"""Fetches prediction field from prediction byte array.
After TensorRT inference, prediction data is saved in
byte array and returned by object detection network.
This byte array contains several pieces of data about
prediction - we call one such piece a prediction field.
The prediction fields layout is described in TRT_PREDICTION_LAYOUT.
This function, given prediction byte array returned by network,
staring index of given prediction and field name of interest,
returns prediction field data corresponding to given arguments.
Args:
field_name (str): field of interest, one of keys of TRT_PREDICTION_LAYOUT
detection_out (array): object detection network output
pred_start_idx (int): start index of prediction of interest in detection_out
Returns:
Prediction field corresponding to given data.
"""
return detection_out[pred_start_idx + TRT_PREDICTION_LAYOUT[field_name]]
def analyze_prediction(detection_out, pred_start_idx, img_pil):
image_id = int(fetch_prediction_field("image_id", detection_out, pred_start_idx))
label = int(fetch_prediction_field("label", detection_out, pred_start_idx))
confidence = fetch_prediction_field("confidence", detection_out, pred_start_idx)
xmin = fetch_prediction_field("xmin", detection_out, pred_start_idx)
ymin = fetch_prediction_field("ymin", detection_out, pred_start_idx)
xmax = fetch_prediction_field("xmax", detection_out, pred_start_idx)
ymax = fetch_prediction_field("ymax", detection_out, pred_start_idx)
if confidence > VISUALIZATION_THRESHOLD:
class_name = COCO_LABELS[label]
confidence_percentage = "{0:.0%}".format(confidence)
print("Detected {} with confidence {}".format(
class_name, confidence_percentage))
boxes_utils.draw_bounding_boxes_on_image(
img_pil, np.array([[ymin, xmin, ymax, xmax]]),
display_str_list=["{}: {}".format(
class_name, confidence_percentage)],
color=coco_utils.COCO_COLORS[label]
)
def parse_commandline_arguments():
"""Parses command line arguments and adjusts internal data structures."""
# Define script command line arguments
parser = argparse.ArgumentParser(description='Run object detection inference on input image.')
parser.add_argument('input_img_path', metavar='INPUT_IMG_PATH',
help='an image file to run inference on')
parser.add_argument('-p', '--precision', type=int, choices=[32, 16], default=32,
help='desired TensorRT float precision to build an engine with')
parser.add_argument('-b', '--max_batch_size', type=int, default=1,
help='max TensorRT engine batch size')
parser.add_argument('-w', '--workspace_dir',
help='sample workspace directory')
parser.add_argument("-o", "--output",
help="path of the output file",
default=os.path.join(PATHS.get_sample_root(), "image_inferred.jpg"))
parser.add_argument('-d', '--data',
help="Specify the data directory where it is saved in. $TRT_DATA_DIR will be overwritten by this argument.")
args, _ = parser.parse_known_args()
data_dir = os.environ.get('TRT_DATA_DIR', None) if args.data is None else args.data
if data_dir is None:
raise ValueError("Data directory must be specified by either `-d $DATA` or environment variable $TRT_DATA_DIR.")
PATHS.set_data_dir_path(data_dir)
# Set workspace dir path if passed by user
if args.workspace_dir:
PATHS.set_workspace_dir_path(args.workspace_dir)
try:
os.makedirs(PATHS.get_workspace_dir_path())
except:
pass
# Verify Paths after adjustments. This also exits script if verification fails
PATHS.verify_all_paths()
# Fetch TensorRT engine path and datatype
args.trt_engine_datatype = TRT_PRECISION_TO_DATATYPE[args.precision]
args.trt_engine_path = PATHS.get_engine_path(args.trt_engine_datatype,
args.max_batch_size)
try:
os.makedirs(os.path.dirname(args.trt_engine_path))
except:
pass
return args
def main():
# Parse command line arguments
args = parse_commandline_arguments()
# Fetch .uff model path
ssd_model_uff_path = PATHS.get_model_uff_path(MODEL_NAME)
# Set up all TensorRT data structures needed for inference
trt_inference_wrapper = TRTInference(
args.trt_engine_path, ssd_model_uff_path,
trt_engine_datatype=args.trt_engine_datatype,
batch_size=args.max_batch_size)
# Start measuring time
inference_start_time = time.time()
# Get TensorRT SSD model output
detection_out, keep_count_out = \
trt_inference_wrapper.infer(args.input_img_path)
# Make PIL.Image for drawing bounding boxes and
# let analyze_prediction() draw them based on model output
img_pil = Image.open(args.input_img_path)
prediction_fields = len(TRT_PREDICTION_LAYOUT)
for det in range(int(keep_count_out[0])):
analyze_prediction(detection_out, det * prediction_fields, img_pil)
# Output total [img load + inference + drawing bboxes] time
print("Total time taken for one image: {} ms\n".format(
int(round((time.time() - inference_start_time) * 1000))))
# Save output image and output path
img_pil.save(args.output)
print("Saved output image to: {}".format(args.output))
if __name__ == '__main__':
main()