コンテンツにスキップ
ステージングサーバー
開発サーバー

画像の操作#

このトピックでは、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) が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)

形状を直接検査できます。

print(image.shape)

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), uint8
  • PixelType_Mono16 → (height, width), uint16
  • PixelType_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負荷が増加します

これを回避するための戦略:

処理パイプラインでの画像の使用#

画像はNumPy配列であるため、OpenCV、NumPy Operations、およびAI/ML Frameworksで直接使用できます。

これはイメージパイプラインの一般的な図解です。

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配列として提供されます。
  • 必要な場合は常にバッファデータをコピーしてください。
  • 正しい Pixel Format を使用していることを確認してください。
  • 後続の処理のために変換が必要になる場合があります。