IDS peak ICV v1.5.0
Loading...
Searching...
No Matches
Camera Calibration

Geometric camera calibration is an important image processing technique used to compute intrinsic and extrinsic parameters of a camera system. These parameters characterize the mapping between 3D points in the world and their corresponding 2D projections in the image plane.

Recommended application scenario

The intrinsic and extrinsic parameters obtained from camera calibration serve a wide range of purposes in computer vision.

  • Measurement: Calibration is indispensable for precise measurements in applications where accurate dimensions are critical. It ensures that measurements derived from images or sensors are accurate and consistent.
  • Image Undistortion: It corrects distortions caused by the camera lens, resulting in undistorted images that are crucial for downstream tasks like feature detection and matching.
  • Stereo Vision: In stereo vision applications depth perception is derived from images captured by multiple cameras. Accurate calibration ensures the alignment of corresponding points in the stereo image pairs, enabling precise 3D reconstruction.

Requirements

Calibration Plate

To perform a calibration you need:

  • a calibration plate from IDS Imaging Development Systems GmbH which you can directly obtain from the sales department.
  • a corresponding description file, which can be downloaded from here.
  • to check the calibration plate for stains or damage (e.g. scratches), as these have a negative influence on the quality of the calibration.

Images

To ensure a successful calibration process, adhere to the following guidelines when capturing images of the calibration plate:

  1. Capture at least 10 to 15 images with different poses of the calibration plate. We recommended to capture one or two additional images in case the markers are not detected in individual shots.
  2. Configure the camera with the following settings:
    • Set a fix aperture. Changes in brightness can be readjusted using the camera's exposure time while taking the images, if required.
    • Set a fix focus, respectively focal length.
    • Note: If you change aperture or focus you have to recalibrate the camera.
    • Strictly avoid any non-linear transformations (e.g., gamma correction) during image capture.
  3. Pay attention to the following quality criteria when taking the images:
    • Achieve optimal contrast between the background and calibration marks.
    • Preferably use homogeneous lighting conditions for even exposure. Avoid overexposure under all circumstances.
    • Save the captured images in an uncompressed format. Compression artifacts can compromise calibration accuracy.
  4. Position the calibration plate in the image according to the following guidelines:
    • Maximize the calibration mark diameter in the image while ensuring the calibration plate remains fully visible. The calibration plate should cover at least a quarter of the image.
    • Move the calibration plate across the entire image field. Move the plate as far as possible into the corners, ensuring the pattern remains fully visible.
    • Capture images with a tilted calibration plate, up to an angle of 45°, to ensure a comprehensive calibration.

Usage instructions

To perform a camera calibration using one of the provided interfaces, follow the steps below:

  • C++
    // Create a CameraCalibration object for a specific calibration plate
    peak::icv::CalibrationPlate calibrationPlate{ "radon-checkerboard-marker-65mm-6x6.json" };
    peak::icv::CameraCalibration calibration{ calibrationPlate };
    //
    // Store images of the calibration plate in different poses into a vector
    std::vector<peak::icv::Image> images = ReadImages();
    //
    // Carry out the calibration
    auto calibrationResult = calibration.Process(images);
    //
    // Evaluate the calibration by checking the mean reprojection error
    std::cout << "Mean reprojection error: " << calibrationResult.GetMeanReprojectionError() << std::endl;
  • C#
    // Create a CameraCalibration object for a specific calibration plate
    using var calibrationPlate = new CalibrationPlate("radon-checkerboard-marker-65mm-6x6.json");
    var cameraCalibration = new CameraCalibration(calibrationPlate);
    //
    // Store images of the calibration plate in different poses into a list
    using var images = SnippetHelper.ReadImagesFromDir("calibration_images");
    //
    // Carry out the calibration
    using var calibrationResult = cameraCalibration.Process(images);
    //
    // Evaluate the calibration by checking the mean reprojection error
    Console.WriteLine("Mean reprojection error: {0}", calibrationResult.MeanReprojectionError);
  • Python
    # Create a CameraCalibration object for a specific calibration plate
    calibration_plate = CalibrationPlate.create_from_file("radon-checkerboard-marker-65mm-6x6.json")
    camera_calibration = CameraCalibration.create_from_plate(calibration_plate)
    #
    # Store images of the calibration plate in different poses into a list
    images = read_images()
    #
    # Carry out the calibration
    calibration_result = camera_calibration.process(images)
    #
    # Evaluate the calibration by checking the mean reprojection error
    print("Mean reprojection error: ", calibration_result.mean_reprojection_error)

Individual steps

Create a CameraCalibration object

The calibration process is facilitated using an instance of the CameraCalibration class. Since calibration relies on the known positions of world points (specifically, the checkerboard corners), this positional data must be provided to the instance of CameraCalibration.

The world points are stored in a description file, which can be loaded using the CalibrationPlate class.

Once the CalibrationPlate object has been initialized, it must be used to create a CameraCalibration object.

Take images of the calibration plate

To determine the calibration parameters, images of a calibration plate captured from various poses are required. These images must be stored in an array (see the API Reference for the specific type used).

Target Target Target Target

