SingleImage (PGM Save) Project (GbE-2 / Python)
Steps for creating a script that uses the common module puclib.py created in HelloWorld to capture and decode one frame of compressed image data from the GbE-2, and save it as a PGM (Portable Graymap) file.
-
Create the script
In the same folder as
puclib.py, creategbe2_single_image_pgm.pyand write the following code.gbe2_single_image_pgm.py from ctypes import c_uint32, c_ushort, c_ubyte, c_void_p, byrefimport numpy as np# 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 SingleImage (PGM) capture...")# 1. Load and initialize the SDKpuclib = load_sdk()if puclib.PUC_Initialize() != PUC_SUCCEEDED:print("Error: Failed to initialize the SDK.")return# 2. 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# 3. 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)xfer_data_size = c_uint32()puclib.PUC_GetXferDataSize(h_device, byref(xfer_data_size))print(f"Resolution: {w} x {h} pixels")# 4. Allocate bufferscomp_buffer = (c_ubyte * xfer_data_size.value)()line_bytes = (w + 3) & ~3 # 4-byte boundary alignmentdecoded_buffer = (c_ubyte * (line_bytes * h))()# 5. Perform the capturexfer_info = PUC_XFER_DATA_INFO()xfer_info.pData = comp_bufferxfer_info.nDataSize = xfer_data_size.valueprint("Capturing one frame...")if puclib.PUC_GetSingleXferData(h_device, byref(xfer_info)) == PUC_SUCCEEDED:# 6. Decode processingret = puclib.PUC_DecodeData(decoded_buffer, 0, 0, w, h, line_bytes, comp_buffer, q_vals)if ret == PUC_SUCCEEDED:# 7. Convert the ctypes buffer into a NumPy array (remove padding)img_np = np.ctypeslib.as_array(decoded_buffer).reshape((h, line_bytes))[:, :w]# 8. Save the file in PGM (P5) formatfilename = "captured_image.pgm"with open(filename, "wb") as f:header = f"P5\n{w} {h}\n255\n".encode("ascii")f.write(header)f.write(img_np.tobytes())print(f"SUCCESS: Saved the PGM image file ({filename})")else:print(f"Error: Failed to decode the image data. ErrorCode: {ret}")else:print("Error: Failed to retrieve the image data.")# 9. Closepuclib.PUC_CloseDevice(h_device)if __name__ == "__main__":main() -
Run the script
Terminal window python gbe2_single_image_pgm.pyAfter execution finishes,
captured_image.pgmwill be generated in the current directory.
Code Explanation Highlights
Section titled “Code Explanation Highlights”1. Significant code reduction through the common module
Section titled “1. Significant code reduction through the common module”By calling puclib.py, there is no longer any need to write the DLL type definitions or C struct declarations directly in the script.
from puclib import ( load_sdk, PUC_SUCCEEDED, PUC_DETECT_TARGET_GBE2, PUC_Q_COUNT, PUC_DETECT_FILTER, PUC_DETECT_INFO, PUC_XFER_DATA_INFO)2. Converting a ctypes buffer into a NumPy array
Section titled “2. Converting a ctypes buffer into a NumPy array”Using np.ctypeslib.as_array(), the decode buffer (decoded_buffer) can be turned directly into a NumPy array with no memory copy.
img_np = np.ctypeslib.as_array(decoded_buffer).reshape((h, line_bytes))[:, :w]reshape((h, line_bytes)): Rearranges the data into a 2D shape that accounts for the 4-byte boundary alignment (line_bytes).[:, :w]: Cuts off the extra padding bytes automatically appended to the end of each row for boundary alignment, extracting the actual image size (w x h).
