如何只用两个Python函数在几分钟内创建完整的计算机视觉应用程序

        本文介绍在计算机视觉开发中采用的Pipeless开源框架,以及如何使用几个代码函数创建一个完整的应用程序。

        本文首先概述典型的计算机视觉应用程序的要求。然后,介绍Pipeless这一为嵌入式计算机视觉提供无服务器开发体验的开源框架。最后,提供一个详细的步骤指南,介绍如何创建和执行一个简单的对象检测应用程序,该应用程序只需采用几个Python函数和一个模型进行创建。

创建计算机视觉应用程序

        如果有人希望用一句话描述“计算机视觉”的话,那么给出回答是“通过摄像头界面识别视觉事件并对其做出反应的艺术。”但这可能不是他想听到的答案。因此,以下将深入了解计算机视觉应用程序是如何构建的,以及每个子系统需要实现的功能。

•真正快速的帧处理:如要实时处理60 fps的视频流,只有16毫秒的时间来处理每帧。这在一定程度上是通过多线程和多处理进程实现的。在许多情况下,希望在前一个帧完成之前开始处理一个帧。

•在每一帧上运行推理并执行对象检测、分割、姿态估计等的人工智能模型:幸运的是,有越来越多优秀的开源模型,所以不必从头开始创建自己的模型,通常只需微调模型的参数以匹配用例。

•推理运行时间:推理运行时间负责加载模型,并在不同的可用设备(GPU或CPU)上高效运行。

•GPU:为了使模型足够快地运行推理,我们需要采用GPU。这是因为GPU可以处理比CPU多几个数量级的并行操作,而最低级别的模型只是大量的数学运算。你需要处理帧所在的内存。它们可以位于 GPU 内存或 CPU 内存 (RAM) 中,在这些内存之间复制帧是一项非常繁重的操作,因为帧大小会使处理速度变慢。

•多媒体管道:这些部件允许从数据源获取视频流,将它们分割成帧,将它们作为模型的输入,有时修改和重建视频流以转发。

•视频流管理:开发人员可能希望应用程序能够抵抗视频流的中断、重新连接、动态添加和删除视频流、同时处理多个视频流,等等。

        所有这些系统都需要创建或合并到项目中,因此,需要维护代码。然而,面临的问题是最终维护的大量代码并非特定于应用程序,而是围绕实际案例特定代码的子系统。

Pipeless框架

        为了避免从头开始构建上述所有内容,可以代用Pipeless框架。这是一个用于计算机视觉的开源框架,允许提供一些特定于案例的功能,并且能够处理其他事物。

        Pipeless框架将应用程序的逻辑划分为“阶段”,其中的一个阶段就像单个模型的微型应用程序。一个阶段可以包括预处理、使用预处理的输入运行推理,以及对模型输出进行后处理以采取行动。然后,可以链接尽可能多的阶段,以组成完整的应用程序,甚至使用多个模型。

        为了提供每个阶段的逻辑,只需添加一个特定于应用程序的代码函数,然后在需要时由Pipeless负责调用它。这就是可以将Pipeless视为一个框架的原因,它为嵌入式计算机视觉提供类似服务器的开发体验,并且提供了一些功能,不必担心需要其他的子系统。

        Pipeless的另一个重要特性是,可以通过CLI或REST API动态地添加、删除和更新视频流,从而实现视频流处理的自动化。甚至可以指定重新启动策略,指示何时应该重新启动视频流的处理,是否应该在出现错误后重新启动,等等。

        最后,部署Pipeless框架,只需要在任何设备上安装它并与代码函数一起运行,无论是在云计算虚拟机或容器化模式中,还是直接在Nvidia Jetson、Raspberry等边缘设备中。

创建对象检测应用程序

        以下深入地了解如何使用Pipeless框架创建一个简单的对象检测应用程序。

        第一就是安装。安装脚本,使其安装非常简单:


Curl https://raw.githubusercontent.com/pipeless-ai/pipeless/main/install.sh | bash
        现在,必须创建一个项目。Pipeless项目是一个包含阶段的目录。每个阶段都在子目录下,在每个子目录中,创建包含hooks(特定的代码函数)的文件。为每个阶段文件夹提供的名称是稍后要为视频流运行该阶段时,必须向Pipeless框指示的阶段名称。

pipeless init my-project --template empty
cd my-project在这里,空模板告诉CLI只创建目录,如果不提供任何模板,CLI将提示几个问题以交互式地创建阶段。

        如上所述,现在需要为项目添加一个阶段。采用下面的命令从GitHub下载一个阶段示例:


