This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[参考译文] SK-AM62A-LP:在生成模型工件后运行推理脚本时出现问题

Guru**** 1788580 points
请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/processors-group/processors/f/processors-forum/1411919/sk-am62a-lp-problem-running-inference-script-after-model-artifact-generation

器件型号:SK-AM62A-LP

工具与软件:

大家好、我为使用 RESNET 50的 ONNX 模型(补丁实现)生成了模型工件。  

现在、每当我在电路板上运行以下推理脚本时、尝试使用 TIDL 加速器:  

我收到此错误:  
2024年09月05日03:56:32.346482125 [W:onnxruntime:、execution_FRAME.cc:835 VerifyOutputSize]来自{11024、14}模型的预期形状与 OUTPUT.332的{1、1、11024、14}实际形状不匹配

我不知道为什么会发生这种情况、因为我知道在生成模型工件时会添加这些额外的尺寸。 我有一个为不同的应用运行具有类似尺寸的 tflite 模型、不知道问题出在这里。

import os
import cv2
import numpy as np
import torch
from torchvision import transforms
import onnxruntime as ort
import faiss
from PIL import Image
from scipy.ndimage import gaussian_filter
import gi
import time

gi.require_version('Gst', '1.0')
from gi.repository import Gst

# Import necessary components from train.py
from train import embedding_concat, reshape_embedding, min_max_norm, cvt2heatmap, heatmap_on_image, get_args

