Skip to content
⚡ Developer documentation for INFINICAM, the real-time high-speed camera (UC-1.1 / GbE-2)

scikit-image Analysis & Contour Extraction (GbE-2 / Python)

Steps for creating a program that uses the common module puclib.py created in HelloWorld to perform scientific-computing-grade image analysis (thresholding and contour extraction) with scikit-image (skimage) and matplotlib on an image captured from the GbE-2, and saves the results.

  1. Create the script

    In the same folder as puclib.py, create gbe2_skimage_single_process.py and write the following code.

    gbe2_skimage_single_process.py
    from ctypes import c_uint32, c_ushort, c_ubyte, c_void_p, byref
    import numpy as np
    import matplotlib.pyplot as plt
    from skimage import filters, measure
    # Import from the common module puclib.py
    from 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 scikit-image analysis sample...")
    # 1. Load and initialize the SDK
    puclib = load_sdk()
    if puclib.PUC_Initialize() != PUC_SUCCEEDED:
    print("Error: Failed to initialize the SDK.")
    return
    # 2. Search for and open the device
    detect_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.")
    return
    h_device = c_void_p()
    if puclib.PUC_OpenDevice2(0, byref(h_device)) != PUC_SUCCEEDED:
    print("Error: Failed to open the device.")
    return
    # 3. Retrieve the resolution, quantization table, and transfer size
    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)
    xfer_data_size = c_uint32()
    puclib.PUC_GetXferDataSize(h_device, byref(xfer_data_size))
    print(f"Resolution: {w} x {h} pixels")
    # 4. Allocate buffers
    comp_buffer = (c_ubyte * xfer_data_size.value)()
    line_bytes = (w + 3) & ~3 # 4-byte boundary alignment
    decoded_buffer = (c_ubyte * (line_bytes * h))()
    # 5. Perform the single-frame capture
    xfer_info = PUC_XFER_DATA_INFO()
    xfer_info.pData = comp_buffer
    xfer_info.nDataSize = xfer_data_size.value
    print("Capturing one frame...")
    if puclib.PUC_GetSingleXferData(h_device, byref(xfer_info)) == PUC_SUCCEEDED:
    # 6. Decode processing
    ret = puclib.PUC_DecodeData(
    decoded_buffer, 0, 0, w, h, line_bytes, comp_buffer, q_vals
    )
    if ret == PUC_SUCCEEDED:
    # 7. Convert into a NumPy array
    img = np.ctypeslib.as_array(decoded_buffer).reshape((h, line_bytes))[:, :w]
    # 8. Analysis processing with scikit-image
    # Determine an automatic threshold that maximizes between-class variance using Otsu's method
    thresh = filters.threshold_otsu(img)
    binary_img = img > thresh
    # Detect contours on the binarized image using a marching-squares-based algorithm
    contours = measure.find_contours(binary_img, 0.5)
    # 9. Draw and plot the analysis images with Matplotlib
    fig, ax = plt.subplots(1, 2, figsize=(10, 5))
    # Left: original image
    ax[0].imshow(img, cmap='gray')
    ax[0].set_title('Original Image')
    ax[0].axis('off')
    # Right: binarized image with the extracted contour lines overlaid (in red)
    ax[1].imshow(binary_img, cmap='gray')
    for contour in contours:
    ax[1].plot(contour[:, 1], contour[:, 0], linewidth=1.5, color='red')
    ax[1].set_title(f'Otsu Thresholding & Contours (Threshold: {thresh:.1f})')
    ax[1].axis('off')
    plt.tight_layout()
    # Save
    filename = "skimage_analysis_result.png"
    plt.savefig(filename, bbox_inches='tight', dpi=150)
    print(f"SUCCESS: Saved the analysis result plot ({filename})")
    # Display
    plt.show()
    else:
    print(f"Error: Failed to decode the image data. ErrorCode: {ret}")
    else:
    print("Error: Failed to retrieve the image data.")
    # 10. Close
    puclib.PUC_CloseDevice(h_device)
    if __name__ == "__main__":
    main()
  2. Run the script

    Terminal window
    python gbe2_skimage_single_process.py

    When run, a Matplotlib graph window opens showing the original image on the left, and on the right the binarized image split at the Otsu threshold along with the detected contour lines (in red). Closing the window saves skimage_analysis_result.png in the current directory.


1. Automatic thresholding (filters.threshold_otsu)

Section titled “1. Automatic thresholding (filters.threshold_otsu)”

From the image’s histogram, a single threshold is statistically determined that best separates the foreground (subject) from the background. This is extremely powerful for automatic object-region extraction in environments without fixed brightness.

2. High-precision contour extraction (measure.find_contours)

Section titled “2. High-precision contour extraction (measure.find_contours)”

Rather than working pixel by pixel, this interpolates along the continuity of boundaries to obtain contour lines as precise 2D coordinate lists. It is useful as a preprocessing step for measuring object area, perimeter, circularity, and other instrumentation or shape-analysis tasks.