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:使用 gstreamer 流水线、脚本细分运行 python 脚本。

Guru**** 2487425 points


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

https://e2e.ti.com/support/processors-group/processors/f/processors-forum/1428192/sk-am62a-lp-running-python-script-using-gstreamer-pipeline-script-breakdown

器件型号:SK-AM62A-LP

工具与软件:

我尝试在电路板上运行以下代码、但我不使用 OpenCV GUI 窗口、而是使用带 kmssink 的 gstreamer 流水线直接显示输出帧。 下面是这个例子: https://github.com/TexasInstruments-Sandbox/edgeai-gst-apps-people-tracking 

import numpy as np
import tflite_runtime.interpreter as tflite  # Use tflite_runtime for TIDL delegate support
import faiss
import cv2
from PIL import Image
import os

MODEL_PATH = '/opt/edgeai-tidl-artifacts/cl-tfl-fomo-01/trained.tflite'
CAPTURED_IMAGES_DIR = './captured_frames'  # Directory to save captured frames
FAISS_INDEX_PATH = 'faiss_index.bin'
ANOMALY_THRESHOLD = 0.5

# Preprocess frame to match model input
def process_frame(frame, interpreter):
    img = Image.fromarray(cv2.cvtColor(frame, cv2.COLOR_BGR2RGB))
    input_details = interpreter.get_input_details()
    output_details = interpreter.get_output_details()
    input_shape = input_details[0]['shape']

    img_resized = img.resize([input_shape[1], input_shape[2]])
    np_frame = np.array(img_resized, dtype=np.float32) / 255.0
    np_frame = np.expand_dims(np_frame, axis=0)  # Add batch dimension

    interpreter.set_tensor(input_details[0]['index'], np_frame)
    interpreter.invoke()
    output_data = interpreter.get_tensor(output_details[0]['index'])
    return output_data

# Build the FAISS index using reference ("good") examples
def build_faiss_index(captured_images, interpreter, output_resolution=[12, 12]):
    first_example_response = process_frame(cv2.imread(captured_images[0]), interpreter)
    feature_dim = first_example_response.shape[-1]
    faiss_index = faiss.IndexFlatL2(feature_dim)

    for image_path in captured_images:
        response = process_frame(cv2.imread(image_path), interpreter)
        for i in range(output_resolution[0]):
            for j in range(output_resolution[1]):
                patch_features = response[0, i, j, :].reshape(1, -1)
                faiss_index.add(patch_features.astype(np.float32))

    return faiss_index

# Save FAISS index to disk
def save_faiss_index(faiss_index, index_path):
    faiss.write_index(faiss_index, index_path)

# Load FAISS index from disk
def load_faiss_index(index_path):
    return faiss.read_index(index_path)

# Compute anomaly scores using FAISS
def compute_anomaly_faiss(image_features, faiss_index, output_resolution):
    distances = np.zeros(output_resolution)
    for i in range(output_resolution[0]):
        for j in range(output_resolution[1]):
            f_vec = image_features[0, i, j, :].reshape(1, -1)
            distance, _ = faiss_index.search(f_vec, 1)
            distances[i, j] = distance[0][0]
    return distances

# GStreamer pipeline configuration for TI AM62A board
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 format-msb=9 ! '
        'video/x-raw, format=NV12, width=640, height=480, framerate=15/1 ! videoconvert ! video/x-raw, format=BGR ! appsink'
    )

