Commit ·
e6e795c
1
Parent(s): 8fab2b0
add 2 m
Browse files
conversion_scripts/dpt_pt_2_trt.py
ADDED
|
@@ -0,0 +1,111 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/usr/bin/env python3
|
| 2 |
+
"""
|
| 3 |
+
Depth-Anything V2 (metric)
|
| 4 |
+
PyTorch → ONNX → TensorRT
|
| 5 |
+
|
| 6 |
+
Default: static 518×518 engine.
|
| 7 |
+
Add --dynamic to build a multi-resolution engine.
|
| 8 |
+
|
| 9 |
+
Error “no optimisation profile” is gone because the script
|
| 10 |
+
creates a profile whenever the ONNX contains -1 dimensions.
|
| 11 |
+
"""
|
| 12 |
+
|
| 13 |
+
import argparse, os, sys, onnx, torch, tensorrt as trt, pycuda.driver as cuda
|
| 14 |
+
cuda.init(); import pycuda.autoinit # noqa: E402
|
| 15 |
+
from depth_anything_v2.dpt import DepthAnythingV2
|
| 16 |
+
|
| 17 |
+
# ───────────────────────── checkpoints ─────────────────────────
|
| 18 |
+
def ckpt_path(ds, enc):
|
| 19 |
+
return f"checkpoints/depth_anything_v2_metric_{ds}_{enc}.pth"
|
| 20 |
+
|
| 21 |
+
# ───────────────────────── ONNX export ─────────────────────────
|
| 22 |
+
def export_onnx(a):
|
| 23 |
+
cfg = {
|
| 24 |
+
"vits": dict(encoder="vits", features=64, out_channels=[48, 96,192,384]),
|
| 25 |
+
"vitb": dict(encoder="vitb", features=128, out_channels=[96,192,384,768]),
|
| 26 |
+
"vitl": dict(encoder="vitl", features=256, out_channels=[256,512,1024,1024])
|
| 27 |
+
}
|
| 28 |
+
print(f"[ONNX] export {a.encoder.upper()} ({a.dataset}) …")
|
| 29 |
+
model = DepthAnythingV2(**cfg[a.encoder], max_depth=a.max_depth).to("cuda")
|
| 30 |
+
model.load_state_dict(torch.load(ckpt_path(a.dataset, a.encoder), map_location="cuda"),
|
| 31 |
+
strict=False)
|
| 32 |
+
model.eval()
|
| 33 |
+
|
| 34 |
+
dummy = torch.randn(1, 3, *a.input_hw, device="cuda")
|
| 35 |
+
dynamic_axes = {}
|
| 36 |
+
if a.dynamic: # only add dynamic sizes if user asked for it
|
| 37 |
+
dynamic_axes = {"rgb": {0: "N", 2: "H", 3: "W"}}
|
| 38 |
+
|
| 39 |
+
torch.onnx.export(
|
| 40 |
+
model, dummy, a.onnx,
|
| 41 |
+
opset_version=17,
|
| 42 |
+
input_names=["rgb"], output_names=["depth"],
|
| 43 |
+
do_constant_folding=True, dynamic_axes=dynamic_axes)
|
| 44 |
+
onnx.checker.check_model(onnx.load(a.onnx))
|
| 45 |
+
print(f"[ONNX] saved → {a.onnx}")
|
| 46 |
+
|
| 47 |
+
# ───────────────────── TensorRT build ──────────────────────────
|
| 48 |
+
def build_trt(a):
|
| 49 |
+
print("[TRT] build …")
|
| 50 |
+
logger, builder = trt.Logger(trt.Logger.INFO), trt.Builder(trt.Logger(trt.Logger.INFO))
|
| 51 |
+
network = builder.create_network()
|
| 52 |
+
parser = trt.OnnxParser(network, logger)
|
| 53 |
+
with open(a.onnx, "rb") as f:
|
| 54 |
+
if not parser.parse(f.read()):
|
| 55 |
+
for i in range(parser.num_errors):
|
| 56 |
+
print(parser.get_error(i)); sys.exit(1)
|
| 57 |
+
|
| 58 |
+
cfg = builder.create_builder_config()
|
| 59 |
+
cfg.set_memory_pool_limit(trt.MemoryPoolType.WORKSPACE, int(a.workspace_gb * (1 << 30)))
|
| 60 |
+
if a.fp16 and builder.platform_has_fast_fp16: cfg.set_flag(trt.BuilderFlag.FP16)
|
| 61 |
+
if a.sparse and hasattr(trt.BuilderFlag, "SPARSE_WEIGHTS"):
|
| 62 |
+
cfg.set_flag(trt.BuilderFlag.SPARSE_WEIGHTS)
|
| 63 |
+
|
| 64 |
+
# ── add optimisation profile if input is dynamic ──
|
| 65 |
+
if network.get_input(0).shape[0] == -1:
|
| 66 |
+
prof = builder.create_optimization_profile()
|
| 67 |
+
in_name = network.get_input(0).name
|
| 68 |
+
h, w = a.input_hw
|
| 69 |
+
prof.set_shape(in_name, (1,3,h,w), (1,3,h,w), (4,3,h,w))
|
| 70 |
+
cfg.add_optimization_profile(prof) # mandatory :contentReference[oaicite:2]{index=2}
|
| 71 |
+
|
| 72 |
+
# TRT-10 path
|
| 73 |
+
if hasattr(builder, "build_serialized_network"):
|
| 74 |
+
eng_bytes = builder.build_serialized_network(network, cfg)
|
| 75 |
+
if eng_bytes is None: sys.exit("[ERR] build failed")
|
| 76 |
+
engine = trt.Runtime(logger).deserialize_cuda_engine(eng_bytes)
|
| 77 |
+
else: # TRT-8 fallback
|
| 78 |
+
engine = builder.build_engine(network, cfg)
|
| 79 |
+
|
| 80 |
+
with open(a.engine, "wb") as f: f.write(engine.serialize())
|
| 81 |
+
print(f"[TRT] engine → {a.engine}")
|
| 82 |
+
|
| 83 |
+
# ───────────────────────────── CLI ─────────────────────────────
|
| 84 |
+
def parse():
|
| 85 |
+
p = argparse.ArgumentParser()
|
| 86 |
+
p.add_argument("-e","--encoder", choices=["vits","vitb","vitl"], default="vitb")
|
| 87 |
+
p.add_argument("-d","--dataset", choices=["vkitti","hypersim"], default="vkitti")
|
| 88 |
+
p.add_argument("--max-depth", type=float, default=80.0)
|
| 89 |
+
p.add_argument("--input-hw", type=int, nargs=2, default=[518,518])
|
| 90 |
+
p.add_argument("--workspace-gb", type=float, default=4.0)
|
| 91 |
+
p.add_argument("--fp16-off", dest="fp16", action="store_false")
|
| 92 |
+
p.add_argument("--sparse", action="store_true")
|
| 93 |
+
p.add_argument("--dynamic", action="store_true",
|
| 94 |
+
help="make H/W & batch dynamic (adds optimisation profile)")
|
| 95 |
+
p.add_argument("--rebuild", action="store_true")
|
| 96 |
+
return p.parse_args()
|
| 97 |
+
|
| 98 |
+
def main():
|
| 99 |
+
a = parse(); a.fp16 = getattr(a,"fp16",True); a.input_hw = tuple(a.input_hw)
|
| 100 |
+
base = f"depth_anything_v2_{a.encoder}_{a.dataset}"
|
| 101 |
+
a.onnx = f"{base}.onnx"
|
| 102 |
+
a.engine = f"{base}_{'fp16' if a.fp16 else 'fp32'}{'_dyn' if a.dynamic else ''}.engine"
|
| 103 |
+
if a.rebuild:
|
| 104 |
+
for f in (a.onnx, a.engine):
|
| 105 |
+
if os.path.isfile(f): os.remove(f)
|
| 106 |
+
if not os.path.isfile(a.onnx): export_onnx(a)
|
| 107 |
+
if not os.path.isfile(a.engine): build_trt(a)
|
| 108 |
+
else: print(f"[OK] engine exists → {a.engine}")
|
| 109 |
+
|
| 110 |
+
if __name__ == "__main__": main()
|
| 111 |
+
|
conversion_scripts/ultralytics-pt-to-trt.py
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os
|
| 2 |
+
import torch
|
| 3 |
+
from ultralytics import YOLO
|
| 4 |
+
|
| 5 |
+
# Set environment variables for CUDA
|
| 6 |
+
os.environ['CUDA_HOME'] = '/usr/local/cuda'
|
| 7 |
+
os.environ['PATH'] = f"{os.environ['CUDA_HOME']}/bin:{os.environ['PATH']}"
|
| 8 |
+
os.environ['LD_LIBRARY_PATH'] = f"{os.environ['CUDA_HOME']}/lib64:{os.environ.get('LD_LIBRARY_PATH', '')}"
|
| 9 |
+
|
| 10 |
+
def verify_cuda_installation():
|
| 11 |
+
print("Verifying CUDA installation...")
|
| 12 |
+
print("CUDA_HOME:", os.environ['CUDA_HOME'])
|
| 13 |
+
print("PATH:", os.environ['PATH'])
|
| 14 |
+
print("LD_LIBRARY_PATH:", os.environ['LD_LIBRARY_PATH'])
|
| 15 |
+
|
| 16 |
+
def check_cuda_availability():
|
| 17 |
+
print("Checking CUDA availability in PyTorch...")
|
| 18 |
+
cuda_available = torch.cuda.is_available()
|
| 19 |
+
print("CUDA available:", cuda_available)
|
| 20 |
+
if cuda_available:
|
| 21 |
+
device_count = torch.cuda.device_count()
|
| 22 |
+
print("CUDA device count:", device_count)
|
| 23 |
+
for i in range(device_count):
|
| 24 |
+
print(f"CUDA device {i}: {torch.cuda.get_device_name(i)}")
|
| 25 |
+
return cuda_available
|
| 26 |
+
|
| 27 |
+
def load_and_transform_model(cuda_available):
|
| 28 |
+
print("Loading YOLOv8 model...")
|
| 29 |
+
model = YOLO("best_model.pt")
|
| 30 |
+
|
| 31 |
+
if cuda_available:
|
| 32 |
+
print("CUDA is available. Exporting model to TensorRT format...")
|
| 33 |
+
model.export(format="engine") # creates 'debris-det.engine'
|
| 34 |
+
tensorrt_model = YOLO("best.engine")
|
| 35 |
+
else:
|
| 36 |
+
print("CUDA is not available. Skipping TensorRT export.")
|
| 37 |
+
tensorrt_model = model
|
| 38 |
+
|
| 39 |
+
return tensorrt_model
|
| 40 |
+
|
| 41 |
+
def run_inference(tensorrt_model):
|
| 42 |
+
print("Running inference...")
|
| 43 |
+
results = tensorrt_model("https://ultralytics.com/images/bus.jpg")
|
| 44 |
+
|
| 45 |
+
print("Inference results:")
|
| 46 |
+
print(results)
|
| 47 |
+
|
| 48 |
+
if __name__ == "__main__":
|
| 49 |
+
verify_cuda_installation()
|
| 50 |
+
cuda_available = check_cuda_availability()
|
| 51 |
+
tensorrt_model = load_and_transform_model(cuda_available)
|
| 52 |
+
run_inference(tensorrt_model)
|
| 53 |
+
|
conversion_scripts/unet_to_trt_lptop.py
ADDED
|
@@ -0,0 +1,149 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/usr/bin/env python3
|
| 2 |
+
import os
|
| 3 |
+
import torch
|
| 4 |
+
import torch.nn as nn
|
| 5 |
+
import tensorrt as trt
|
| 6 |
+
import pycuda.autoinit # initializes CUDA driver
|
| 7 |
+
|
| 8 |
+
class Encoder(nn.Module):
|
| 9 |
+
def __init__(self, in_channels, out_channels, rate, pooling=True):
|
| 10 |
+
super(Encoder, self).__init__()
|
| 11 |
+
self.pooling = pooling
|
| 12 |
+
self.bn = nn.BatchNorm2d(in_channels)
|
| 13 |
+
self.c1 = nn.Conv2d(in_channels, out_channels, kernel_size=3, padding=1)
|
| 14 |
+
self.drop = nn.Dropout(rate)
|
| 15 |
+
self.c2 = nn.Conv2d(out_channels, out_channels, kernel_size=3, padding=1)
|
| 16 |
+
self.pool = nn.MaxPool2d(kernel_size=2)
|
| 17 |
+
|
| 18 |
+
def forward(self, x):
|
| 19 |
+
x = self.bn(x)
|
| 20 |
+
x = nn.ReLU()(self.c1(x))
|
| 21 |
+
x = self.drop(x)
|
| 22 |
+
x = nn.ReLU()(self.c2(x))
|
| 23 |
+
if self.pooling:
|
| 24 |
+
y = self.pool(x)
|
| 25 |
+
return y, x
|
| 26 |
+
return x
|
| 27 |
+
|
| 28 |
+
class Decoder(nn.Module):
|
| 29 |
+
def __init__(self, in_channels, out_channels, skip_channels, rate):
|
| 30 |
+
super(Decoder, self).__init__()
|
| 31 |
+
self.bn = nn.BatchNorm2d(in_channels)
|
| 32 |
+
self.cT = nn.ConvTranspose2d(in_channels, out_channels, kernel_size=3, stride=2, padding=1, output_padding=1)
|
| 33 |
+
self.c1 = nn.Conv2d(out_channels + skip_channels, out_channels, kernel_size=3, padding=1)
|
| 34 |
+
self.drop = nn.Dropout(rate)
|
| 35 |
+
self.c2 = nn.Conv2d(out_channels, out_channels, kernel_size=3, padding=1)
|
| 36 |
+
|
| 37 |
+
def forward(self, x, skip_x):
|
| 38 |
+
x = self.bn(x)
|
| 39 |
+
x = nn.ReLU()(self.cT(x))
|
| 40 |
+
x = torch.cat([x, skip_x], dim=1)
|
| 41 |
+
x = nn.ReLU()(self.c1(x))
|
| 42 |
+
x = self.drop(x)
|
| 43 |
+
x = nn.ReLU()(self.c2(x))
|
| 44 |
+
return x
|
| 45 |
+
|
| 46 |
+
class UNet(nn.Module):
|
| 47 |
+
def __init__(self):
|
| 48 |
+
super(UNet, self).__init__()
|
| 49 |
+
self.initial = nn.Conv2d(3, 64, kernel_size=3, padding=1)
|
| 50 |
+
self.enc1 = Encoder(64, 64, 0.1)
|
| 51 |
+
self.enc2 = Encoder(64, 128, 0.1)
|
| 52 |
+
self.enc3 = Encoder(128, 256, 0.2)
|
| 53 |
+
self.enc4 = Encoder(256, 512, 0.2)
|
| 54 |
+
self.enc5 = Encoder(512, 512, 0.3, pooling=False)
|
| 55 |
+
|
| 56 |
+
self.dec1 = Decoder(512, 512, 512, 0.2)
|
| 57 |
+
self.dec2 = Decoder(512, 256, 256, 0.2)
|
| 58 |
+
self.dec3 = Decoder(256, 128, 128, 0.1)
|
| 59 |
+
self.dec4 = Decoder(128, 64, 64, 0.1)
|
| 60 |
+
|
| 61 |
+
self.final = nn.Conv2d(64, 1, kernel_size=3, padding=1)
|
| 62 |
+
|
| 63 |
+
def forward(self, x):
|
| 64 |
+
x = nn.ReLU()(self.initial(x))
|
| 65 |
+
p1, c1 = self.enc1(x)
|
| 66 |
+
p2, c2 = self.enc2(p1)
|
| 67 |
+
p3, c3 = self.enc3(p2)
|
| 68 |
+
p4, c4 = self.enc4(p3)
|
| 69 |
+
e = self.enc5(p4)
|
| 70 |
+
|
| 71 |
+
d1 = self.dec1(e, c4)
|
| 72 |
+
d2 = self.dec2(d1, c3)
|
| 73 |
+
d3 = self.dec3(d2, c2)
|
| 74 |
+
d4 = self.dec4(d3, c1)
|
| 75 |
+
|
| 76 |
+
return torch.sigmoid(self.final(d4))
|
| 77 |
+
|
| 78 |
+
|
| 79 |
+
def convert_to_onnx(model, input_shape, onnx_path):
|
| 80 |
+
model.eval()
|
| 81 |
+
dummy_input = torch.randn(input_shape).cuda()
|
| 82 |
+
torch.onnx.export(
|
| 83 |
+
model,
|
| 84 |
+
dummy_input,
|
| 85 |
+
onnx_path,
|
| 86 |
+
verbose=False,
|
| 87 |
+
opset_version=12,
|
| 88 |
+
input_names=["input"],
|
| 89 |
+
output_names=["output"]
|
| 90 |
+
)
|
| 91 |
+
print(f"✅ ONNX model saved at: {onnx_path}")
|
| 92 |
+
|
| 93 |
+
|
| 94 |
+
def convert_to_tensorrt_py(onnx_path, engine_path):
|
| 95 |
+
logger = trt.Logger(trt.Logger.WARNING)
|
| 96 |
+
builder = trt.Builder(logger)
|
| 97 |
+
network_flags = 1 << int(trt.NetworkDefinitionCreationFlag.EXPLICIT_BATCH)
|
| 98 |
+
network = builder.create_network(network_flags)
|
| 99 |
+
parser = trt.OnnxParser(network, logger)
|
| 100 |
+
|
| 101 |
+
with open(onnx_path, "rb") as f:
|
| 102 |
+
if not parser.parse(f.read()):
|
| 103 |
+
for i in range(parser.num_errors):
|
| 104 |
+
print(parser.get_error(i))
|
| 105 |
+
raise RuntimeError("Failed to parse ONNX model")
|
| 106 |
+
|
| 107 |
+
config = builder.create_builder_config()
|
| 108 |
+
# Set workspace memory limit to 1 GiB
|
| 109 |
+
config.set_memory_pool_limit(trt.MemoryPoolType.WORKSPACE, 1 << 30)
|
| 110 |
+
if builder.platform_has_fast_fp16:
|
| 111 |
+
config.set_flag(trt.BuilderFlag.FP16)
|
| 112 |
+
|
| 113 |
+
print("⏳ Building TensorRT engine in Python...")
|
| 114 |
+
serialized_engine = builder.build_serialized_network(network, config)
|
| 115 |
+
if serialized_engine is None:
|
| 116 |
+
raise RuntimeError("Failed to build serialized engine")
|
| 117 |
+
|
| 118 |
+
# Optional: Deserialize to verify
|
| 119 |
+
runtime = trt.Runtime(logger)
|
| 120 |
+
engine = runtime.deserialize_cuda_engine(serialized_engine)
|
| 121 |
+
if engine is None:
|
| 122 |
+
raise RuntimeError("Failed to deserialize engine")
|
| 123 |
+
|
| 124 |
+
with open(engine_path, "wb") as f:
|
| 125 |
+
f.write(serialized_engine)
|
| 126 |
+
print(f"✅ TensorRT engine saved at: {engine_path}")
|
| 127 |
+
|
| 128 |
+
|
| 129 |
+
def main():
|
| 130 |
+
# Paths
|
| 131 |
+
model_path = 'water_segmentation_model.pth'
|
| 132 |
+
onnx_path = 'water_segmentation_model.onnx'
|
| 133 |
+
engine_path = 'water_segmentation_model.engine'
|
| 134 |
+
|
| 135 |
+
# Load PyTorch model
|
| 136 |
+
model = UNet()
|
| 137 |
+
model.load_state_dict(torch.load(model_path))
|
| 138 |
+
model.cuda()
|
| 139 |
+
|
| 140 |
+
# Convert to ONNX
|
| 141 |
+
convert_to_onnx(model, (1, 3, 256, 256), onnx_path)
|
| 142 |
+
|
| 143 |
+
# Build TRT engine in Python
|
| 144 |
+
convert_to_tensorrt_py(onnx_path, engine_path)
|
| 145 |
+
|
| 146 |
+
|
| 147 |
+
if __name__ == '__main__':
|
| 148 |
+
main()
|
| 149 |
+
|