Question about US cone calibration result

Hi ImFusion team,

I used the following code to do spatial calibration:

sweeps=[sweep1,sweep2]
parameters=imfusion.algorithmProperties('Ultrasound;Cone Calibration', sweeps)
parameters.params()
parameters['modelPath']="./model/cones.yaml"
imfusion.executeAlgorithm('Ultrasound;Cone Calibration', sweeps,parameters)

How should I interpret the result? How could I get the Calibration Matrix and calibration error? In C++, I could use UltrasoundConeCalibrationAlgorithm::EstimatedCalibration, but I could not found corresponding method in Python.

Example algorithm output:

[UltrasoundConeCalibrationAlgorithm] Matched cones with heights: 52.7048 51.0477
[UltrasoundConeCalibrationAlgorithm] Matched cones with heights: 52.7048 51.0477
[UltrasoundConeCalibrationAlgorithm] Matched cones with heights: 19.2437 19.0725
[UltrasoundConeCalibrationAlgorithm] Matched cones with heights: 19.2437 19.0725
[UltrasoundConeCalibrationAlgorithm] Matched cones with heights: 19.2437 21.6618
[UltrasoundConeCalibrationAlgorithm] Matched cones with heights: 19.2437 21.6618
[UltrasoundConeCalibrationAlgorithm] Got 37 matches
[UltrasoundConeCalibrationAlgorithm] Got 37 matches
[UltrasoundConeCalibrationAlgorithm] Ransac took 767.571 ms
[UltrasoundConeCalibrationAlgorithm] Ransac took 767.571 ms
[UltrasoundConeCalibrationAlgorithm] Refining using image content
[UltrasoundConeCalibrationAlgorithm] Refining using image content
0 0 0 0 0 0 0 → 0.176383
0 0 0 0 0 0 0 → 0.176383
1 0 0 0 0 0 0 → 0.174917
1 0 0 0 0 0 0 → 0.174917
0 1 0 0 0 0 0 → 0.17553
0 1 0 0 0 0 0 → 0.17553
0 0 1 0 0 0 0 → 0.173214
0 0 1 0 0 0 0 → 0.173214
0 0 0 1 0 0 0 → 0.168651
0 0 0 1 0 0 0 → 0.168651
0 0 0 0 1 0 0 → 0.164981
0 0 0 0 1 0 0 → 0.164981
0 0 0 0 0 1 0 → 0.160965
0 0 0 0 0 1 0 → 0.160965
0 0 0 0 0 0 1 → 0.176383
0 0 0 0 0 0 1 → 0.176383
-1 0 0 0 0 0 0 → 0.175846
-1 0 0 0 0 0 0 → 0.175846
0 -1 0 0 0 0 0 → 0.175561
0 -1 0 0 0 0 0 → 0.175561
0 0 -1 0 0 0 0 → 0.176275
0 0 -1 0 0 0 0 → 0.176275
0 0 0 -1 0 0 0 → 0.16587
0 0 0 -1 0 0 0 → 0.16587
0 0 0 0 -1 0 0 → 0.164626
0 0 0 0 -1 0 0 → 0.164626
0 0 0 0 0 -1 0 → 0.174846
0 0 0 0 0 -1 0 → 0.174846
0 0 0 0 0 0 -1 → 0.176261
0 0 0 0 0 0 -1 → 0.176261
-0.16611 -0.00575179 -0.482038 0.0749996 0.0115297 -0.409379 0.02594 → 0.175183
-0.16611 -0.00575179 -0.482038 0.0749996 0.0115297 -0.409379 0.02594 → 0.175183
-0.106594 -0.00356937 0.249695 0.0766676 0.0072235 -0.412404 0.0164444 → 0.174865
-0.106594 -0.00356937 0.249695 0.0766676 0.0072235 -0.412404 0.0164444 → 0.174865
-0.126295 -0.00411429 -0.178986 0.0707732 0.009278 -0.094801 0.0203593 → 0.175333
-0.126295 -0.00411429 -0.178986 0.0707732 0.009278 -0.094801 0.0203593 → 0.175333
-0.0140629 -0.000465861 0.0940426 0.0286433 0.0032828 -0.011099 0.0018992 → 0.176171
-0.0140629 -0.000465861 0.0940426 0.0286433 0.0032828 -0.011099 0.0018992 → 0.176171
0.0456693 -7.88481e-05 -0.00820917 0.00703911 0.000900647 -0.0172182 0.000307769 → 0.176473
0.0456693 -7.88481e-05 -0.00820917 0.00703911 0.000900647 -0.0172182 0.000307769 → 0.176473
0.0740375 -0.000255488 -0.0407238 0.0224386 0.00257671 0.00272174 0.00098548 → 0.176633
50 evaluations in 11.856 seconds, success
50 evaluations in 11.856 seconds, success
-0.0865414 0.0318517 -0.0240927 0.0262888 -0.0516507 -0.0262292 0.966277 → 0.176921 (0.176689)

-0.0865414 0.0318517 -0.0240927 0.0262888 -0.0516507 -0.0262292 0.966277 → 0.176921 (0.176689)

Process finished with exit code 0

Could you please provide some help? Thanks in advance.

Hello,

At the end, the final calibration is applied to the two input sweeps. So for obtaining the matrix, you can just retrieve the calibration of sweep1.

Unfortunately, we currently don’t have Python bindings for this algorithms and its data structures, but I’ve created an internal ticket to add that.

Best,
Oliver

Hi Oliver,
Thanks a lot for your help. But I would like to get the calibration matrix transform 2D pixels to 3D points, which should be constant over all frames. But when I retrieved matrix from sweep1, I got 524 (# of frames) different matrix. Is it possible to get this matrix in Python?

Best,
Luohong

Hi,
There seems to be some confusion on which matrix is what.

If you ask an UltrasoundSweep which matrix a frame i has, it will:

  • check which TrackingSequence (previously we called this TrackingStream) is the main one,
  • check which timestamp frame i has,
  • call TrackingSequence::matrix() with either index i or the timestamp corresponding to i (plus temporal calibration) on the main one.

The TrackingSequence will then obtain the i-th tracking matrix (or interpolate a tracking pose for the given timestamp), let’s call that T.
The full matrix provided to the UltrasoundSweep is then R * T * C, where R is the registration matrix, and C the calibration matrix. While T is different for each frame, R and C are constant.

The calibration maps from the image center to the tracking target’s local coordinate system.

So, in C++ you need to call sweep->tracking()->calibration() to get C, and sweep->matrix(i) to obtain the full matrix mapping from image coordinates (again, we’re using the image center as origin, and mm as unit here - not pixels) to 3D world space. Mapping between image coordinates and pixel coordinates can be done via an image’s imageToPixelMatrix.

For all of these methods, there are identical Python bindings.

Best,
Oliver

Hi Oliver,

Thank you so much for your help and Explanation. Now, things are much clearer.

The matrix C is exactly what we needs. Since the clarius plugin can’t be used at the moment, I would like to calibrate our device, collect data and visualize them in ImFusion.

However, I still have two questions:

  1. What’s the meaning of the registration matrix R here? What object is the sweep registered to? I guess it’s a transformation matrix from tracking camera’s coordinate system to a certain coord in ImFusion.
  2. In the output of the calibration algorithm, -0.0865414 0.0318517 -0.0240927 0.0262888 -0.0516507 -0.0262292 0.966277 → 0.176921 (0.176689), does the last number means score (the lower, the better)?

Best,
Luohong