Skip to content

X2TestAccuracy

Test scanner accuracy in binocular mode. Take Win 10 system as an example, the steps are as follows:

RVC Scanner Accuracy Testing Procedure

1. Build the Python runtime environment

This step can be referred to Python SDK configuration.

a. Install Python: Python 3.7-Python 3.10, recommended version: Python 3.7.9.

b. Install RyRVC module. Enter it in the Command Prompt:

pip3 install PyRVC

c. Install NumPy.

pip3 install numpy

d. Install OpenCV-Python.

pip3 install opencv-python 

e. Install Matplotlib.

pip3 install matplotlib

2. Select a suitable calibration board

According to the working distance of the scanner, determine the appropriate size of the calibration board, and then determine the center distance and specifications of the calibration board.

Take the A6 calibration board as an example, A6:0.02 means the center distance is 0.02 m. You need to select the calibration board as shown in the figure below according to the parameters marked on the calibration board. Detailed specifications and diagrams of the calibration board are shown in RVC Calibration Board Dimensions.

Calibration Board specification A2 A3 A4 A5 A6 A7 A8 A9 A10
Center distance (m) 0.08 0.056 0.04 0.028 0.02 0.014 0.01 0.007 0.0048

CaliboardA6

3. Adjust capture parameters

Take 2D and 3D captures of the calibration board, adjust the capture parameters in RVCManager until the satisfactory result is achieved, and record the capture parameters at this time.

Go to the folder: /RVCSDK/examples/Python in the RVC installation directory, find the binocular mode accuracy test example X2TestAccuracy.py, locate it in following code, and change it to the capture parameters recorded earlier.

# Set capture parameters
cap_opt = RVC.X2_CaptureOptions()
# Transform point map's coordinate to left/right(RVC.CameraID_Left/RVC.CameraID_Right) camera or reference
# plane(RVC.CameraID_NONE)
cap_opt.transform_to_camera = RVC.CameraID_Left
# Set 2d and 3d exposure time. Capture with white light, range [11, 100]ms, others [3, 100]ms.
cap_opt.exposure_time_2d = 20
cap_opt.exposure_time_3d = 20
# Set 2d and 3d gain. the default value is 0. The gain value of each series cameras is different, you can call function GetGainRange() to get specific range.
cap_opt.gain_2d = 0
cap_opt.gain_3d = 0
# Set 2d and 3d gamma. the default value is 1. The gamma value of each series cameras is different, you can call function GetGammaRange() to get specific range.
cap_opt.gamma_2d = 1
cap_opt.gamma_3d = 1
# range in [0, 10], default = 5. The contrast of point less than this value will be treat * as invalid point and be removed.
cap_opt.light_contrast_threshold = 2
# edge control after point matching, range in [0, 10], default = 2. The big the value, the more edge * noise to be
# removed.
cap_opt.edge_noise_reduction_threshold = 0
cap_opt.capture_mode = RVC.CaptureMode_Ultra

4. Warm-up

In RVCManager, select the continuous capturing mode and cycle the capturing for 30 minutes to warm up.

5. Run the accuracy test example

Execute the command:

python ./X2TestAccuracy.py 1 A6 10

This command means that the script name is X2TestAccuracy.py, the Gamma value is 1, the calibration board specification is A6, and the number of accuracy tests is 10, these parameters can be modified according to the actual situation. Please make sure that the calibration board specification is accurate, otherwise it will lead to measurement error.

6. View Test Results

The accuracy test result will be displayed as a line graph, the vertical axis of the image is the accuracy deviation value, and the horizontal axis is the number of tests. If the accuracy deviation value is large (e.g. up to millimeter level), please contact technical support.

Example Code

# Copyright (c) RVBUST, Inc - All rights reserved.
import PyRVC as RVC
import sys
import os
import numpy as np
import cv2
import time

from Utils.CaliBoardUtils import *
from Utils.Tools import *


