處理影像#
圖像表示#
在 pypylon 中,影像以NumPy 陣列等形式呈現,這意味著它們可直接應用於科學及機器視覺工作流程中。
以下是一個典型的作業流程:
存取影像資料#
必須清楚了解何時該複製擷取結果中的資料,以及何時不該複製。複製過多會浪費時間,而複製過少則可能導致系統當機或像素資料錯誤。
| 程式碼 | 描述 | 需要複製嗎? |
|---|---|---|
.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) |
您可以直接檢視該形狀:
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),uint8PixelType_Mono16→(height, width),uint16PixelType_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 負載
避免此情況的策略:
- 縮小感興趣區域 (ROI)(請參閱「設定攝影機參數」)
- 避免不必要的轉換
在處理流程中使用影像#
由於影像屬於 NumPy 陣列,因此可直接用於OpenCV、NumPy 運算以及AI/ML 框架中。
這是一幅關於影像處理流程的概括性示意圖。
這代表了大多數電腦視覺系統的核心資料流。
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 陣列的形式提供。
- 必要時請務必複製緩衝區資料。
- 請確保您使用的是正確的像素格式。
- 後續處理可能需要進行轉換。