# Webcam stream with training and inference functionality
def evaluate_fomo_stream(interpreter):
    cap = cv2.VideoCapture(gstreamer_pipeline(), cv2.CAP_GSTREAMER)
    captured_images = []

    faiss_index = None  # No FAISS index initially

    def capture_frame(event, x, y, flags, param):
        nonlocal captured_images
        if event == cv2.EVENT_LBUTTONDOWN:
            print("Capturing frame for training...")
            img_path = os.path.join(CAPTURED_IMAGES_DIR, f'captured_{len(captured_images)}.png')
            cv2.imwrite(img_path, frame)  # Save the frame without heatmap
            captured_images.append(img_path)
            print(f"Captured and saved: {img_path}")

    cv2.namedWindow("Anomaly Detection")
    cv2.setMouseCallback("Anomaly Detection", capture_frame)

    while True:
        ret, frame = cap.read()
        if not ret:
            print("Failed to grab frame")
            break

        # If we have enough images for training (say, 10), build FAISS index
        if len(captured_images) >= 10 and faiss_index is None:
            print("Building FAISS index with captured images...")
            faiss_index = build_faiss_index(captured_images, interpreter)
            save_faiss_index(faiss_index, FAISS_INDEX_PATH)
            print("FAISS index saved and inference mode is enabled.")

        if faiss_index is not None:
            image_feat = process_frame(frame, interpreter)
            anomaly_score = compute_anomaly_faiss(image_feat, faiss_index, [12, 12])

            global_anomaly_score = np.mean(anomaly_score)
            classification = 'Anomaly' if global_anomaly_score > ANOMALY_THRESHOLD else 'No Anomaly'

            anomaly_heatmap = cv2.resize(anomaly_score, (frame.shape[1], frame.shape[0]), interpolation=cv2.INTER_NEAREST)
            anomaly_heatmap_normalized = cv2.normalize(anomaly_heatmap, None, 0, 255, cv2.NORM_MINMAX)
            anomaly_heatmap_colored = cv2.applyColorMap(np.uint8(anomaly_heatmap_normalized), cv2.COLORMAP_JET)

            overlay_frame = cv2.addWeighted(frame, 0.6, anomaly_heatmap_colored, 0.4, 0)

            cv2.putText(overlay_frame, f'Anomaly Score: {global_anomaly_score:.2f}', (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 1,
                        (255, 255, 255), 2)
            cv2.putText(overlay_frame, f'Classification: {classification}', (10, 70), cv2.FONT_HERSHEY_SIMPLEX, 1,
                        (0, 0, 255) if classification == 'Anomaly' else (0, 255, 0), 2)

            cv2.imshow("Anomaly Detection", overlay_frame)
        else:
            cv2.imshow("Anomaly Detection", frame)

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

    cap.release()
    cv2.destroyAllWindows()

# Create a directory to save captured frames
if not os.path.exists(CAPTURED_IMAGES_DIR):
    os.makedirs(CAPTURED_IMAGES_DIR)

# Load the TFLite model with TIDL delegate support
tidl_delegate = [tflite.load_delegate('libtidl_tfl_delegate.so', {'artifacts_folder': '/opt/edgeai-tidl-artifacts/cl-tfl-fomo-01'})]
interpreter = tflite.Interpreter(model_path=MODEL_PATH, experimental_delegates=tidl_delegate)
interpreter.allocate_tensors()

# Start real-time anomaly detection with live training
evaluate_fomo_stream(interpreter)

但我对应该如何打破代码感到有点困惑。 我需要什么部分作为一个预或后处理,特别是如何可以做鼠标点击功能10次点击图片,然后使用它们来生成和保存传真索引。 如何创建 gstreamer 流水线(我甚至必须手动创建该流水线、还是使用上面的示例自动生成该流水线?)、通过示例中的脚本已处理了流水线的哪些部分? 我想使用 OptiFlow、以便流水线不会变慢。 如果您能帮助我细分我需要的类/文件/流水线、那就太好了。

下面是我创建的配置 YAML 文件的链接、您能否告诉我是否可以用于此目的?  drive.google.com/.../view

谢谢你  

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

    Pragya、您好!

    很高兴能提供帮助。  Linux Edgeai SDK 文档提供了有关设置 edgeai-gst-apps 的详细信息。  https://software-dl.ti.com/processor-sdk-linux/esd/AM62AX/10_00_00/exports/edgeai-docs/common/sdk_overview.html

    Unknown 说:
    但我对应该如何分解代码有点困惑。 作为前期或后期流程、我需要哪些器件[/QUOT]

    edgeai-gst-apps 负责与图像采集、预处理、模型初始化和推理以及显示相关的所有功能。 它还提供简单的后处理功能、您可以针对自己的应用进行扩展。 有关管道的示例、请参阅此链接: https://software-dl.ti.com/processor-sdk-linux/esd/AM62AX/10_00_00/exports/edgeai-docs/common/edgeai_dataflows.html#object-detection

    POST 过程在 https://github.com/TexasInstruments-Sandbox/edgeai-gst-apps-people-tracking/blob/main/apps_python/post_process.py#L357文件中实现。您可以看到、在第357行、将为与人员跟踪演示相关的后处理工作创建一个新类。 请注意、在这种情况下、POST 过程负责对图片进行批注、还可以使用仪表板生成整个显示屏。  

    [quote userid="622655" url="~/support/processors-group/processors/f/processors-forum/1428192/sk-am62a-lp-running-python-script-using-gstreamer-pipeline-script-breakdown 如何创建 gstreamer 流水线(我是否需要手动创建或者是否使用以上示例自动生成?)、通过示例中的脚本已经处理了流水线的哪些部分?

    根据 YAML 文件为您生成 gstreamer 流水线。 有关设置 YAML 文件的详细信息、请参阅文档的以下部分: https://software-dl.ti.com/processor-sdk-linux/esd/AM62AX/10_00_00/exports/edgeai-docs/common/configuration_file.html。 

    Unknown 说:
    我想使用 OptiFlow、以便流水线不慢。

    OpTIFlow 的速度非常快、因为它 使用 gstreamer 插件来调用模型推理和后处理。 这些插件已针对预定义类型的后处理(分类、检测和分段)进行了编译。 将 OptiFlow 用于任何其他后处理都需要编辑和编译插件。  为 OptiFlow 生成管道的说明如下: https://software-dl.ti.com/processor-sdk-linux/esd/AM62AX/10_00_00/exports/edgeai-docs/common/sample_apps.html?highlight=optiflow#optiflow。请注意、上面链接中的脚本输入是相同的 YAML 文件。  

    Unknown 说:
    如果您能帮我细分我需要的类/文件/流水线、那就太棒了。

    按照本课程中的代码将 POST 过程更改为所需内容。  https://github.com/TexasInstruments-Sandbox/edgeai-gst-apps-people-tracking/blob/main/apps_python/post_process.py#L357

    Unknown 说:
    特别是我可以如何执行鼠标点击功能10次来点击图片,然后使用它们来生成和保存传真索引。

    edgeai-gst-apps 不支持鼠标功能。 我建议在设计项目时不需要鼠标。 否则、您可以查看基于 QT 构建的开箱即用 GUI 示例。 此项目的源代码可从以下位置获得: https://git.ti.com/cgit/apps/edgeai-gui-app/。请注意、这是一个静态 GUI 应用程序、用于方便地运行开箱即用演示、这些演示是 gstreamer 应用程序的集合。

    此致、

    Qutaiba

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

    你好,谢谢你的答复。  

    您提到 edgeai-gst-apps 不支持鼠标功能,那么从连接的键盘的键功能是什么?  

    另外、该脚本中是否可以在 AI 加速器上同时部署和运行两个模型?  

    谢谢你。  

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

    Pragya、您好!

    您提到 edgeai-gst-apps 不支持鼠标功能、那么连接的键盘的键功能可能是什么?

    这里的限制因素是 GUI 渲染、而不是硬件。 因此使用键盘是 一个很好的选择。 您可以使用连接到 EVM 的完整 USB 键盘、也可以使用自定义键盘并通过 GPIO: https://github.com/TexasInstruments/ti-gpio-py 进行连接。 

    此外、脚本中是否可以在 AI 加速器上同时部署和运行两个模型?  
    [报价]

    是的、可以在 AI 加速器上同时运行多个模型。 请参阅此处 edgeai-gst-apps 中的示例: https://github.com/TexasInstruments/edgeai-gst-apps/blob/main/configs/multi_input_multi_infer.yaml。 此处说明数据流: https://software-dl.ti.com/processor-sdk-linux/esd/AM62AX/10_00_00/exports/edgeai-docs/common/edgeai_dataflows.html#single-input-multi-inference 

    此致、

    Qutaiba

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

    好的,所以回过头来的问题:键盘功能的点击图片,并生成和存储的传真索引,然后将是预处理的一部分,还是不是? 而指标比较部分和分数和热图生成将是后处理的权利吗?  

    另外、我想问一下是否可以在 AI 加速器上部署 tf 或 ONNx 模型、而无需为其生成模型事实?  

    谢谢你

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

    Pragya、您好!

    简言之、可以是、任何在 ML 推理之后的功能都可以在后处理过程中实现。 我想强调的是、根据这些过程的复杂性和时间消耗、您可能希望使用多线程来平衡负载、并避免延迟显示注释的帧。  

    此致、

    Qutaiba

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

    您好!  

    但我想理解的是、单击(10)个图像然后将它们传递到模型以提取特征、这需要进行正确的预处理、因为在这里、流媒体和图像点击会在传递到模型之前发生? 该功能应包含在 edgeai GST 应用的哪些文件中?

    另外、我想问一下是否可以在 AI 加速器上部署 tf 或 ONNx 模型、而无需为其生成模型事实?  

    谢谢!
    Pragya

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

    Pragya、您好!

    预处理可以在 infer_pipe.py 文件中实现/调用。 以下是有关此文件流程的一些注意事项:

    您要求的是 在将图片发送至 ML 推理之前、按照您想要选择图片的方式进行预处理。 但是、您必须先显示它们、以便用户可以查看并决定要选择的内容。 在这种情况下、edgeai-gst-apps 不直接适用于您的用例。 该应用假设从摄像头到推理再到后处理再显示的帧是连续的。 除了后处理步骤之外、此流程中没有干扰。 您将必须进行一些更改才能实现所需的功能。  

    现在、我想了解您想要实现的确切功能。 我的理解是、您希望看到从摄像头到监视器的有争议的直播流。 用户可以按键盘上的某个键来选择要发送到 ML 推理的帧。 该推理的结果保存在文件中。 是这样吗? 如果是这种情况、那么您不连续进行 ML 推理并为用户显示注释的帧、然后用户仍然可以按键盘上的某个键来存储该帧、这是什么? 在这种情况下、按键将进入"postprocess (后处理)"步骤。  

    此致、

    Qutaiba

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

    您好!  

    1.所以我想做的是有一个 有争议的直播从相机到显示器。 用户通过点击键盘上的键来选择10个帧、只有这10个帧传递给模型、以便输出保存到文件(索引)中。 执行此过程后、每一帧都流经模型、并与保存在文件中的输出(通过这10帧生成)进行比较、同时生成热图以检测异常。 希望这是明确的。  

    2.我想您之前忽略了一些问题、但是 在 AI 加速器上部署 tf 或 ONNx 模型、而不生成模型的事实吗?  

    3.在模型动物园是可以有我的模型和它的文物的这种格式(由你的脚本生成): https://drive.google.com/drive/folders/1hNAvUqlz3-oJ4WNqRDZebvilGTG3Rf5w?usp=drive_link 或我需要他们在这里提到的格式: https://software-dl.ti.com/jacinto7/esd/processor-sdk-linux-sk-tda4vm/09_02_00/exports/edgeai-docs/common/inference_models.html

    谢谢你。  

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

    Pragya、您好!

    感谢您解释有关您的项目的更多详细信息。 如果您不希望所有帧都由 ML 处理、我建议您编辑 infer_pipe.py 文件以直接在屏幕上显示帧、并根据客户按键决定要由 ML 处理的帧。显然、您在此处尝试实现的功能不会直接映射到 edgeai-gst-apps 项目、但您可以将其用作起点。  

    我想您之前错过了一些问题、但 是否可以在 AI 加速器上部署 tf 或 onnx 模型、而无需为其生成模型实况?  [报价]

    我漏掉了该器件。 答案是否定的 您 必须编译模型并生成工件、才能将其卸载到 AI 加速器。  

    n 模型动物园是可以有我的模型和它的文物这种格式(由你的脚本生成):

    您在 google drive 文件夹中共享的工件看起来很好。 您试过吗?  

    此致、

    Qutaiba

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

    您好!  

    我尝试运行一切(python ./ app_edgeai.py ../configs/anomaly_detection.yaml ), 我得到这个输出:  


    子图的数量:1、24个节点中委派的24个节点

    应用程序:初始化...!!!
    内存:初始化...!!!
    MEM:已初始化的 DMA 堆(FD=6)!!!
    内存:初始化...完成!!!
    IPC:初始化...!!!
    IPC:初始化...完成!!!
    remote_servic: init…!!
    Remote_servic:初始化...完成!!!
    114.118990s:GTC 频率= 200 MHz
    应用程序:初始化...完成!!!
    114.121339 s:vx_zone_init:Enabled
    114.121381 s:vx_zone_error:Enabled
    114.121391 s:vx_zone_warning:Enabled
    114.123672 s:vx_zone_init:[tivxInitLocal:130]初始化已完成!!
    114.125239 s:vx_zone_init:[tivxHostInitLocal:101]主机初始化已完成!!!
    ==== [输入流水线(S)]====

    [PIPE-0]

    v4l2src device=/dev/video3 IO-mode=5 pixel-Aspect-ratio=无! 队列泄漏=2! capsfilter caps="video/x-bayer, width=(int)640, height=(int)480, format=(string)rggb;"! tiovxisp dcc-isp-file=/opt/imaging/imx219/linear/dcc_viss.bin sensor-name=sensor_Sony_IMX219_RPI! capsfilter caps="video/x-raw、format=(string) NV12;"! tiovxmultiscaler name=split_01
    SPLIT_01。 ! 队列! capsfilter caps="video/x-raw、width=(int)640、height=(int)480;"! tiovxdlcolorconvert out-pool-size=4! capsfilter caps="video/x-raw、format=(string) rgb;"! appsink max-buffers=2 dropp=True name=sen_0
    SPLIT_01。 ! 队列! capsfilter caps="video/x-raw、width=(int)384、height=(int)288;"! tiovxmultiscaler target=1! capsfilter caps="video/x-raw、width=(int)128、height=(int)96;"! tiovxdlcolorconvert out-pool-size=4! capsfilter caps="video/x-raw、format=(string) rgb;"! videobox QoS =真左=16右=16 ! tiovxdlpreproc out-pool-size=4 channel-order=1! capsfilter caps="application/x-tensor-tiovx;"! appsink max-buffers=2 dropp=True name=pre_0


    ==== [输出流水线]====

    appsrc DO-timestamp=True format=3 block=True name=post_0! tiovxdlcolorconvert ! capsfilter caps="video/x-raw、format=(string) NV12、width=(int) 640、height=(int) 480;"! 队列! mosaic_0.sink_0

    tiovxmosaic target=1 background=/tmp/background_0 name=mosaic_0 src::pool-size=4
    Sink_0::startx="<0>" Sink_0:starty="<0>" Sink_0::width="<640>" Sink_0::heights="<480>"
    ! capsfilter caps="video/x-raw、format=(string) NV12、width=(int) 640、height=(int) 480;"! 队列! tiperfoverlay title=异常检测! kmssink sync=False 最大延迟=5000000 QoS =真正的处理-最后期限=15000000 driver-name=tidss connector-id=40 plane-id=31 force-modesetting=True



    |异常检测|++--------------- ++------------------ +|输入 src:/dev/video3 |型号名称:CL-TFL-FOMOO-01 |型号类型:分类|+/--------- ++------------------ ++------------------ +|异常检测|+------------------------------------------------------- ++------------------ +|输入 src:/dev/video3 |型号名称:CL-TFL-FOMOO-01 |型号类型:分类|+/--------- ++------------------

    屏幕不显示任何内容、仅显示主页

    但我也得到错误:错误从 GST 管道拉张量。  

    这是我的 param.yaml 文件:  

    postprocess:
      data_layout: NHWC
    preprocess:
      crop:
      - 96
      - 96
      data_layout: NHWC
      mean:
      - 0
      - 0
      - 0
      resize:
      - 96
      - 96
      scale:
      - 0.003921569790691137
      - 0.003921569790691137
      - 0.003921569790691137
      reverse_channels: false
    session:
      artifacts_folder: ''
      model_folder: model
      model_path: trained.tflite
      session_name: tflitert
      input_data_layout: NHWC
      input_details:
      - name: "serving_default_x:0"  
        type: <class 'numpy.float32'>
        shape:
        - 1
        - 96
        - 96
        - 3
      input_optimization: True
      output_details:
      - name: "StatefulPartitionedCall:0"  
        type: <class 'numpy.float32'>
        shape:
        - 1
        - 12
        - 12
        - 96
    target_device: AM62A
    task_type: anomaly_detection



    这是我新的 postprocess 类:  
    class PostProcessAnomalyDetection(PostProcess):
        def __init__(self, flow):
            super().__init__(flow)
            self.captured_images = []
            self.faiss_index = None
    
            if not os.path.exists(CAPTURED_IMAGES_DIR):
                os.makedirs(CAPTURED_IMAGES_DIR)
    
        def __call__(self, frame, results):
            image_feat = results
    
            # Check for keyboard input to save the frame
            key = cv2.waitKey(1) & 0xFF
            if key == ord('s'):  # Press 's' key to save frame
                img_path = os.path.join(CAPTURED_IMAGES_DIR, f'captured_{len(self.captured_images)}.png')
                cv2.imwrite(img_path, frame)
                self.captured_images.append(img_path)
                print(f"Captured and saved: {img_path}")
    
            # Build FAISS index once we have enough images
            if len(self.captured_images) >= 10 and self.faiss_index is None:
                print("Building FAISS index with captured images...")
                self.faiss_index = self.build_faiss_index()
                print("FAISS index saved and ready for inference.")
    
            # Only compute anomaly score and generate heatmap if FAISS index is available
            if self.faiss_index is not None:
                anomaly_score = self.compute_anomaly_score(image_feat)
                global_anomaly_score = np.mean(anomaly_score)
                classification = 'Anomaly' if global_anomaly_score > ANOMALY_THRESHOLD else 'No Anomaly'
    
                # Generate and display heatmap overlay
                overlay_frame = self.generate_heatmap_overlay(frame, anomaly_score, global_anomaly_score, classification)
                cv2.imshow("Anomaly Detection", overlay_frame)
            else:
                # Display raw frame if FAISS index is unavailable
                cv2.imshow("Anomaly Detection", frame)
    
            return frame
    
        def build_faiss_index(self, output_resolution=[12, 12]):
            first_example_response = self.process_frame_for_features(cv2.imread(self.captured_images[0]))
            feature_dim = first_example_response.shape[-1]
            faiss_index = faiss.IndexFlatL2(feature_dim)
    
            for image_path in self.captured_images:
                response = self.process_frame_for_features(cv2.imread(image_path))
                for i in range(output_resolution[0]):
                    for j in range(output_resolution[1]):
                        patch_features = response[0, i, j, :].reshape(1, -1)
                        faiss_index.add(patch_features.astype(np.float32))
    
            faiss.write_index(faiss_index, FAISS_INDEX_PATH)
            return faiss_index
    
        def compute_anomaly_score(self, image_features, output_resolution=[12, 12]):
            distances = np.zeros(output_resolution)
            for i in range(output_resolution[0]):
                for j in range(output_resolution[1]):
                    f_vec = image_features[0, i, j, :].reshape(1, -1)
                    distance, _ = self.faiss_index.search(f_vec, 1)
                    distances[i, j] = distance[0][0]
            return distances
    
        def generate_heatmap_overlay(self, frame, anomaly_score, global_anomaly_score, classification):
            anomaly_heatmap = cv2.resize(anomaly_score, (frame.shape[1], frame.shape[0]), interpolation=cv2.INTER_NEAREST)
            anomaly_heatmap_normalized = cv2.normalize(anomaly_heatmap, None, 0, 255, cv2.NORM_MINMAX)
            anomaly_heatmap_colored = cv2.applyColorMap(np.uint8(anomaly_heatmap_normalized), cv2.COLORMAP_JET)
    
            overlay_frame = cv2.addWeighted(frame, 0.6, anomaly_heatmap_colored, 0.4, 0)
            cv2.putText(overlay_frame, f'Anomaly Score: {global_anomaly_score:.2f}', (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 1,
                        (255, 255, 255), 2)
            cv2.putText(overlay_frame, f'Classification: {classification}', (10, 70), cv2.FONT_HERSHEY_SIMPLEX, 1,
                        (0, 0, 255) if classification == 'Anomaly' else (0, 255, 0), 2)
            return overlay_frame


    这是我的异常检测.yaml
    title: "Anomaly Detection"
    log_level: 2
    inputs:
        input0:
            source: /dev/video-rpi-cam0
            subdev-id: /dev/v4l-rpi-subdev0
            width: 640
            height: 480
            format: rggb
            framerate: 30
    
    models:
        model0:
            model_path: /opt/model_zoo/cl-tfl-fomo-01
    
    outputs:
        output0:
            sink: kmssink
            width: 640
            height: 480
            format: NV12
            overlay-perf-type: graph
    
    flows:
        flow0: [input0,model0,output0,[0,0,640,480]]
    


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

    Pragya、您好!

     这里有多个变量可能会出错。 我建议 一次迈出这一步。 首先、我想问:

    • 我在您的异常_detection.yaml 中看到、您正在使用/dev/video-rpi-cam0作为输入、但您共享的 gstreamer 流水线正在尝试连接到/dev/video3. 这是您想要使用的正确摄像头吗?
    • 此摄像机是否支持640x480? 请记住、硬件多标量加速器将处理任何缩放任务、以便您可以使用摄像机的实际分辨率。  
    • 输出设置为640x480、您的显示器是否支持此分辨率?
    • 在您的 python 代码中、您将使用 CV2.waitkey (1)函数。 您是否在单独的测试脚本中尝试过此函数以确保它实际有效? 我用于将硬件键盘连接到 EVM 的方法是 evdev。 如果尝试使用主机上的键盘、也可以尝试使用 input()方法。

    我的建议是首先测试模型、而不使用任何自定义的 POST 流程。 我看到您的模型用于分类任务。 我建议编辑 config/image_classification.yaml 中的示例以测试您的模型。

    您可以使用 gst_debug=2来打印有关流水线中出现问题的更多详细信息。 例如、您可以使用:

    gst_debug=2 ./app_edgeai.py ../configs/image_classification.yaml -n

    末尾的-n 用于禁用终端上的性能统计信息。  

    请告诉我您找到的内容。

    此致、

    Qutaiba

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

    您好!  

    我找出了我遇到的问题、在 gst_wrapper.py 中、行644和1304上使用的 DSP 和 DCC 文件是:  

    "/opt/imaging %s/linear/DCC_viss.bin"、"/opt/imaging %s/linear/DCC_2a.bin"

    而对于640x480分辨率、我们应该使用的文件是:  

    "/opt/imaging %s/linear/DCC_viss_10b_640x480-bin"和 "/opt/imaging %s/linear/DCC_2a_10b_640x480-bin"

    这样就解决了错误、 但现在我在屏幕上看到的输出流似乎失真、颜色看起来不正确(非常绿色/紫色)、分辨率似乎仍然为1920x1080尺寸、我无法解决该问题、您能帮我解决吗? 谢谢你  

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

    Pragya、您好!

    使用"-n"选项运行时、您是否共享终端输出?  

    除了这种颜色问题、型号是否正常工作?

    此致、

    Qutaiba

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

    Pragya、您好!

    我看到您在 gst_wrapper 中对.bin 文件使用10位格式。 我建议  改用"/opt/imaging %s/linear/DCC_viss_640x480-bin"和"/opt/imaging %s/linear/DCC_2a_640x480.bin"。  

    此外、编辑 edgeai-gst-apps/script/setup_cameras.sh 第36行中的文件 https://github.com/TexasInstruments/edgeai-gst-apps/blob/main/scripts/setup_cameras.sh#L36、使用 IMX219_CAM_FMT="${IMX219_CAM_FMT:-[fmt:SRGGB8_1X8/640x480]}"。 在运行边缘 AI 应用程序之前、请先运行此脚本。  

    我只是尝试了一下、它在我这边可以正常工作。  

    此致、

    Qutaiba

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

    您好、感谢您的帮助、现在该脚本在640x480分辨率上运行良好。  

    但现在,当我尝试在1920x1080上运行它,然后我得到以下错误:  

    ==========[INPUT PIPELINE(S)]==========
    
    
    ** (python:1498): CRITICAL **: 11:25:01.438: gst_tiovx_multi_scaler_fixate_caps: assertion 'src_caps_list' failed
    
    ** (python:1498): CRITICAL **: 11:25:01.456: gst_tiovx_multi_scaler_fixate_caps: assertion 'src_caps_list' failed
    
    ** (python:1498): CRITICAL **: 11:25:01.479: gst_tiovx_multi_scaler_fixate_caps: assertion 'src_caps_list' failed
    
    ** (python:1498): CRITICAL **: 11:25:01.493: gst_tiovx_multi_scaler_fixate_caps: assertion 'src_caps_list' failed
    [ERROR] Error pulling tensor from GST Pipeline
    


    1.我更改了 gst_wrapper.py 以将宽度和高度设置为1920x1080,并将文件更改为 /opt/imaging %s/linear/DCC_viss.bin","/opt/imaging %s/linear/DCC_2a.bin"。

    2.我还更改了我的 YAML 文件,使其具有与 rggb 相同的高度和宽度和格式。  

    3.我还将 setup_cameras.sh 文件更改回此文件 [fmt:SRGGB8_1X8/1920x1080]

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

    Pragya、您好!

      与摄像机的1920x1080分辨率相比、您的型号输入的96x96太小。 这将需要在该帧上执行几个向下缩放周期。 我正在检查 edgeai-gst-apps 是否可以为此类极端用例生成流水线。 同时、您可以将 param.yaml 文件中的 resize 属性更新为256、而不是96、同时将裁剪属性保持为96。 生成的流水线将正常工作。 在该解决方案中、帧将按比例缩小到256、然后将中间的96x96区域裁剪掉。  

    此致、

    Qutaiba

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

    您好!  

    我尝试将调整大小设置为256、但这并没有解决问题。 仍然显示相同的错误。  

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

    Pragya、您好!

    edgeai-gst-apps 并非设计用于准备 gstreamer 流水线以将帧从1920x1080扩展到96x96。 这需要几个缩减周期。 硬件可能无法满足要求、但软件未针对此类用例做好准备。 您可以创建自己的流水线、也可以更新 edgeai-gst-apps 的软件。  

    现在、作为一项解决方法、您可以将范围缩小到256、然后裁剪到96x96。 这在理论上应该起作用。 为了更好地帮助您、当您尝试运行示例时、请共享您的 param.yaml 文件以及整个终端打印输出。  

    如果可能、您可以共享模型工件在我结束时进行尝试、但在我能够运行它之前需要一些延迟。  

    此致、

    Qutaiba