跳至內容
測試伺服器
開發伺服器

處理影像#

本主題說明影像資料在 pypylon 中如何被表示、如何安全地存取該資料,以及如何將其準備好以供後續處理(例如使用 NumPy、OpenCV 或 AI 框架)。

圖像表示#

在 pypylon 中,影像以NumPy 陣列等形式呈現,這意味著它們可直接應用於科學及機器視覺工作流程中。

以下是一個典型的作業流程:

Camera → GrabResult → Buffer → NumPy Array

存取影像資料#

必須清楚了解何時該複製擷取結果中的資料,以及何時不該複製。複製過多會浪費時間,而複製過少則可能導致系統當機或像素資料錯誤。

程式碼 描述 需要複製嗎?
.Array 傳回一個 NumPy 副本 不(已有副本)
.GetMemoryView() 傳回一個緩衝區檢視 是
.GetArrayZeroCopy() 回傳一個零複製陣列 是
  • grab_result.Array 是內部緩衝區的副本。
  • grab_result.GetMemoryView() 是一個 檢視內部緩衝區 (但以下列像素類型除外: pylon.IsPacked(grab_result.PixelType) (為真)。
  • grab_result.GetArrayZeroCopy() 是一個 檢視內部緩衝區 在不進行複製的情況下提供 NumPy 陣列(唯獨像素類型除外,其 pylon.IsPacked(grab_result.PixelType) (為真)。
  • 當離開 with 封鎖或 grab_result.Release() 被呼叫。
  • 在釋放緩衝區後存取記憶體檢視或零拷貝陣列,可能會導致記憶體存取錯誤。

正確用法:

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

影像形狀與格式#

陣列的形狀取決於像素格式:

Pixel Format 形狀範例
Mono8 (高度, 寬度)
RGB8/BGR8 (高度, 寬度, 3)

您可以直接檢視該形狀:

print(image.shape)

Pixel Format 轉換#

視相機設定而定,原始影像格式可能不適用,因此可能需要進行轉換。

範例:轉換為 BGR 格式(相容於 OpenCV)

converter = pylon.ImageFormatConverter()
converter.OutputPixelFormat = pylon.PixelType_BGR8packed

image = converter.Convert(grab_result).GetArray()

資訊

在 ImageFormatConverter, OutputPixelFormat 是一個儲存像素型值的普通屬性,而非參數節點。請直接為其賦值(converter.OutputPixelFormat = pylon.PixelType_BGR8packed). 它沒有 .Value 配件。

直接轉換為 NumPy 陣列 (ConvertToArray)#

converter.Convert(src) 返回一個 PylonImage. 透過以下方式讀取其像素: .Array (或 .GetArray()),會產生一個 附加內容 已轉換的緩衝區。若您只需要將結果轉換為 NumPy 陣列,請使用 converter.ConvertToArray(src) 相反地,這會預先分配一個具有正確形狀和資料類型的 NumPy 陣列,並讓轉換器將轉換後的像素寫入其中 直接存入該陣列中, 避免不必要的複製。

converter = pylon.ImageFormatConverter()
converter.OutputPixelFormat = pylon.PixelType_BGR8packed

# Equivalent result to converter.Convert(grab_result).Array, but without the extra copy.
image = converter.ConvertToArray(grab_result)

ConvertToArray 接受與以下相同的來源類型: Convert (一項抓取結果,一個 PylonImage、一個資料元件,或任何 IImage),而所得陣列的形狀與資料類型反映了 OutputPixelFormat:

  • PixelType_Mono8 → (height, width), uint8
  • PixelType_Mono16 → (height, width), uint16
  • PixelType_RGB8packed / PixelType_BGR8packed → (height, width, 3), uint8

一種位元壓縮的輸出格式(即一種 pylon.IsPacked(pixel_type) (若為真)沒有明確的 NumPy 形狀/資料類型,因此 ConvertToArray 提高 ValueError 預設情況下,請為其設定。傳遞 raw=True 以平面格式取得轉換後的位元組 uint8 改用陣列:

# raw=True returns a flat uint8 array of the converted bytes,
# which is also how to handle bit-packed output formats.
raw_bytes = converter.ConvertToArray(grab_result, raw=True)
方法 結果 多出一份嗎?
converter.Convert(src).Array 透過中間變數建立 NumPy 陣列 PylonImage 是
converter.ConvertToArray(src) 就地寫入 NumPy 陣列 否
converter.ConvertToArray(src, raw=True) 平房 uint8 陣列(亦適用於緊湊格式) 否

為何轉換是必要的#

  • 相機通常會輸出 RAW 或拜耳(Bayer)格式的檔案。
  • 應用程式通常會預期:
    • BGR(OpenCV)
    • RGB(可視化)

常見陷阱#

在緩衝區釋放後使用資料#

with camera.RetrieveResult(...) as grab_result:
    image = grab_result.Array # NumPy array
    memory_view = grab_result.GetMemoryView()
    with grab_result.GetArrayZeroCopy() as zero_copy_array:
        ... process zero_copy_array (NumPy array) ...

這樣做是不安全的,因為 memory_view 現在可能會存取無效的記憶體。請務必使用 result.Array 若需在區塊外使用,或保留該 grab_result 還活著。

忽略Pixel Format#

請務必驗證或明確設定像素格式。若忽略此點,可能會導致以下後果:

  • 錯誤的顏色解讀
  • 處理結果不正確

效能開銷#

以下操作可能會降低系統效能:

  • 複製大型圖片需要時間
  • 轉換會增加 CPU 負載

避免此情況的策略:

在處理流程中使用影像#

由於影像屬於 NumPy 陣列,因此可直接用於OpenCV、NumPy 運算以及AI/ML 框架中。

這是一幅關於影像處理流程的概括性示意圖。

Camera → GrabResult → NumPy Array → Processing → Output

這代表了大多數電腦視覺系統的核心資料流。

OpenCV#

import cv2

cv2.imshow("image", image)
cv2.waitKey(1)

NumPy 運算#

mean = image.mean()

AI/ML 框架#

  • PyTorch
  • TensorFlow

使用 NumPy 的範例影像處理流程#

NumPy 能夠直接對已擷取的影像進行快速且向量化的影像處理。

以下範例是一個規模雖小但切合實際的、使用 NumPy 的影像處理流程。

範例程式碼#

import numpy as np
from pypylon import pylon

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

    camera.StartGrabbingMax(100)

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

                # Do something with the image data.

                if image.ndim == 3:
                    gray = image.mean(axis=2)
                else:
                    gray = image

                norm = gray / 255.0

                binary = norm > 0.5

                mean_intensity = norm.mean()
                bright_pixel_ratio = binary.mean()

                print(f"Mean intensity: {mean_intensity:.3f}")
                print(f"Bright pixels: {bright_pixel_ratio*100:.1f}%")

以下是各個步驟的說明:

  • 灰階轉換:

    gray = image.mean(axis=2)
    
  • 正規化:

    norm = gray / 255.0
    
  • 閾值設定:

    binary = norm > 0.5
    
  • 統計評估:

    mean_intensity = norm.mean()
    bright_pixel_ratio = binary.mean()
    

一個通用的 NumPy 影像處理流程如下所示:

Raw Image → NumPy Array → Processing → Features → Decision

重點摘要#

  • 影像以 NumPy 陣列的形式提供。
  • 必要時請務必複製緩衝區資料。
  • 請確保您使用的是正確的像素格式。
  • 後續處理可能需要進行轉換。