Carry out the calibration

The parameters are calculated by the process function of the CameraCalibration class. Since this process needs the images, the array containing the images must be passed to the function. The function returns an instance of CalibrationResults that contains the determined parameters. See Result of the Calibration for details.

Check the error

Check the mean reprojection error of the calibration process to ensure it is below 0.25. This value is stored in the CalibrationResult object returned by the process function.

Persisting Results

Save Calibration Results to a File

Once the calibration has been successfully completed and validated, the resulting parameters can be stored for later use. The preferred method is to save the calibration result to a file. This allows you to reload and reuse the parameters without repeating the calibration process.

  • C++
    // Save calibration parameters to a file for later use
    calibrationWriter.Write("calibration_result.json", calibrationResult);
  • C#
    // Save calibration parameters to a file for later use
    var calibrationResultWriter = new CalibrationResultWriter();
    calibrationResultWriter.Write("calibration_result.json", calibrationResult);
  • Python
    # Save calibration parameters to a file for later use
    calibration_result.save("calibration_result.json")

To load calibration parameters from a file, use the corresponding constructor:

  • C++
    // Load calibration parameters from file
    peak::icv::CalibrationResult calibrationResultRead{ "calibration_result.json" };
  • C#
    // Load calibration parameters from file
    using var loadedCalibrationResult = new CalibrationResult("calibration_result.json");
  • Python
    # Load calibration parameters from file
    calibration_result = CalibrationResult.create_from_file("calibration_result.json")

Upload Calibration Parameters to the Camera

As an alternative to file-based storage, you can upload the calibration parameters directly to the camera’s internal memory. This requires converting the parameters to a binary format and using the FileAdapter class from the IDS peak genericAPI.

  • C++
    #include <peak/peak.hpp>
    // Get the CalibrationParameters from the CalibrationResult
    auto calibrationParameters = calibrationResult.GetCalibrationParameters();
    // Convert to binary format in order to be able to write it to the camera
    auto binaryCalibrationParameters = calibrationParameters.ToBinary();
    // Upload CalibrationParameters to the camera
    peak::core::file::FileAdapter fileAdapter(nodeMapRemoteDevice, "LensCalibrationData");
    auto dataWrite = reinterpret_cast<uint8_t*>(&binaryCalibrationParameters);
    fileAdapter.Write(dataWrite, sizeof(peak_icv_calibration_parameters));
  • C#
    // Get the CalibrationParameters from the CalibrationResult
    var calibrationParameters = calibrationResult.CalibrationParameters;
    //
    // Convert to binary format in order to be able to write it to the camera
    var binaryCalibrationParameters = calibrationParameters.ToBinary();
    //
    // Upload CalibrationParameters to the camera
    using var fileAdapter = new FileAdapter(nodeMapRemoteDevice, "LensCalibrationData");
    //
    fileAdapter.Write(new ByteCollection(binaryCalibrationParameters));
  • Python
    import numpy as np
    from ids_peak_icv.calibration.calibration_parameters import CalibrationParameters
    from ids_peak import ids_peak
    # Get the CalibrationParameters from the CalibrationResult
    calibration_parameters = calibration_result.calibration_parameters
    # Convert to binary format in order to be able to write it to the camera
    binary_calibration_parameters = calibration_parameters.to_binary()
    # Upload CalibrationParameters to the camera
    file_adapter = ids_peak.FileAdapter(node_map_remote_device, "LensCalibrationData")
    file_adapter.Write(binary_calibration_parameters.tobytes())

To download the parameters back from the camera, use the Read method of the FileAdapter:

  • C++
    // Download CalibrationParameters from the camera
    std::vector<uint8_t> dataRead(sizeof(peak_icv_calibration_parameters));
    fileAdapter.Read(dataRead.data(), sizeof(peak_icv_calibration_parameters));
    peak::icv::CalibrationParameters calibrationParametersRead{dataRead};
  • C#
    // Download CalibrationParameters from the camera
    var calibrationParametersReadBinary = fileAdapter.Read((ulong)binaryCalibrationParameters.Length);
    var calibrationParametersRead = new CalibrationParameters(calibrationParametersReadBinary);
  • Python
    # Download CalibrationParameters from the camera
    read_bytes = file_adapter.Read(binary_calibration_parameters.size)
    read_back_binary_calibration_parameters = CalibrationParameters.create_from_binary(np.frombuffer(read_bytes).copy())

Result of the Calibration

The calibration result represents the outcome of a camera calibration process. It includes the calibration parameters, the mean reprojection error of the calibration and detailed information about each processed image, referred to as a calibration view.

This calibration result can be used in functions that require calibration parameters, and the type will be automatically converted as needed. However, if there is more than one calibration view in the calibration result, the extrinsic parameters are set to the identity matrix. This conversion is one-way and cannot be reversed.

For example, the calibration parameters can be applied to correct lens-induced distortion and produce an undistorted image.

Original image Undistorted image
Distorted image Undistorted image

Reprojection error

It describes a geometric error corresponding to the distance between a projected point and a measured marker point in an image.

Typically, this error should be minimized to below 0.25, although the desired accuracy may vary depending on the application.

