處理影像#
圖像表示#
在 pypylon 中,圖像會以例如 NumPy arrays 的形式公開,這意味著它們可以直接用於科學和機器視覺工作流程中。
這是一個典型的工作流程:
存取圖像資料#
必須清楚了解何時該複製擷取結果中的資料,何時不該複製。複製過多會浪費時間,而複製過少則可能導致系統當機或像素資料錯誤。
| 程式碼 | 描述 | 是否需要複製? |
|---|---|---|
.Array | 傳回 NumPy 複本 | 否(已經是複本) |
.GetMemoryView() | 傳回緩衝區檢視 | 是 |
.GetArrayZeroCopy() | 傳回零複製陣列 | 是 |
grab_result.Array是內部緩衝區的複本。grab_result.GetMemoryView()是一個 檢視內部緩衝區 (像素類型除外,其中pylon.IsPacked(grab_result.PixelType)為 True)。grab_result.GetArrayZeroCopy()是一個 檢視內部緩衝區 提供無需複製的 NumPy 陣列(以下像素類型除外:pylon.IsPacked(grab_result.PixelType)為 True)。- 抓取結果緩衝區會在離開
with區塊或grab_result.Release()為止。 - 在緩衝區釋放後存取 Memory 檢視或 zero-copy 陣列可能會導致無效的 Memory 存取。
正確用法:
with camera.RetrieveResult(5000) as grab_result:
if grab_result.GrabSucceeded():
image = grab_result.Array
圖像形狀與格式#
陣列的形狀取決於 Pixel Format:
| Pixel Format | 形狀範例 |
|---|---|
| Mono8 | (高度、寬度) |
| RGB8/BGR8 | (高度、寬度、3) |
您可以直接檢查形狀:
Pixel Format Conversion#
根據相機組態,原始影像格式可能不適用,且可能需要進行轉換。
範例:轉換為 BGR(相容於 OpenCV)
converter = pylon.ImageFormatConverter()
converter.OutputPixelFormat = pylon.PixelType_BGR8packed
image = converter.Convert(grab_result).GetArray()
資訊
在 ImageFormatConverter, OutputPixelFormat 是用於保存像素類型值的簡單屬性,而非 Property 節點。請直接指派(converter.OutputPixelFormat = pylon.PixelType_BGR8packed)。它沒有 .Value 存取子。
直接轉換為 NumPy 陣列(ConvertToArray)#
converter.Convert(src) 會傳回 PylonImage。使用 .Array (或針對 32 位元應用程式的 .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),uint8PixelType_Mono16→(height, width),uint16PixelType_RGB8packed/PixelType_BGR8packed→(height, width, 3),uint8
位元封包輸出格式(其中 pylon.IsPacked(pixel_type) 為 True)沒有明確的 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 陣列(也適用於封包格式) | 否 |
為什麼需要轉換#
- 相機通常會輸出原始格式或 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 現在可能會參照無效的 Memory。如果在區塊外部需要,請務必使用 result.Array ,或者保持 grab_result 處於啟用狀態。
忽略 Pixel Format#
請務必驗證或明確設定 Pixel Format。忽略此操作可能會導致以下後果:
- 顏色解析錯誤
- 處理結果不正確
效能開銷#
以下操作可能會降低效能:
- 複製大型圖像需要花費時間
- 轉換會增加 CPU 負載
避免此情況的策略:
- 縮小 Region of Interest (ROI)(請參閱 Configuring Camera Parameters)
- 避免不必要的轉換
在處理管線中使用圖像#
由於圖像為 NumPy 陣列,因此可以直接與 OpenCV、NumPy Operations 以及 AI/ML Frameworks 搭配使用。
這是圖像處理管線的通用圖解。
統計評估:
OpenCV#
NumPy 操作#
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}%")
以下是各個步驟的說明:
-
轉為灰階:
-
正規化:
-
閾值處理:
-
統計評估:
通用的 NumPy 圖像管線如下所示:
重點整理#
- 圖像會以 NumPy 陣列的形式提供。
- 需要在必要時複製緩衝區資料。
- 確保您使用的是正確的 Pixel Format。
- 後續處理可能需要進行轉換。