Image grabbing

The image retrieval process begins when the camera’s sensor data is read out and transferred to the host computer via the GigEVision protocol. This is known as acquisition. The acquisition can run for a specific number of frames or continue indefinitely until manually stopped.

As images arrive at the host, they are collected in an internal queue managed by ItalaApi’s acquisition engine. User application can then retrieve images from this queue one by one.

Warning

The user application is responsible for the lifetime of each image instance. After users are finished with an image, users must release it. This allows its memory to be reused by the acquisition engine for subsequent images.

The following examples demonstrate a basic workflow.

Use IDevice::GetNextImage() to retrieve an image. This method throws a GenICam::TimeoutException if no image is available within the specified timeout.

// Start the acquisition process on the camera
pDevice->StartAcquisition();

for (int i = 0; i < 100; i++)
{
  Itala::IImage* pImage = nullptr;
  try
  {
    // Ask for an image, waiting up to 500ms
    pImage = pDevice->GetNextImage(500);

    // Check if the image is incomplete due to packet loss
    if (pImage->IsIncomplete())
    {
      std::cout << "Incomplete image received. Skipping." << std::endl;
      continue; // The 'finally' block will still execute
    }

    // ... Process the image data via the IImage interface ...
  }
  catch (const GenICam::TimeoutException& e)
  {
    std::cout << "Timeout: No image available." << std::endl;
  }
  finally
  {
    // CRITICAL: Always dispose of the image to release its buffer
    if (pImage)
    {
      pImage->Dispose();
    }
  }
}

pDevice->StopAcquisition();

The retrieved image is accessed via the Itala::IImage interface, which provides properties like width, height, pixel format, and a pointer to the data buffer.

Use DEV_GetNextImage() to retrieve an image handle. Check the return code to determine if the operation was successful or timed out.

// Start the acquisition process on the camera
error = DEV_StartAcquisition(hDevice);

for (size_t i = 0; i < 100; i++)
{
  H_IMAGE hImage = NULL;
  // Ask for an image, waiting up to 500ms
  error = DEV_GetNextImage(hDevice, 500, &hImage);

  if (error == ItalaErrorTimeout) {
    printf("Timeout: No image available.\n");
    continue;
  }

  // Check if the image is incomplete
  bool isIncomplete = false;
  error = IMG_IsIncomplete(hImage, &isIncomplete);
  if (isIncomplete) {
    printf("Incomplete image received. Skipping.\n");
  } else {
    // ... Process the image data using IMG_ functions with hImage ...
  }

  // CRITICAL: Always dispose of the image to release its buffer
  error = IMG_Dispose(hImage);
  hImage = NULL;
}

error = DEV_StopAcquisition(hDevice);

The retrieved image is accessed via the H_IMAGE handle, which can be passed to various IMG_ functions to get its properties and data.

Use IDevice.GetNextImage(), which throws an exception on timeout. The recommended approach is to use a using block, which guarantees that Dispose() is called on the image, even if errors occur.

// Start the acquisition process on the camera
device.StartAcquisition();

for (int i = 0; i < 100; i++)
{
  try
  {
    // The 'using' block ensures image.Dispose() is called automatically
    using (IImage image = device.GetNextImage(500))
    {
      // Check if the image is incomplete
      if (image.IsIncomplete)
      {
          Console.WriteLine("Incomplete image received. Skipping.");
          continue;
      }

      // ... Process the image data via the IImage interface ...
    }
  }
  catch (Exception e) // Catch a more specific timeout exception if available
  {
    Console.WriteLine("No image available.");
    continue;
  }
}

device.StopAcquisition();

The retrieved image is accessed via the Itala.IImage interface, which provides properties like Width, Height, PixelFormat, and access to the data buffer.

Use IDevice.get_next_image(), which raises an exception on timeout. The recommended Pythonic approach is to use a with statement to ensure the image’s dispose() method is called automatically.

# Start the acquisition process on the camera
device.start_acquisition()

for i in range(100):
  try:
    # The 'with' statement ensures image.dispose() is called automatically
    with device.get_next_image(500) as image:
      # Check if the image is incomplete
      if image.is_incomplete:
        print("Incomplete image received. Skipping.")
        continue

      # ... Process the image ...

  except Exception as e:
    print(f"No image available: {e}")
    continue

device.stop_acquisition()

The image is accessed via the itala.IImage class.

Working with Image Data

To use the image data with external libraries like NumPy and OpenCV, users must first get a pointer to the raw buffer and then wrap it in an appropriate data structure.

import ctypes
import numpy as np
import cv2

# (Inside the acquisition loop from above)
with device.get_next_image(500) as image:
  if image.is_incomplete:
    continue

  # 1. Get the raw buffer pointer
  buffer_ptr = image.get_data()

  # 2. Define the buffer type based on image properties (e.g., Mono8)
  pixel_format = image.pixel_format # Assuming this returns a known format
  height = image.height
  width = image.width

  if pixel_format == "Mono8": # Example check
    buffer_size = width * height
    # Create a ctypes array pointer of the correct type and size
    c_uint8_p = ctypes.POINTER(ctypes.c_uint8 * buffer_size)

    # Cast the raw pointer to the typed pointer and get its contents
    data = ctypes.cast(buffer_ptr, c_uint8_p).contents

    # 3. Create a NumPy array that shares memory with the buffer (no copy)
    numpy_array = np.frombuffer(data, dtype=np.uint8)

    # 4. Reshape to image dimensions and use with OpenCV
    cv_image = numpy_array.reshape((height, width))
    cv2.imwrite("image.jpg", cv_image)

Network configuration for reliability

Warning

The filter driver and packet resend functionalities are enabled by default for a more reliable and efficient acquisition. The filter driver component must be installed and enabled on the Network Interface Card (NIC) the camera is connected to. These functionalities can be configured or disabled via the DataStream nodemap.