Skip to content

OpenCV LiveView (モノクロ) プロジェクト(GbE-2 / Python)

This content is not available in your language yet.

HelloWorld で作成した共通モジュール puclib.py と OpenCV (cv2) を使用して、GbE-2(モノクロモデル)から連続送信される圧縮データを C コールバック関数で受信・復号し、ウィンドウ上にリアルタイム表示(ライブビュー)するスクリプトの作成手順です。

  1. スクリプトの作成

    puclib.py と同じフォルダーに gbe2_opencv_live.py を作成し、以下のコードを記述します。

    gbe2_opencv_live.py
    import ctypes
    from ctypes import c_uint32, c_ushort, c_ubyte, c_void_p, POINTER, WINFUNCTYPE, byref
    import threading
    import numpy as np
    import cv2
    # 共通モジュール puclib.py から読み込み
    from puclib import (
    load_sdk, PUC_SUCCEEDED, PUC_DETECT_TARGET_HAWK,
    PUC_Q_COUNT, PUC_DETECT_FILTER, PUC_DETECT_INFO, PUC_XFER_DATA_INFO
    )
    def main():
    print("INFINICAM GbE-2 OpenCV LiveView (モノクロ) 開始...")
    # 1. SDKのロードと初期化
    puclib = load_sdk()
    if puclib.PUC_Initialize() != PUC_SUCCEEDED:
    print("エラー: SDKの初期化に失敗しました。")
    return
    # 2. 連続転送制御用 API の追加型定義
    CALLBACK_FUNC = WINFUNCTYPE(None, POINTER(PUC_XFER_DATA_INFO), c_void_p)
    puclib.PUC_SetRingBufferCount.argtypes = [c_void_p, c_uint32]
    puclib.PUC_SetRingBufferCount.restype = c_uint32
    puclib.PUC_BeginXferData.argtypes = [c_void_p, CALLBACK_FUNC, c_void_p]
    puclib.PUC_BeginXferData.restype = c_uint32
    puclib.PUC_EndXferData.argtypes = [c_void_p]
    puclib.PUC_EndXferData.restype = c_uint32
    # 3. デバイスの検索とオープン
    detect_filter = PUC_DETECT_FILTER(nDeviceTypeFlags=PUC_DETECT_TARGET_HAWK)
    detect_info = PUC_DETECT_INFO()
    if puclib.PUC_DetectDevice2(byref(detect_filter), byref(detect_info)) != PUC_SUCCEEDED or detect_info.nDeviceCount == 0:
    print("エラー: GbE-2 カメラが見つかりませんでした。")
    return
    h_device = c_void_p()
    if puclib.PUC_OpenDevice2(0, byref(h_device)) != PUC_SUCCEEDED:
    print("エラー: デバイスのオープンに失敗しました。")
    return
    # 4. カメラパラメータの取得
    width, height = c_uint32(), c_uint32()
    puclib.PUC_GetResolution(h_device, byref(width), byref(height))
    w, h = width.value, height.value
    q_vals = (c_ushort * PUC_Q_COUNT)()
    puclib.PUC_GetQuantization2(h_device, q_vals)
    print(f"解像度: {w} x {h} ピクセル (モノクロ)")
    # 5. バッファおよび排他制御の準備
    line_bytes = (w + 3) & ~3
    decoded_buffer = (c_ubyte * (line_bytes * h))()
    latest_frame = None
    frame_lock = threading.Lock()
    # 6. コールバック関数の定義
    @CALLBACK_FUNC
    def image_callback(p_xfer_data, p_user_param):
    nonlocal latest_frame
    if not p_xfer_data or p_xfer_data.contents.isDamaged:
    return
    # 受信した圧縮データを復号
    ret = puclib.PUC_DecodeData(
    decoded_buffer, 0, 0, w, h, line_bytes,
    p_xfer_data.contents.pData, q_vals
    )
    if ret == PUC_SUCCEEDED:
    # NumPy 配列化(スレッド間で安全に保持するため copy します)
    img = np.ctypeslib.as_array(decoded_buffer).reshape((h, line_bytes))[:, :w].copy()
    with frame_lock:
    latest_frame = img
    # 7. 連続転送の開始
    puclib.PUC_SetRingBufferCount(h_device, 32)
    ret = puclib.PUC_BeginXferData(h_device, image_callback, None)
    if ret != PUC_SUCCEEDED:
    print(f"エラー: 連続転送の開始に失敗しました。ErrorCode: {ret}")
    puclib.PUC_CloseDevice(h_device)
    return
    window_name = "INFINICAM GbE-2 LiveView (ESCまたはQキーで終了)"
    cv2.namedWindow(window_name, cv2.WINDOW_AUTOSIZE)
    print("ライブビュー表示中... ウィンドウ上で 'ESC' または 'Q' キーを押すと終了します。")
    # 8. メイン描画ループ
    try:
    while True:
    img_to_show = None
    with frame_lock:
    if latest_frame is not None:
    img_to_show = latest_frame
    if img_to_show is not None:
    cv2.imshow(window_name, img_to_show)
    # 1ms 待機してキー入力をチェック
    key = cv2.waitKey(1) & 0xFF
    if key in (27, ord('q'), ord('Q')): # ESC (27) または 'q' / 'Q'
    print("ユーザー操作により終了します。")
    break
    finally:
    # 9. 終了処理
    puclib.PUC_EndXferData(h_device)
    cv2.destroyAllWindows()
    puclib.PUC_CloseDevice(h_device)
    if __name__ == "__main__":
    main()
  2. スクリプトの実行

    Terminal window
    python gbe2_opencv_live.py

    実行すると OpenCV の表示ウィンドウが立ち上がり、カメラからの映像がリアルタイムにストリーミング描画されます。キーボードの ESC または Q キーを押すと転送が停止し、安全に終了します。


リアルタイム処理の実装ポイント

Section titled “リアルタイム処理の実装ポイント”

1. C コールバック関数(ctypes.WINFUNCTYPE)

Section titled “1. C コールバック関数(ctypes.WINFUNCTYPE)”

PUC_BeginXferData は、カメラから新しいデータフレームを受信した際に SDK 内部スレッドから自動的に Python 側の関数を呼び出します。C 言語とのインターフェースを定義するために WINFUNCTYPE で型定義を行っています。

CALLBACK_FUNC = WINFUNCTYPE(None, POINTER(PUC_XFER_DATA_INFO), c_void_p)

2. スレッド安全なフレーム更新(threading.Lock)

Section titled “2. スレッド安全なフレーム更新(threading.Lock)”

SDK の受信・復号スレッド(コールバック内)と、OpenCV の描画スレッド(メインループ)が同時にフレームデータへアクセスすることによるメモリ競合(画面のチラつきや不整合)を防ぐため、threading.Lock() による調停を行っています。