# Define transforms (ensure these match those used in train.py)
data_transforms = transforms.Compose([
    transforms.Resize((224, 224), Image.LANCZOS),  # Reduced resolution
    transforms.ToTensor(),
    transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
inv_normalize = transforms.Normalize(
    mean=[-0.485 / 0.229, -0.456 / 0.224, -0.406 / 0.225],
    std=[1 / 0.229, 1 / 0.224, 1 / 0.225]
)

def gstreamer_pipeline():
    return (
        'v4l2src device=/dev/video3 io-mode=dmabuf-import ! '
        'video/x-bayer, width=640, height=480, framerate=15/1, format=rggb10 ! '
        'tiovxisp sink_0::device=/dev/v4l-subdev2 sensor-name="SENSOR_SONY_IMX219_RPI" '
        'dcc-isp-file=/opt/imaging/imx219/linear/dcc_viss_10b_640x480.bin sink_0::dcc-2a-file=/opt/imaging/imx219/linear/dcc_2a_10b_640x480.bin '
        '! video/x-raw, format=NV12, width=640, height=480, framerate=15/1 ! '
        'videoconvert ! video/x-raw, format=BGR ! appsink'
    )

def heatmap_on_image(heatmap, image, alpha=0.5, colormap=cv2.COLORMAP_JET):
    if heatmap.shape != image.shape:
        heatmap = cv2.resize(heatmap, (image.shape[1], image.shape[0]))
    heatmap = cv2.applyColorMap(np.uint8(heatmap), colormap)
    overlay = cv2.addWeighted(heatmap, alpha, image, 1 - alpha, 0)
    return overlay

def main():
    # Initialize GStreamer
    Gst.init(None)

    # Timing model load
    start_time = time.time()
    
    # Path to the ONNX model file
    onnx_model_path = '/opt/edgeai-tidl-artifacts/cl-ort-patchcore/patchcore_model.onnx'

    options = {
        'artifacts_folder': '/opt/edgeai-tidl-artifacts/cl-ort-patchcore'
    }

    so = ort.SessionOptions()
    
    # Specify execution providers with TIDL configuration
    ep_list = ['TIDLExecutionProvider', 'CPUExecutionProvider']
    
    # Load the ONNX model with TIDL acceleration
    ort_session = ort.InferenceSession(onnx_model_path, providers=ep_list, provider_options=[options, {}], sess_options=so)

    model_load_time = time.time() - start_time
    print(f"Model loading time: {model_load_time:.4f} seconds")

    # Get input and output details
    input_name = ort_session.get_inputs()[0].name
    output_names = [output.name for output in ort_session.get_outputs()]

    # Get arguments
    args = get_args()

    # Update the dataset path to your actual path on the board
    args.dataset_path = '/opt/edgeai-gst-apps/PatchCore_anomaly_detection'
    args.category = 'bottle'  # Ensure this is set to the correct category

    # Load the FAISS index
    start_time = time.time()
    index_path = os.path.join(args.dataset_path, 'embeddings', args.category, 'index.faiss')
    index = faiss.read_index(index_path)
    if torch.cuda.is_available():
        res = faiss.StandardGpuResources()
        index = faiss.index_cpu_to_gpu(res, 0, index)
    faiss_load_time = time.time() - start_time
    print(f"FAISS index loading time: {faiss_load_time:.4f} seconds")

    # Function to run inference on ONNX model
    def run_onnx_inference(ort_session, input_data):
        start_time = time.time()
        outputs = ort_session.run(output_names, {input_name: input_data})
        inference_time = time.time() - start_time
        print(f"Model inference time: {inference_time:.4f} seconds")
        return outputs

    # Initialize video capture with GStreamer pipeline
    cap = cv2.VideoCapture(gstreamer_pipeline(), cv2.CAP_GSTREAMER)

    if not cap.isOpened():
        print("Error: Unable to open video source.")
        return

    frame_count = 0
    total_processing_time = 0

    while cap.isOpened():
        start_time = time.time()
        ret, frame = cap.read()
        if not ret:
            break

        frame_read_time = time.time() - start_time
        print(f"Frame read time: {frame_read_time:.4f} seconds")

        # Preprocess frame
        start_time = time.time()
        pil_img = Image.fromarray(cv2.cvtColor(frame, cv2.COLOR_BGR2RGB))
        input_tensor = data_transforms(pil_img).unsqueeze(0).numpy().astype(np.float32)
        preprocessing_time = time.time() - start_time
        print(f"Frame preprocessing time: {preprocessing_time:.4f} seconds")

        # Run ONNX inference
        start_time = time.time()
        features = run_onnx_inference(ort_session, input_tensor)

        inference_time = time.time() - start_time

        # Convert features to tensors
        start_time = time.time()
        features = [torch.tensor(f) for f in features]

        # Extract embeddings and perform the same steps as in the test_step
        embeddings = []
        for feature in features:
            m = torch.nn.AvgPool2d(3, 1, 1)
            embeddings.append(m(feature))
        embedding_ = embedding_concat(embeddings[0], embeddings[1])
        embedding_test = np.array(reshape_embedding(np.array(embedding_)))
        feature_extraction_time = time.time() - start_time
        print(f"Feature extraction time: {feature_extraction_time:.4f} seconds")

        # Search the FAISS index
        start_time = time.time()
        score_patches, _ = index.search(embedding_test, k=args.n_neighbors)
        faiss_search_time = time.time() - start_time
        print(f"FAISS search time: {faiss_search_time:.4f} seconds")

        # Postprocess anomaly map
        start_time = time.time()
        anomaly_map = score_patches[:, 0].reshape((28, 28))
        N_b = score_patches[np.argmax(score_patches[:, 0])]
        w = (1 - (np.max(np.exp(N_b)) / np.sum(np.exp(N_b))))
        score = w * max(score_patches[:, 0])  # Image-level score

        anomaly_map_resized = cv2.resize(anomaly_map, (224, 224))
        anomaly_map_resized_blur = gaussian_filter(anomaly_map_resized, sigma=2)  # Reduced sigma for faster processing

        anomaly_map_norm = min_max_norm(anomaly_map_resized_blur)
        anomaly_map_norm_hm = cvt2heatmap(anomaly_map_norm * 255)
        anomaly_map_norm_hm_resized = cv2.resize(anomaly_map_norm_hm, (frame.shape[1], frame.shape[0]))
        heatmap_overlay_time = time.time() - start_time
        print(f"Heatmap overlay time: {heatmap_overlay_time:.4f} seconds")

        hm_on_img = heatmap_on_image(anomaly_map_norm_hm_resized, frame, alpha=0.3)  # More transparent overlay
	        # Display result
        start_time = time.time()
        cv2.imshow('Anomaly Detection', hm_on_img)
        display_time = time.time() - start_time
        print(f"Display time: {display_time:.4f} seconds")

        frame_processing_time = time.time() - start_time
        total_processing_time += frame_processing_time
        frame_count += 1
        print(f"Frame processing time: {frame_processing_time:.4f} seconds")

        if cv2.waitKey(1) & 0xFF == ord('q'):
            break

    cap.release()
    cv2.destroyAllWindows()

    average_processing_time = total_processing_time / frame_count if frame_count else 0
    print(f"Average frame processing time: {average_processing_time:.4f} seconds")

if __name__ == '__main__':
    main()

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您好!
    我理解这里的警告(在本例中可以安全地忽略、但在某些情况下会产生错误)。 请在调用 Linux 环境中设置 TIDL_RT_ONNX_VARDIM=1。

    导出 TIDL_RT_ONNX_VARDIM=1


    TIDL 在所有光学传感器上内部使用6维。 这通常意味着将单个轴添加到基础数据对象中。 ONNX 抱怨这一点。 无论出于何种原因、TFLite 都不支持。 我上面提到的环境变量将强制运行时在返回到 ONNX 时删除这些单个轴。

    这曾经在 osrt_python 页面的文档中、但已被删除。 让我看看如何解决这个问题,以避免未来的混淆

    BR、
    Reese
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好!  

    非常感谢您的答复:)  

    我还想问一下 GitHub 上提供的模型工件生成脚本、它是否仅为一个输出(最终节点)生成工件?  

    因为我的脚本包含两个输出、其中一个来自中间层。
    所以,当我运行这个代码行:   

    output_names =[ output.name for output in ort_session.get_outputs()]

    我得到的 output_name 是["input.128"、"input.332"]  

    但是当我运行这个代码行时:  

    输出= ort_session.run(output_names、{input_name:input_data})

    我获得的输出为[None、array (valid)]。  

    我如何为这两个输出生成它? 谢谢你




  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好!

    很高兴为您提供帮助!

    由于我的脚本包含两个输出、其中一个输出来自中间层。
    [报价]

    我遇到了中间节点用作输出的问题。  在模型导入/编译过程中是否存在任何错误警告或指示? 在编译过程中、您可以通过 在传递给 onruntime_options 的集合中传递"debug_level=2"来获得更详细的输出日志。 InferenceSession。 如果您使用的是 edgeai-tidl-tools、也可以在 examples/osrt_python/common_utils.py 中进行更改  

    解决此问题的一种方法是添加一个基本节点(例如 Identity)、以有效地缓冲中间节点所需的输出。  

    希望这对您有所帮助!

    BR、

    Reese

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    你好,谢谢你的答复。  

    否、我在模型导入/编译期间没有收到任何错误。  

    我试图确定此问题是由什么引起的、它是否可以来自  onnx_model_opt.py 文件?  

    谢谢你

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好!

    否、此问题更可能发生在模型编译/导入工具正在执行的操作内部。 如果您可以、请分享您的工件目录。

    可以从 onnxrtMetaData.txt 中检查 TIDL 正在使用的输出数量。 您还可以通过查看包含 artifacts/tempDir 子目录的 SVG 文件来可视化模型的解析方式。 如果在浏览器中打开、将鼠标悬停在节点上将显示其他信息。 我建议对也要将其视为输出的中间节点执行此操作。

    编辑:此主题已分为以下主题。 我将结束该主题、新主题中将提供更多回复

    -e2e.ti.com/.../sk-am62a-lp-problem-with-onnx-model-artifact-generation

    -Reese

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    你好,谢谢你的答复。

    我已经检查了  onnxrtMetaData.txt、 由于某种原因它只接受一个输出。  

    以下是模型工件文件夹的链接: https://drive.google.com/drive/folders/18FYxpObW7Rp6MInwUvXbfr0VWB9e-RBj?usp=sharing

    谢谢你:)

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    回复发布在以下主题中: https://e2e.ti.com/support/processors-group/processors/f/processors-forum/1412653/sk-am62a-lp-problem-with-onnx-model-artifact-generation