跳转到内容
STAGING SERVER
DEVELOPMENT SERVER

线程与并发#

本主题阐述了如何在 pypylon 应用程序中使用线程和并发性,以及如何构建采集和处理流水线以实现高性能和可扩展性。

此可视化图表展示了图像采集在 Python 应用程序中的工作原理。

Camera → Native Thread → Buffer Queue → Python Application
  • 图像采集运行在 pylon 内部的 原生(C++)线程 中。
  • 您的 Python 代码从 缓冲区队列 中检索图像。
  • 这种分离实现了异步采集。

在许多应用程序中,图像采集速度快于处理速度:

Camera → 100 fps
Processing → 20 fps

没有并发机制时:

  • 缓冲区被填满。
  • 帧被丢弃。
  • 延迟增加。

基本执行模型#

单线程方法是图像采集流水线最简单的形式。

Acquire → Process → Acquire → Process

示例:

while camera.IsGrabbing():
    with camera.RetrieveResult(5000) as grab_result:
        if grab_result.GrabSucceeded():
            image = grab_result.Array
            process(image)

这具有以下缺点:

  • 处理过程会阻塞采集。
  • CPU 利用率低下
  • 可扩展性受限

这是一种用于图像采集流水线的更为复杂的方法。

Acquisition Thread → Queue → Worker Thread(s)
  • Producer:采集线程抓取图像并将其推送到队列中。
  • Consumer:工作线程独立处理图像。

使用自定义线程的示例实现#

信息

您可以使用 InstantCamera 提供的抓取循环线程(请参阅 grab_using_grab_loop_thread 示例)。此自定义实现仅用于演示目的。

import threading
import queue
from pypylon import pylon

def process(image):
    print(image.shape)

image_queue = queue.Queue(maxsize=10)

# Producer thread
def grab_loop(camera):
    while camera.IsGrabbing():
        with camera.RetrieveResult(5000) as grab_result:
            if grab_result.GrabSucceeded():
                image = grab_result.Array
                image_queue.put(image)

# Consumer thread
def process_loop():
    while True:
        image = image_queue.get()
        process(image)
        image_queue.task_done()

with pylon.InstantCamera(pylon.FirstFound) as camera:
    camera.StartGrabbing()

    grab_thread = threading.Thread(target=grab_loop, args=(camera,))
    processing_thread = threading.Thread(target=process_loop)

    grab_thread.start()
    processing_thread.start()

    grab_thread.join()
    image_queue.join()

队列行为与背压#

Queue full → producer blocks → acquisition slows down

策略:

  • 增大队列大小。
  • 手动丢弃帧。
  • 使用 LatestImageOnly.

与抓取策略相结合#

  • LatestImageOnly:减少积压。
  • OneByOne:确保完整性。

最佳实践:

LatestImageOnly + queue → responsive systems
OneByOne + logging → analysis systems

线程安全性注意事项#

  • 避免在没有锁的情况下共享可变数据。
  • 在将图像传递给其他线程之前复制图像,例如通过使用 Array 函数。
  • 使用 queue.Queue 以实现安全的通信。

CPU 利用率#

并行处理具有以下优势:

  • 更好的 CPU 利用率
  • 关注点分离
  • 可扩展的架构
Core 1 → Acquisition
Core 2 → Processing
Core 3 → AI

何时使用多线程#

在以下情况下使用线程:

  • 处理速度慢于采集速度。
  • 存在多个处理阶段。
  • 需要实时响应能力。

在以下情况下避免使用线程:

  • 处理开销可以忽略不计。
  • 必须保持最低的系统复杂度。

高级模式(概述)#

多阶段流水线#

多阶段流水线将图像处理拆分为独立步骤,这些步骤可并发运行并通过队列交换数据。

Grab → Preprocess → Analyze → Display

多消费者设置#

Producer → Queue → Multiple processing threads

概念流水线#

Camera → Queue → Processing → Results

核心要点#

  • 采集和处理应进行解耦。
  • 使用生产者-消费者模式来提高可扩展性。
  • 队列提供线程安全的通信。
  • 多线程可以提升性能,但也会增加复杂性。