사용 모델

https://github.com/cfzd/Ultra-Fast-Lane-Detection Culane DataSheet (culane_18.pth) 사용

Npu에 모델 올려서 추론 하는 법 - topst.ai 문서 참조

https://topst.ai/tech/docs?page=754cd4fd74aa7f89d0f2491636bf389fea1eabe3

딥러닝 모델을 보드에서 돌리기 까지의 과정

*PyTorch(.pth) → ONNX(.onnx) → NPU 변환 → 보드 실행(tc-nn-app)

  1. .pth 파일을 .onnx 파일로 변환하기 - PyTorch에서 학습된 .pth 모델은 보드에서 바로 못 쓰고, Telechips TOPST AI-G 보드의 NPU 컨버터는 ONNX 형식을 입력으로 받음
//Colab

!pip install onnx onnxruntime

from google.colab import files
uploaded = files.upload() 

import torch
import torch.nn as nn
import torch.nn.functional as F
import torchvision.models as models

class parsingNet(nn.Module):
    def __init__(self, pretrained=False, backbone='18', cls_dim=(18, 200, 4), use_aux=False):
        super(parsingNet, self).__init__()
        self.use_aux = use_aux
        self.cls_dim = cls_dim
        self.total_dim = int(torch.prod(torch.tensor(cls_dim)))

        if backbone == '18':
            self.model = models.resnet18(pretrained=pretrained)
        elif backbone == '34':
            self.model = models.resnet34(pretrained=pretrained)
        else:
            raise NotImplementedError

        self.model = nn.Sequential(*list(self.model.children())[:-2])

        self.fc = nn.Sequential(
            nn.Conv2d(512, 256, kernel_size=1),
            nn.ReLU(),
            nn.Conv2d(256, self.total_dim, kernel_size=1)
        )

    def forward(self, x):
        x = self.model(x)        # backbone feature
        x = self.fc(x)           # (B, total_dim, H, W)
        x = F.avg_pool2d(x, x.shape[2:])  # GAP
        x = x.view(-1, *self.cls_dim)
        return x

cls_num_per_lane = 200
num_row = 18
num_lane = 4

net = parsingNet(
    pretrained=False,
    backbone='18',
    cls_dim=(num_row, cls_num_per_lane, num_lane),
    use_aux=False
)

pth_path = "culane_18.pth"
state_dict = torch.load(pth_path, map_location="cpu")
net.load_state_dict(state_dict, strict=False)
net.eval()

dummy_input = torch.randn(1, 3, 288, 800)

onnx_path = "culane_18.onnx"
torch.onnx.export(
    net,
    dummy_input,
    onnx_path,
    input_names=["input"],
    output_names=["output"],
    dynamic_axes={"input": {0: "batch"}, "output": {0: "batch"}},
    opset_version=11
)

print("변환 완료: ", onnx_path)
  1. Converter
python ./EnlightSDK/converter.py ./input_networks/ufld_culane.onnx   --type unknown   --logistic softmax   --dataset Custom   --dataset-root ./my_dataset_path   --output ./output_networks/UFLD_final.enlight   --enable-track   --mean 0.485 0.456 0.406   --std 0.229 0.224 0.225   --num-class 4   --variance 0.1 0.2   --force-output Linear_1___cls_cls_2_Gemm
source ./venv/bin/activate
netron ./input_networks/ufld_culane.onnx

가상환경을 활성화한 뒤 netron 실행파일을 실행하면, 기본 웹브라우저에서 <http://localhost:8080> 주소가 열리면서 모델 구조를 Netron 뷰어로 확인할 수 있다.
** --force-output Linear_1___cls_cls_2_Gemm 옵션을 사용하면, 툴킷에서 지원하지 않는 Reshape 연산 직전 노드를 강제로 출력으로 지정하여 모델을 그 지점에서 끊을 수 있다. 

위의 명령어를 통해 output_networks 폴더 안에 UFLD_final.enlight 파일이 생긴것을 확인해 볼 수 있다.

Reshape 연산 직전 노드를 강제로 출력하는 이유는 미지원 연산이기 때문에 Quantizer 과정에서 오류가 뜨는 것을 확인해 볼 수 있다.