def App(gamma, pattern_type, capture_times):

    # Initialize RVC X system
    RVC.SystemInit()

    # Choose RVC X Camera type (USB, GigE or All)
    opt = RVC.SystemListDeviceTypeEnum.All

    # Scan all RVC X Camera devices
    ret, devices = RVC.SystemListDevices(opt)
    print("RVC X Camera devices number:", len(devices))

    # Find whether any RVC X Camera is connected or not
    if len(devices) == 0:
        print("Can not find any RVC X Camera!")
        RVC.SystemShutdown()
        exit(1)

    # Create a RVC X Camera
    x = RVC.X2.Create(devices[0])

    # Test RVC X Camera is valid or not
    if x.IsValid() == False:
        print("RVC X Camera is not valid!")
        RVC.X2.Destroy(x)
        RVC.SystemShutdown()
        exit(1)

    #PrintCaptureMode(devices[0])

    # Open RVC X Camera
    ret1 = x.Open()

    # Test RVC X Camera is opened or not
    if x.IsOpen() == False:
        print("RVC X Camera is not opened!")
        RVC.X2.Destroy(x)
        RVC.SystemShutdown()
        exit(1)

    # Print ExposureTime Range
    _, exp_range_min, exp_range_max = x.GetExposureTimeRange()
    print("ExposureTime Range:[{}, {}]".format(exp_range_min, exp_range_max))

    # Set capture parameters
    cap_opt = RVC.X2_CaptureOptions()
    # Transform point map's coordinate to left/right(RVC.CameraID_Left/RVC.CameraID_Right) camera or reference
    # plane(RVC.CameraID_NONE)
    cap_opt.transform_to_camera = RVC.CameraID_Left
    # Set 2d and 3d exposure time. Capture with white light, range [11, 100]ms, others [3, 100]ms.
    cap_opt.exposure_time_2d = 20
    cap_opt.exposure_time_3d = 20
    # Set 2d and 3d gain. the default value is 0. The gain value of each series cameras is different, you can call function GetGainRange() to get specific range.
    cap_opt.gain_2d = 0
    cap_opt.gain_3d = 0
    # Set 2d and 3d gamma. the default value is 1. The gamma value of each series cameras is different, you can call function GetGammaRange() to get specific range.
    cap_opt.gamma_2d = 1
    cap_opt.gamma_3d = 1
    # range in [0, 10], default = 5. The contrast of point less than this value will be treat * as invalid point and be removed.
    cap_opt.light_contrast_threshold = 2
    # edge control after point matching, range in [0, 10], default = 2. The big the value, the more edge * noise to be
    # removed.
    cap_opt.edge_noise_reduction_threshold = 0
    cap_opt.capture_mode = RVC.CaptureMode_Ultra

    # Create saving address of image and point map.
    save_dir = "Data"
    if not os.path.exists(save_dir):
        os.makedirs(save_dir)

    valid_cnt = 0
    fail_cnt = 0
    err_list = []

    i = 0
    while valid_cnt < capture_times and fail_cnt < 5:
        # Capture a point map and a image.
        t_start = time.time()
        ret2 = x.Capture(cap_opt)
        t_end = time.time()
        print("time cost ", t_end - t_start)
        if ret2 == True:
            # Get image data. choose left or right side. the point map is map to left image.
            img = x.GetImage(RVC.CameraID_Left)
            # Convert image to array and save it.
            img = np.array(img, copy=False)
            pm = np.array(x.GetPointMap(), copy=False).reshape(-1, 3)

            if 0 == i:
                # Save image and point map data, only save once to save time and space
                cv2.imwrite("{}/test.png".format(save_dir), img)
                print("Save image successed!")

                # Save point map (m) to file.
                if x.GetPointMap().Save("{}/test.ply".format(save_dir), RVC.PointMapUnitEnum.Meter):
                    print("Save point map successed!")
                else:
                    print("Save point map failed!")

            # Calculate accuracy by image and point cloud.
            ret3, error_mm = CalcAccuracy(img,
                                             pm,
                                             gamma=gamma,
                                             m_type=pattern_type)
            if ret3:
                valid_cnt += 1
                mean_err = np.mean(error_mm)
                err_list.append(mean_err)
                max_err = error_mm[np.argmax(np.abs(error_mm))]
                print(f"{valid_cnt} times accuracy test, mean error: {mean_err} mm, max_error: {max_err} mm")
            else:
                fail_cnt += 1

        else:
            print(RVC.GetLastErrorMessage())
            fail_cnt += 1
        i += 1

    if len(err_list) > 0:
        PlotError(err_list)
    else:
        print("no valid result, please adjust param as suggested!")

    # Close RVC X Camera
    x.Close()

    # Destroy RVC X Camera
    RVC.X2.Destroy(x)

    # Shut Down RVC X System
    RVC.SystemShutdown()


if __name__ == "__main__":
    """
        This demo shows how to get X2 accuracy.
        argv[1]: gamma (0~1), for adjust image brightness. gamma>1 will increse image brightness
                 and gamma<1 wille decrease image brightness
        argv[2]: pattern_type, type of cali board pattern used. You can choose A2, A3, ..., A10
                 Center distance of circles on cali borad (m):
                 A2:0.08
                 A3:0.056
                 A4:0.04
                 A5:0.028
                 A6:0.02
                 A7:0.014
                 A8:0.01
                 A9:0.007
                 A10:0.0048
        argv[3]: capture times, 10 - 100 recommended. Average error of N capture times will be returned
                 as result
        Please select a cali board pattern of appropriate size according to the working distance
        of 3D camera. For details, please consult technical support.
    """

    if len(sys.argv) != 4:
        sys.exit("Invalid arguments: Usage: python3 X2TestAccuracy.py 1 A4 10")

    gamma = sys.argv[1]
    pattern_type = sys.argv[2]
    capture_times = sys.argv[3]

    print("gamma: {}, pattern_type: {}, capture_times: {}".format(
        gamma, pattern_type, capture_times))

    gamma = float(gamma)
    capture_times = int(capture_times)
    App(gamma, pattern_type, capture_times)