wget -O - https://github.com/pipeless-ai/pipeless/archive/main.tar.gz | 
  tar -xz --strip=2 "pipeless-main/examples/onnx-yolo"
         这将创建一个阶段目录onnx-yolo,其中包含应用程序函数。

        然后,检查每个阶段文件的内容,也就是应用程序hooks。

        这里有一个pre-process.py文件,它定义了一个接受一个框架和一个场景的函数(hooks)。该函数执行一些操作来准备接收RGB帧的输入数据,以便与模型期望的格式匹配。该数据被添加到frame_data[' interence_input ']中,这是Pipeless将传递给模型的数据。

 

def hook(frame_data, context):
    frame = frame_data["original"].view()
    yolo_input_shape = (640, 640, 3) # h,w,c
    frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
    frame = resize_rgb_frame(frame, yolo_input_shape)
    frame = cv2.normalize(frame, None, 0.0, 1.0, cv2.NORM_MINMAX)
    frame = np.transpose(frame, axes=(2,0,1)) # Convert to c,h,w
    inference_inputs = frame.astype("float32")
    frame_data['inference_input'] = inference_inputs
... (some other auxiliar functions that we call from the hook function)
        还有process.json文件,它指示要使用的Pipeless推理运行时间(在本例中为ONNX运行时间),在哪里可以找到它应该加载的模型,以及它的一些可选参数,例如要使用的execution_provider,即CPU、CUDA、TensortRT等。

{ 
    "runtime": "onnx",
    "model_uri": "https://pipeless-public.s3.eu-west-3.amazonaws.com/yolov8n.onnx",
    "inference_params": { 
        "execution_provider": "tensorrt" 
    }
}
        最后,post-process.py文件定义了一个类似于pre-process.py中的函数。这一次,它接受Pipeless存储在frame_data["inference_output"]中的推理输出,并执行将该输出解析为边界框的操作。稍后,它在框架上绘制边界框,最后将修改后的框架分配给frame_data['modified']。这样,Pipeless将转发提供的视频流,但带有修改后的帧,其中包括边界框。
 

def hook(frame_data, _):
    frame = frame_data['original']
    model_output = frame_data['inference_output']
    yolo_input_shape = (640, 640, 3) # h,w,c
    boxes, scores, class_ids = 
           parse_yolo_output(model_output, frame.shape, yolo_input_shape)
    class_labels = [yolo_classes[id] for id in class_ids]
    for i in range(len(boxes)):
        draw_bbox(frame, boxes[i], class_labels[i], scores[i])

    frame_data['modified'] = frame

... (some other auxiliar functions that we call from the hook function)
        最后一步是启动Pipeless并提供一个视频流。要启动Pipeless,只需在my-project目录下运行以下命令:

pipeless start --stages-dir .
        一旦运行,将提供来自网络摄像头(v4l2)的视频流,并直接在屏幕上显示输出。需要注意的是,必须提供视频流按顺序执行的阶段列表。在这个例子中,它只是onnx-yolo阶段:
 

pipeless add stream --input-uri "v4l2" --output-uri "screen" --frame-path "onnx-yolo"

结论

        创建计算机视觉应用程序是一项复杂的任务,因为有许多因素和必须围绕它实现的子系统。使用像Pipeless这样的框架,启动和运行只需要几分钟,可以专注于为特定用例编写代码。此外,Pipeless的“阶段”是高度可重用的,易于维护,因此维护将会很容易,可以非常快速地迭代。

        如果希望参与Pipeless的开发,可以通过它的GitHub存储库来实现。

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-03-25 02:58:03       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-03-25 02:58:03       101 阅读
  3. 在Django里面运行非项目文件

    2024-03-25 02:58:03       82 阅读
  4. Python语言-面向对象

    2024-03-25 02:58:03       91 阅读

热门阅读

  1. PiflowX-Faker组件

    2024-03-25 02:58:03       46 阅读
  2. bind更改this指向问题

    2024-03-25 02:58:03       43 阅读
  3. 三维重建-单目相机标定

    2024-03-25 02:58:03       37 阅读
  4. c语言如何颠倒字符串顺序

    2024-03-25 02:58:03       35 阅读
  5. 网络安全工程师学习路线汇总

    2024-03-25 02:58:03       43 阅读
  6. 安卓面试题多线程 131-135

    2024-03-25 02:58:03       37 阅读
  7. 关于利率,你需要知道的那些事

    2024-03-25 02:58:03       47 阅读
  8. platform devices创建实例

    2024-03-25 02:58:03       34 阅读
  9. AOP原理和切面应用

    2024-03-25 02:58:03       35 阅读
  10. P8717 [蓝桥杯 2020 省 AB2] 成绩分析 Python

    2024-03-25 02:58:03       44 阅读
  11. 【算法】数论---乘法逆元

    2024-03-25 02:58:03       46 阅读
  12. C. Lexicographically Largest - 思维

    2024-03-25 02:58:03       46 阅读