OpenCV LiveView (Monochrome) Project (GbE-2 / Python)
Steps for creating a script that uses the common module puclib.py created in HelloWorld together with OpenCV (cv2) to receive and decode, via a C callback function, compressed data continuously streamed from the GbE-2 (monochrome model), and display it in real time (live view) in a window.
-
Create the script
In the same folder as
puclib.py, creategbe2_opencv_live.pyand write the following code.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# Import from the common module puclib.pyfrom puclib import (load_sdk, PUC_SUCCEEDED, PUC_DETECT_TARGET_GBE2,PUC_Q_COUNT, PUC_DETECT_FILTER, PUC_DETECT_INFO, PUC_XFER_DATA_INFO)def main():print("Starting INFINICAM GbE-2 OpenCV LiveView (monochrome)...")# 1. Load and initialize the SDKpuclib = load_sdk()if puclib.PUC_Initialize() != PUC_SUCCEEDED:print("Error: Failed to initialize the SDK.")return# 2. Additional type definitions for the continuous-transfer control APICALLBACK_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. Search for and open the devicedetect_filter = PUC_DETECT_FILTER(nDeviceTypeFlags=PUC_DETECT_TARGET_GBE2)detect_info = PUC_DETECT_INFO()if puclib.PUC_DetectDevice2(byref(detect_filter), byref(detect_info)) != PUC_SUCCEEDED or detect_info.nDeviceCount == 0:print("Error: No GbE-2 camera was found.")returnh_device = c_void_p()if puclib.PUC_OpenDevice2(0, byref(h_device)) != PUC_SUCCEEDED:print("Error: Failed to open the device.")return# 4. Retrieve camera parameterswidth, 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"Resolution: {w} x {h} pixels (monochrome)")# 5. Prepare the buffer and the mutual-exclusion mechanismline_bytes = (w + 3) & ~3decoded_buffer = (c_ubyte * (line_bytes * h))()latest_frame = Noneframe_lock = threading.Lock()# 6. Define the callback function@CALLBACK_FUNCdef image_callback(p_xfer_data, p_user_param):nonlocal latest_frameif not p_xfer_data or p_xfer_data.contents.isDamaged:return# Decode the received compressed dataret = puclib.PUC_DecodeData(decoded_buffer, 0, 0, w, h, line_bytes,p_xfer_data.contents.pData, q_vals)if ret == PUC_SUCCEEDED:# Convert to a NumPy array (copy it so it can be safely shared between threads)img = np.ctypeslib.as_array(decoded_buffer).reshape((h, line_bytes))[:, :w].copy()with frame_lock:latest_frame = img# 7. Start the continuous transferpuclib.PUC_SetRingBufferCount(h_device, 32)ret = puclib.PUC_BeginXferData(h_device, image_callback, None)if ret != PUC_SUCCEEDED:print(f"Error: Failed to start the continuous transfer. ErrorCode: {ret}")puclib.PUC_CloseDevice(h_device)returnwindow_name = "INFINICAM GbE-2 LiveView (press ESC or Q to exit)"cv2.namedWindow(window_name, cv2.WINDOW_AUTOSIZE)print("Displaying the live view... Press 'ESC' or 'Q' in the window to exit.")# 8. Main rendering looptry: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)# Wait 1 ms and check for key inputkey = cv2.waitKey(1) & 0xFFif key in (27, ord('q'), ord('Q')): # ESC (27) or 'q' / 'Q'print("Exiting due to user action.")breakfinally:# 9. Shutdown processingpuclib.PUC_EndXferData(h_device)cv2.destroyAllWindows()puclib.PUC_CloseDevice(h_device)if __name__ == "__main__":main() -
Run the script
Terminal window python gbe2_opencv_live.pyWhen run, an OpenCV display window opens and the video from the camera is streamed and rendered in real time. Pressing the
ESCorQkey stops the transfer and exits safely.
Real-Time Processing Implementation Highlights
Section titled “Real-Time Processing Implementation Highlights”1. The C callback function (ctypes.WINFUNCTYPE)
Section titled “1. The C callback function (ctypes.WINFUNCTYPE)”PUC_BeginXferData automatically calls the Python-side function from an internal SDK thread whenever a new data frame is received from the camera. WINFUNCTYPE is used to define the type for the interface with C.
CALLBACK_FUNC = WINFUNCTYPE(None, POINTER(PUC_XFER_DATA_INFO), c_void_p)2. Thread-safe frame updates (threading.Lock)
Section titled “2. Thread-safe frame updates (threading.Lock)”threading.Lock() is used to arbitrate access, preventing memory contention (screen flickering or inconsistency) that could occur if the SDK’s receive/decode thread (inside the callback) and the OpenCV rendering thread (the main loop) accessed the frame data at the same time.
