Open2

batchno_classid_score_x1y1x2y2 のNMS出力を使用して画像から複数のROIを抽出して固定サイズにリサイズ後にスタックするONNX処理の模索

PINTOPINTO
make_Loop_nms.py
#! /usr/bin/env python

import torch
import torch.nn as nn
import torch.nn.functional as F
import numpy as np
import onnx
from onnxsim import simplify
import numpy as np
np.random.seed(0)


class Model(nn.Module):
    def __init__(
        self,
    ):
        super(Model, self).__init__()

        self.resize_height = 128
        self.resize_width = 64

    def forward(self, image: torch.Tensor, nms_output: torch.Tensor):
        break_idx = nms_output.shape[0]
        elements = nms_output.shape[1]
        n, c, h, w = image.shape
        # batchno_classid_score_x1y1x2y2
        result_tensor = torch.zeros([break_idx, 3, self.resize_height, self.resize_width])
        for counter in range(break_idx):
            batch = nms_output[counter, 0].to(torch.int64)
            classid = nms_output[counter, 1].to(torch.int64)
            score = nms_output[counter, 2]
            x1 = (nms_output[counter, 3] * w).to(torch.int64)
            y1 = (nms_output[counter, 4] * h).to(torch.int64)
            x2 = (nms_output[counter, 5] * w).to(torch.int64)
            y2 = (nms_output[counter, 6] * h).to(torch.int64)
            partial_image = image[:, :, y1:y2, x1:x2]
            resized_partial_image = \
                F.interpolate(
                    input=partial_image,
                    size=(self.resize_height, self.resize_width),
                    mode='bilinear',
                )
            result_tensor[counter:counter+1, ...] = resized_partial_image
        return result_tensor

def generate_tensor():
    # [3, 7] 形状のテンソル初期化
    tensor = torch.empty(3, 7)
    # batchnoとclassidにランダムな実数を割り当て (ここでは範囲を0.0から10.0、0.0から5.0とする)
    tensor[:, 0] = torch.randint(0, 11, (3,)).float()  # batchno
    tensor[:, 1] = torch.randint(0, 6, (3,)).float()    # classid
    # scoreに0.1から1.0のランダムな実数を割り当て
    tensor[:, 2] = 0.9 * torch.rand(3) + 0.1
    # x1, x2 および y1, y2 に対してランダムな実数を割り当て、適切な条件 x1 < x2, y1 < y2 を満たすように並べ替え
    for i in range(3):
        x1, x2 = sorted(0.9 * torch.rand(2) + 0.1)
        y1, y2 = sorted(0.9 * torch.rand(2) + 0.1)
        tensor[i, 3] = x1
        tensor[i, 4] = y1
        tensor[i, 5] = x2
        tensor[i, 6] = y2
    return tensor

if __name__ == "__main__":
    OPSET=13
    MODEL = f'NMS_Loop'
    model = Model()
    onnx_file = f"{MODEL}_{OPSET}.onnx"

    image = torch.randn([1, 3, 480, 640], dtype=torch.float32)
    # batchno_classid_score_x1y1x2y2
    nms_output = generate_tensor()
    torch.onnx.export(
        torch.jit.script(model),
        args=(image, nms_output),
        f=onnx_file,
        opset_version=OPSET,
        input_names=[
            f'input_image',
            f'input_batchno_classid_score_x1y1x2y2',
        ],
        output_names=[
            f'output_roi',
        ],
        dynamic_axes={
            f'input_batchno_classid_score_x1y1x2y2': {0: 'N'},
            f'output_roi': {0: 'N', 1: '3', 2: str(model.resize_height), 3: str(model.resize_width)},
        },
    )
    model_onnx1 = onnx.load(onnx_file)
    model_onnx1 = onnx.shape_inference.infer_shapes(model_onnx1)
    onnx.save(model_onnx1, onnx_file)
    model_onnx2 = onnx.load(onnx_file)
    model_simp, check = simplify(model_onnx2)
    onnx.save(model_simp, onnx_file)