OpenCV LiveView (モノクロ) プロジェクト(GbE-2 / Python)
This content is not available in your language yet.
HelloWorld で作成した共通モジュール puclib.py と OpenCV (cv2) を使用して、GbE-2(モノクロモデル)から連続送信される圧縮データを C コールバック関数で受信・復号し、ウィンドウ上にリアルタイム表示(ライブビュー)するスクリプトの作成手順です。
-
スクリプトの作成
puclib.pyと同じフォルダーにgbe2_opencv_live.pyを作成し、以下のコードを記述します。gbe2_opencv_live.py import ctypesfrom ctypes import c_uint32, c_ushort, c_ubyte, c_void_p, POINTER, WINFUNCTYPE, byrefimport threadingimport numpy as npimport 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_uint32puclib.PUC_BeginXferData.argtypes = [c_void_p, CALLBACK_FUNC, c_void_p]puclib.PUC_BeginXferData.restype = c_uint32puclib.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 カメラが見つかりませんでした。")returnh_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.valueq_vals = (c_ushort * PUC_Q_COUNT)()puclib.PUC_GetQuantization2(h_device, q_vals)print(f"解像度: {w} x {h} ピクセル (モノクロ)")# 5. バッファおよび排他制御の準備line_bytes = (w + 3) & ~3decoded_buffer = (c_ubyte * (line_bytes * h))()latest_frame = Noneframe_lock = threading.Lock()# 6. コールバック関数の定義@CALLBACK_FUNCdef image_callback(p_xfer_data, p_user_param):nonlocal latest_frameif 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)returnwindow_name = "INFINICAM GbE-2 LiveView (ESCまたはQキーで終了)"cv2.namedWindow(window_name, cv2.WINDOW_AUTOSIZE)print("ライブビュー表示中... ウィンドウ上で 'ESC' または 'Q' キーを押すと終了します。")# 8. メイン描画ループtry:while True:img_to_show = Nonewith frame_lock:if latest_frame is not None:img_to_show = latest_frameif img_to_show is not None:cv2.imshow(window_name, img_to_show)# 1ms 待機してキー入力をチェックkey = cv2.waitKey(1) & 0xFFif key in (27, ord('q'), ord('Q')): # ESC (27) または 'q' / 'Q'print("ユーザー操作により終了します。")breakfinally:# 9. 終了処理puclib.PUC_EndXferData(h_device)cv2.destroyAllWindows()puclib.PUC_CloseDevice(h_device)if __name__ == "__main__":main() -
スクリプトの実行
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() による調停を行っています。
