Skip to content

Commit f6ba577

Browse files
committed
fix: missing model code for CV-CUDA Release 0.3.0 Beta
1 parent f11c87c commit f6ba577

File tree

8 files changed

+623
-2
lines changed

8 files changed

+623
-2
lines changed

.gitattributes

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,4 @@
1919
*.onnx filter=lfs diff=lfs merge=lfs -text
2020
*.bmp filter=lfs diff=lfs merge=lfs -text
2121
*.mp4 filter=lfs diff=lfs merge=lfs -text
22+
*.a filter=lfs diff=lfs merge=lfs -text

.gitignore

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# SPDX-FileCopyrightText: Copyright (c) 2022 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
1+
# SPDX-FileCopyrightText: Copyright (c) 2022-2023 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
22
# SPDX-License-Identifier: Apache-2.0
33
#
44
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -50,5 +50,4 @@ _exhale_api
5050

5151
# Samples
5252
# -------------
53-
models
5453
*.engine

.pre-commit-config.yaml

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
# SPDX-FileCopyrightText: Copyright (c) 2022-2023 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2+
# SPDX-License-Identifier: Apache-2.0
3+
#
4+
# Licensed under the Apache License, Version 2.0 (the "License");
5+
# you may not use this file except in compliance with the License.
6+
# You may obtain a copy of the License at
7+
#
8+
# http://www.apache.org/licenses/LICENSE-2.0
9+
#
10+
# Unless required by applicable law or agreed to in writing, software
11+
# distributed under the License is distributed on an "AS IS" BASIS,
12+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
# See the License for the specific language governing permissions and
14+
# limitations under the License.
15+
16+
# See https://pre-commit.com for more information
17+
# See https://pre-commit.com/hooks.html for more hooks
18+
19+
default_stages:
20+
- merge-commit
21+
- commit
22+
- post-rewrite
23+
24+
repos:
25+
- repo: https://github.com/pre-commit/pre-commit-hooks
26+
rev: v4.3.0
27+
hooks:
28+
- id: check-merge-conflict
29+
- id: trailing-whitespace
30+
- id: end-of-file-fixer
31+
- id: mixed-line-ending
32+
args: ['--fix=lf']
33+
- id: check-executables-have-shebangs
34+
- id: check-shebang-scripts-are-executable
35+
- id: detect-private-key
36+
- id: check-added-large-files
37+
- id: check-case-conflict
38+
- id: destroyed-symlinks
39+
- id: check-yaml
40+
exclude: '.clang-format'
41+
42+
- repo: https://github.com/detailyang/pre-commit-shell
43+
rev: 1.0.5
44+
hooks:
45+
- id: shell-lint
46+
args: ['-x', '--severity=warning']
47+
48+
- repo: https://github.com/pre-commit/mirrors-clang-format
49+
rev: v14.0.6
50+
hooks:
51+
- id: clang-format
52+
53+
- repo: https://github.com/pryorda/dockerfilelint-precommit-hooks
54+
rev: v0.1.0
55+
hooks:
56+
- id: dockerfilelint
57+
58+
- repo: https://github.com/psf/black
59+
rev: 22.10.0
60+
hooks:
61+
- id: black
62+
63+
- repo: https://github.com/pycqa/flake8
64+
rev: 5.0.4
65+
hooks:
66+
- id: flake8
67+
args:
68+
- "--max-line-length=110"
69+
70+
- repo: local
71+
hooks:
72+
- id: copyright_check
73+
name: 'check copyright message'
74+
language: system
75+
types: ['file', 'text']
76+
exclude_types: ['markdown', 'xml', 'json', 'csv']
77+
entry: ./lint/copyright_check.sh
78+
exclude: 'models/.*'
79+
- id: lfs_check
80+
name: 'check LFS objects'
81+
language: system
82+
entry: ./lint/lfs_check.sh
83+
require_serial: true
84+
85+
- repo: https://github.com/alessandrojcm/commitlint-pre-commit-hook
86+
rev: v9.0.0
87+
hooks:
88+
- id: commitlint
89+
stages: [commit-msg]
90+
args: ['--config','lint/commitlint.config.js']
91+
additional_dependencies: ['@commitlint/config-conventional']
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
#!/bin/bash -e
2+
3+
# SPDX-FileCopyrightText: Copyright (c) 2023 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
4+
# SPDX-License-Identifier: Apache-2.0
5+
#
6+
# Licensed under the Apache License, Version 2.0 (the "License");
7+
# you may not use this file except in compliance with the License.
8+
# You may obtain a copy of the License at
9+
#
10+
# http://www.apache.org/licenses/LICENSE-2.0
11+
#
12+
# Unless required by applicable law or agreed to in writing, software
13+
# distributed under the License is distributed on an "AS IS" BASIS,
14+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
# See the License for the specific language governing permissions and
16+
# limitations under the License.
17+
18+
# Object Detection
19+
# PeopleNet model
20+
# This model is based on NVIDIA DetectNet_v2 detector with ResNet34 as feature extractor.
21+
22+
OUT_DIR='/tmp'
23+
24+
if [[ $# -ge 1 ]]; then
25+
OUT_DIR=$1
26+
fi
27+
28+
# Download the etlt model and the labels files from NGC
29+
30+
if [ ! -f $OUT_DIR/resnet34_peoplenet_int8.etlt ]
31+
then
32+
wget 'https://api.ngc.nvidia.com/v2/models/nvidia/tao/peoplenet/versions/deployable_quantized_v2.6.1/files/resnet34_peoplenet_int8.etlt' -P $OUT_DIR
33+
fi
34+
35+
if [ ! -f $OUT_DIR/labels.txt ]
36+
then
37+
wget 'https://api.ngc.nvidia.com/v2/models/nvidia/tao/peoplenet/versions/deployable_quantized_v2.6.1/files/labels.txt' -P $OUT_DIR
38+
fi
39+
40+
# Use tao-converter which parses the .etlt model file, and generates an optimized TensorRT engine
41+
# The model supports implicit batch dimension which requires the max batch size, input layer dimensions and ordering to be specified.
42+
if [ ! -f ${OUT_DIR}/peoplenet.engine ]
43+
then
44+
/tmp/tao_binaries/tao-converter -e $OUT_DIR/peoplenet.engine -k tlt_encode -d 3,544,960 -m 32 -i nchw $OUT_DIR/resnet34_peoplenet_int8.etlt
45+
fi
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
# SPDX-FileCopyrightText: Copyright (c) 2022-2023 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2+
# SPDX-License-Identifier: Apache-2.0
3+
#
4+
# Licensed under the Apache License, Version 2.0 (the "License");
5+
# you may not use this file except in compliance with the License.
6+
# You may obtain a copy of the License at
7+
#
8+
# http://www.apache.org/licenses/LICENSE-2.0
9+
#
10+
# Unless required by applicable law or agreed to in writing, software
11+
# distributed under the License is distributed on an "AS IS" BASIS,
12+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
# See the License for the specific language governing permissions and
14+
# limitations under the License.
15+
16+
# docs_tag: begin_python_imports
17+
# NOTE: One must import PyCuda driver first, before CVCUDA or VPF otherwise
18+
# things may throw unexpected errors.
19+
import pycuda.driver as cuda
20+
import json
21+
import torch
22+
import cvcuda
23+
from model_inference import SegmentationPyTorch
24+
from pipelines import PreprocessorCvcuda, PostprocessorCvcuda
25+
26+
# Import Triton modules
27+
import triton_python_backend_utils as pb_utils
28+
29+
# docs_tag: end_python_imports
30+
31+
32+
# Triton Python Model
33+
class TritonPythonModel:
34+
def initialize(self, args):
35+
# docs_tag: begin_init_model
36+
self.model_config = model_config = json.loads(args["model_config"])
37+
params = model_config["parameters"]
38+
self.device_id = int(params["device_id"]["string_value"])
39+
self.network_width = int(params["network_width"]["string_value"])
40+
self.network_height = int(params["network_height"]["string_value"])
41+
self.visualization_class_name = params["visualization_class_name"][
42+
"string_value"
43+
]
44+
cuda_device = cuda.Device(self.device_id)
45+
self.cuda_ctx = cuda_device.retain_primary_context()
46+
self.cuda_ctx.push()
47+
self.cvcuda_stream = cvcuda.Stream()
48+
self.torch_stream = torch.cuda.ExternalStream(self.cvcuda_stream.handle)
49+
50+
self.inference = SegmentationPyTorch(
51+
output_dir="/tmp",
52+
seg_class_name=self.visualization_class_name,
53+
batch_size=1,
54+
image_size=(self.network_width, self.network_height),
55+
device_id=self.device_id,
56+
)
57+
58+
self.input_tensor_name = "inputrgb"
59+
self.output_tensor_name = "outputrgb"
60+
61+
self.preprocess = PreprocessorCvcuda(self.device_id)
62+
self.postprocess = PostprocessorCvcuda(
63+
"NCHW",
64+
gpu_output=True,
65+
device_id=self.device_id,
66+
)
67+
# docs_tag: end_init_model
68+
69+
# docs_tag: begin_execute_model
70+
def execute(self, requests):
71+
responses = []
72+
# Every Python backend must iterate over everyone of the requests
73+
# and create a pb_utils.InferenceResponse for each of them.
74+
try:
75+
with self.cvcuda_stream, torch.cuda.stream(self.torch_stream):
76+
for request in requests:
77+
in_0 = pb_utils.get_input_tensor_by_name(
78+
request, self.input_tensor_name
79+
)
80+
in_0_numpy = in_0.as_numpy()
81+
image_tensors = torch.from_numpy(in_0_numpy)
82+
83+
orig_tensor, resized_tensor, normalized_tensor = self.preprocess(
84+
image_tensors.cuda(),
85+
out_size=(self.network_width, self.network_height),
86+
)
87+
88+
probabilities = self.inference(normalized_tensor)
89+
90+
blurred_frame = self.postprocess(
91+
probabilities,
92+
orig_tensor,
93+
resized_tensor,
94+
self.inference.class_index,
95+
)
96+
97+
# Get Triton output tensor
98+
out_tensor_0 = pb_utils.Tensor(
99+
"outputrgb", blurred_frame.cpu().numpy()
100+
)
101+
# Create inference response
102+
inference_response = pb_utils.InferenceResponse(
103+
output_tensors=[out_tensor_0]
104+
)
105+
responses.append(inference_response)
106+
107+
# You should return a list of pb_utils.InferenceResponse. Length
108+
# of this list must match the length of `requests` list.
109+
110+
return responses
111+
except Exception as e:
112+
print(e)
113+
# docs_tag: end_execute_model
114+
115+
# docs_tag: begin_finalize_model
116+
def finalize(self):
117+
self.cuda_ctx.pop()
118+
119+
# docs_tag: end_finalize_model
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
# SPDX-FileCopyrightText: Copyright (c) 2023 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2+
# SPDX-License-Identifier: Apache-2.0
3+
#
4+
# Licensed under the Apache License, Version 2.0 (the "License");
5+
# you may not use this file except in compliance with the License.
6+
# You may obtain a copy of the License at
7+
#
8+
# http://www.apache.org/licenses/LICENSE-2.0
9+
#
10+
# Unless required by applicable law or agreed to in writing, software
11+
# distributed under the License is distributed on an "AS IS" BASIS,
12+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
# See the License for the specific language governing permissions and
14+
# limitations under the License.
15+
16+
# Bring the commons folder from the samples directory into our path so that
17+
# we can import modules from it.
18+
import logging
19+
import torch
20+
import nvtx
21+
from torchvision.models import segmentation as segmentation_models
22+
23+
24+
# docs_tag: begin_init_segmentationpytorch
25+
class SegmentationPyTorch: # noqa: E302
26+
def __init__(
27+
self,
28+
output_dir,
29+
seg_class_name,
30+
batch_size,
31+
image_size,
32+
device_id,
33+
):
34+
self.logger = logging.getLogger(__name__)
35+
self.output_dir = output_dir
36+
self.device_id = device_id
37+
# Fetch the segmentation index to class name information from the weights
38+
# meta properties.
39+
# The underlying pytorch model that we use for inference is the FCN model
40+
# from torchvision.
41+
torch_model = segmentation_models.fcn_resnet101
42+
weights = segmentation_models.FCN_ResNet101_Weights.DEFAULT
43+
44+
try:
45+
self.class_index = weights.meta["categories"].index(seg_class_name)
46+
except ValueError:
47+
raise ValueError(
48+
"Requested segmentation class '%s' is not supported by the "
49+
"fcn_resnet101 model. All supported class names are: %s"
50+
% (seg_class_name, ", ".join(weights.meta["categories"]))
51+
)
52+
53+
# Inference uses PyTorch to run a segmentation model on the pre-processed
54+
# input and outputs the segmentation masks.
55+
class FCN_Softmax(torch.nn.Module):
56+
def __init__(self, fcn):
57+
super(FCN_Softmax, self).__init__()
58+
self.fcn = fcn
59+
60+
def forward(self, x):
61+
infer_output = self.fcn(x)["out"]
62+
return torch.nn.functional.softmax(infer_output, dim=1)
63+
64+
fcn_base = torch_model(weights=weights)
65+
fcn_base.eval()
66+
self.model = FCN_Softmax(fcn_base).cuda(self.device_id)
67+
self.model.eval()
68+
69+
self.logger.info("Using PyTorch as the inference engine.")
70+
# docs_tag: end_init_segmentationpytorch
71+
72+
# docs_tag: begin_call_segmentationpytorch
73+
def __call__(self, tensor):
74+
nvtx.push_range("inference.torch")
75+
76+
with torch.no_grad():
77+
78+
if isinstance(tensor, torch.Tensor):
79+
# We are all good here. Nothing needs to be done.
80+
pass
81+
else:
82+
# Convert CVCUDA tensor to Torch tensor.
83+
tensor = torch.as_tensor(
84+
tensor.cuda(), device="cuda:%d" % self.device_id
85+
)
86+
87+
segmented = self.model(tensor)
88+
89+
nvtx.pop_range()
90+
return segmented
91+
92+
# docs_tag: end_call_segmentationpytorch

0 commit comments

Comments
 (0)