Calibration parameters

Calibration parameters consist of the intrinsic and extrinsic parameters.

  • Intrinsic parameters consist of distortion coefficients, the focal length expressed in pixel units, and the principal point. These parameters are essential for tasks such as image undistortion and point cloud generation.
  • Extrinsic parameters consist of a rotation and a translation, which typically describe a pose of an object. Both are essential for a workspace calibration.

For a basic camera calibration the extrinsic parameters are all set to zero, because no pose is selected during camera calibration. In fact each calibration view contains the pose of the calibration plate in the image.

Calibration view

To calibrate a camera several images of different poses of the calibration plate are necessary. For each of those images the following parameters are determined and stored in the calibration view:

Reprojection errors: A list of reprojection errors, where each error corresponds to a detected marker point. These errors offer statistical insights and help assess the calibration process quality.

Each entry includes the following details:

  • Position: The location of the detected marker in the image coordinate system.
  • Direction vector: A (x, y) vector that describes the reprojection error, including directional information.
  • Length: It describes a geometric error corresponding to the distance between a projected point and a measured marker point in an image, representing the reprojection error.

Mean reprojection error: The mean reprojection error is calculated across all marker points from the current calibration view. For more details on reprojection error, see chapter reprojection error.

Maximum reprojection error: This is the maximum reprojection error, measured by distance, found among the list of reprojection errors.

Use saved calibration parameters

To use saved calibration parameters using one of the provided interfaces, follow the steps below:

  • C++
    // Option 1
    // Load calibration parameters from file
    peak::icv::CalibrationParameters calibrationParameters{ "path/to/load/calibration_parameters.json" };
    // Create an instance of Undistortion with CalibrationParameters
    peak::icv::Undistortion undistortion{ calibrationParameters };
    // Option 2
    // Load calibration result from file
    peak::icv::CalibrationResult calibrationResult{ "path/to/load/calibration_result.json" };
    // Create an instance of Undistortion with CalibrationParameters
    peak::icv::Undistortion undistortion{ calibrationResult };
    // Option 3
    // Extract calibration parameters from calibration result loaded from file
    peak::icv::CalibrationResult calibrationResult{ "path/to/load/calibration_result.json" };
    peak::icv::CalibrationParameters calibrationParameters{ calibrationResult.GetCalibrationParameters() };
    // Create an instance of Undistortion with CalibrationParameters
    peak::icv::Undistortion undistortion{ calibrationParameters };
    // Option 4
    // Extract calibration parameters from calibration result loaded from file
    peak::icv::CalibrationResult calibrationResult{ "path/to/load/calibration_result.json" };
    peak::icv::CalibrationParameters calibrationParameters{ calibrationResult.GetCalibrationParameters() };
    // Create an instance of Undistortion with IntrinsicParameters
    peak::icv::Undistortion undistortion{ calibrationParameters.GetIntrinsicParameters() };
  • C#
    // Option 1
    // Load calibration parameters from file
    var calibrationParameters = new CalibrationParameters("path/to/load/calibration_parameters.json");
    // Create an instance of Undistortion with CalibrationParameters
    using var undistortion = new Undistortion(calibrationParameters);
    // Option 2
    // Load calibration result from file
    using var calibrationResult = new CalibrationResult("path/to/load/calibration_result.json");
    // Create an instance of Undistortion with CalibrationParameters
    using var undistortion = new Undistortion(calibrationResult);
    // Option 3
    // Extract calibration parameters from calibration result loaded from file
    using var calibrationResult = new CalibrationResult("path/to/load/calibration_result.json");
    var calibrationParameters = calibrationResult.CalibrationParameters;
    // Create an instance of Undistortion with CalibrationParameters
    using var undistortion = new Undistortion(calibrationParameters);
    // Option 4
    // Extract calibration parameters from calibration result loaded from file
    using var calibrationResult = new CalibrationResult("path/to/load/calibration_result.json");
    var calibrationParameters = calibrationResult.CalibrationParameters;
    // Create an instance of Undistortion with IntrinsicParameters
    using var undistortion = new Undistortion(calibrationParameters.IntrinsicParameters);
  • Python
    # Option 1
    # Load calibration parameters from file
    calibration_parameters = CalibrationParameters.create_from_file("path/to/load/calibration_parameters.json")
    # Create an instance of Undistortion with CalibrationParameters
    undistortion = Undistortion(calibration_parameters)
    # Option 2
    # Load a calibration result from file
    calibration_result = CalibrationResult.create_from_file("path/to/load/calibration_result.json")
    # Create an instance of Undistortion with CalibrationResult
    undistortion = Undistortion(calibration_result)
    # Option 3
    # Extract calibration parameters from calibration result loaded from file
    calibration_result = CalibrationResult.create_from_file("path/to/load/calibration_result.json")
    calibration_parameters = calibration_result.calibration_parameters
    # Create an instance of Undistortion with CalibrationParameters
    undistortion = Undistortion(calibration_parameters)
    # Option 4
    # Create an instance of Undistortion with IntrinsicParameters
    undistortion = Undistortion(calibration_parameters.intrinsic_parameters)