drkareemkamal's picture
Upload 9 files
fcc36c6 verified
import numpy as np
import json
import triton_python_backend_utils as pb_utils
import cv2
class TritonPythonModel:
"""Your Python model must use the same class name. Every Python model
that is created must have "TritonPythonModel" as the class name.
"""
def initialize(self, args):
"""`initialize` is called only once when the model is being loaded.
Implementing `initialize` function is optional. This function allows
the model to intialize any state associated with this model.
Parameters
----------
args : dict
Both keys and values are strings. The dictionary keys and values are:
* model_config: A JSON string containing the model configuration
* model_instance_kind: A string containing model instance kind
* model_instance_device_id: A string containing model instance device ID
* model_repository: Model repository path
* model_version: Model version
* model_name: Model name
"""
# You must parse model_config. JSON string is not parsed here
self.model_config = model_config = json.loads(args['model_config'])
# Get OUTPUT0 configuration
num_detections_config = pb_utils.get_output_config_by_name(
model_config, "num_detections")
detection_boxes_config = pb_utils.get_output_config_by_name(
model_config, "detection_boxes")
detection_scores_config = pb_utils.get_output_config_by_name(
model_config, "detection_scores")
detection_classes_config = pb_utils.get_output_config_by_name(
model_config, "detection_classes")
# Convert Triton types to numpy types
self.num_detections_dtype = pb_utils.triton_string_to_numpy(
num_detections_config['data_type'])
# Convert Triton types to numpy types
self.detection_boxes_dtype = pb_utils.triton_string_to_numpy(
detection_boxes_config['data_type'])
# Convert Triton types to numpy types
self.detection_scores_dtype = pb_utils.triton_string_to_numpy(
detection_scores_config['data_type'])
# Convert Triton types to numpy types
self.detection_classes_dtype = pb_utils.triton_string_to_numpy(
detection_classes_config['data_type'])
self.score_threshold = 0.25
self.nms_threshold = 0.45
def execute(self, requests):
"""`execute` MUST be implemented in every Python model. `execute`
function receives a list of pb_utils.InferenceRequest as the only
argument. This function is called when an inference request is made
for this model. Depending on the batching configuration (e.g. Dynamic
Batching) used, `requests` may contain multiple requests. Every
Python model, must create one pb_utils.InferenceResponse for every
pb_utils.InferenceRequest in `requests`. If there is an error, you can
set the error argument when creating a pb_utils.InferenceResponse
Parameters
----------
requests : list
A list of pb_utils.InferenceRequest
Returns
-------
list
A list of pb_utils.InferenceResponse. The length of this list must
be the same as `requests`
"""
num_detections_dtype = self.num_detections_dtype
detection_boxes_dtype = self.detection_boxes_dtype
detection_scores_dtype = self.detection_scores_dtype
detection_classes_dtype = self.detection_classes_dtype
responses = []
# Every Python backend must iterate over everyone of the requests
# and create a pb_utils.InferenceResponse for each of them.
for request in requests:
# Get INPUT0
in_0 = pb_utils.get_input_tensor_by_name(request, "INPUT_0")
# Get the output arrays from the results
outputs = in_0.as_numpy()
outputs = np.array([cv2.transpose(outputs[0])])
rows = outputs.shape[1]
boxes = []
scores = []
class_ids = []
for i in range(rows):
classes_scores = outputs[0][i][4:]
(minScore, maxScore, minClassLoc, (x, maxClassIndex)
) = cv2.minMaxLoc(classes_scores)
if maxScore >= self.score_threshold:
box = [outputs[0][i][0] -
(0.5 *
outputs[0][i][2]), outputs[0][i][1] -
(0.5 *
outputs[0][i][3]), outputs[0][i][2], outputs[0][i][3]]
boxes.append(box)
scores.append(maxScore)
class_ids.append(maxClassIndex)
result_boxes = cv2.dnn.NMSBoxes(boxes, scores,
self.score_threshold,
self.nms_threshold,
0.5)
num_detections = 0
output_boxes = []
output_scores = []
output_classids = []
for i in range(len(result_boxes)):
index = result_boxes[i]
box = boxes[index]
detection = {
'class_id': class_ids[index],
'confidence': scores[index],
'box': box}
output_boxes.append(box)
output_scores.append(scores[index])
output_classids.append(class_ids[index])
num_detections += 1
num_detections = np.array(num_detections)
num_detections = pb_utils.Tensor(
"num_detections", num_detections.astype(num_detections_dtype))
detection_boxes = np.array(output_boxes)
detection_boxes = pb_utils.Tensor(
"detection_boxes", detection_boxes.astype(detection_boxes_dtype))
detection_scores = np.array(output_scores)
detection_scores = pb_utils.Tensor(
"detection_scores", detection_scores.astype(detection_scores_dtype))
detection_classes = np.array(output_classids)
detection_classes = pb_utils.Tensor(
"detection_classes",
detection_classes.astype(detection_classes_dtype))
inference_response = pb_utils.InferenceResponse(
output_tensors=[
num_detections,
detection_boxes,
detection_scores,
detection_classes])
responses.append(inference_response)
return responses
def finalize(self):
"""`finalize` is called only once when the model is being unloaded.
Implementing `finalize` function is OPTIONAL. This function allows
the model to perform any necessary clean ups before exit.
"""
pass