画像の操作#
画像表現#
pypylonでは、画像はNumPy配列などとして公開されるため、科学技術およびマシンビジョンワークフローで直接使用できます。
これは典型的なワークフローです:
画像データへのアクセス#
グラブ結果からデータをいつコピーすべきで、いつコピーすべきでないかを把握することが不可欠です。コピーしすぎると時間を無駄にし、コピーが少なすぎるとクラッシュや不正確な画素データにつながる可能性があります。
| コード | 説明 | コピーが必要か? |
|---|---|---|
.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()が呼び出されるまで取得モードのままになります。 - バッファが解放された後にメモリビューまたはゼロコピー配列にアクセスすると、無効なメモリアクセスが発生する可能性があります。
正しい使い方:
with camera.RetrieveResult(5000) as grab_result:
if grab_result.GrabSucceeded():
image = grab_result.Array
画像の形状とフォーマット#
配列の形状はピクセルフォーマットによって異なります。
| Pixel Format | 形状例 |
|---|---|
| Mono8 | (高さ、幅) |
| RGB8/BGR8 | (高さ、幅、3) |
形状を直接検査できます。
Pixel Format変換#
カメラの設定によっては、RAW画像フォーマットが適さない場合があり、変換が必要になることがあります。
例: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 (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 配列(パック形式の場合も同様) | いいえ |
変換が必要な理由#
- カメラは、多くの場合、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の無視#
Pixel Formatは常に確認するか、明示的に設定してください。これを無視すると、次のような結果につながる可能性があります。
- 不正確なカラー解釈
- 不正確な処理結果
パフォーマンス上のオーバーヘッド#
以下の操作によりパフォーマンスが低下する可能性があります:
- 大きな画像のコピーには時間がかかります
- 変換によりCPU負荷が増加します
これを回避するための戦略:
- ROIの縮小(「カメラパラメータの設定」を参照)
- 不要な変換の回避
処理パイプラインでの画像の使用#
画像は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 を使用していることを確認してください。
- 後続の処理のために変換が必要になる場合があります。