How to use OpenCV camera calibration to set Physical Camera parameters?

I have calibrated data - camera parameters (attached below). How do I use this to set the Physical Camera parameters in Unity to recreate my real life camera?

My confusions are specifically:

  1. How to add focal length?

4706786--444632--upload_2019-7-2_10-44-48.png
Camera (intrinsic matrix) is the above, which has

  • → a principal point that is usually at the image center
  • → are the focal lengths expressed in pixel units.

The focal length in Unity (I suspect) can’t be in pixel units. Is there some way of retrieving focal length in meters from focal length expressed in pixel units?

  1. Is the Sensor Size the same as cx, cy → principal point?
    I notice that if I change my Sensor size, even if my focal length is fixed, the field of view changes, so it seems strange to me. Shouldn’t FOV always be fixed for a fixed focal length?

  2. What part of the camera parameters from OpenCV correspond to lens shift? Or is that assumed to be some default value?

  3. I am guessing the answer to this is No - Can you model distortion parameters into Unity camera?

Source - Open CV : Camera calibration Camera Calibration and 3D Reconstruction — OpenCV 2.4.13.7 documentation

Thank you!

Camera

#YAML File
CAMERA Parameters from OpenCV
image_width: 0
image_height: 1080
camera_name: left
camera_matrix:
  rows: 3
  cols: 3
  data: [1643.55164017145, 0, 833.842174850277, 0, 1632.81195514379, 657.989554730761, 0, 0, 1]
distortion_model: plumb_bob
distortion_coefficients:
  rows: 1
  cols: 5
  data: [-0.40444238705588, 0.581618979028972, -0.00497978193873161, 0.00232175743375933, -0.215474790066087]
rectification_matrix:
  rows: 3
  cols: 3
  data: [0.9987597352703238, 0.03749814884259891, 0.0327548475211089, -0.03730056012128149, 0.999282144850663, -0.006622929661203378, -0.03297968188735999, 0.00539294131591293, 0.9994414724067496]
projection_matrix:
  rows: 3
  cols: 4
  data: [1199.817340845223, 0, 810.3841648101807, 0, 0, 1199.817340845223, 711.4899749755859, 0, 0, 0, 1, 0]

Oh this forum, I can upload file. (it is attached. go to the bottom of my post, then you can download pdf)

First, I’d recommend you to read this book from page 153 to 157 (http://cvrs.whu.edu.cn/downloads/ebooks/Multiple%20View%20Geometry%20in%20Computer%20Vision%20(Second%20Edition).pdf I think you already know, but just in case) to understand what is exact K after calibration (which is eqation (6.9) at page 157)

So K you have does not directly contain ether f or px(or py) and this is very important thing to understand first.

I made some note to explain what happens in unity.
After you read the note, you will understand my code :

public class IntrinsicSetup : MonoBehaviour {


    Camera mainCamera;
  
    public float f = 35.0f; // f can be arbitrary, as long as sensor_size is resized to to make ax,ay consistient

   // Use this for initialization
   void Start () {
        mainCamera = gameObject.GetComponent<Camera>();
        changeCameraParam();
    }

    public void changeCameraParam()
    {
        string path = "Assets/Resources/Intrinsic.txt";
        float ax, ay, sizeX, sizeY;
        float x0, y0, shiftX, shiftY;
        int width, height;

        string[] lines = File.ReadAllLines(path);
        string[] parameters = lines[1].Split(' ');
        string[] resolution = lines[3].Split(' ');

        ax = float.Parse(parameters[0]);
        ay = float.Parse(parameters[1]);
        x0 = float.Parse(parameters[2]);
        y0 = float.Parse(parameters[3]);

        width = int.Parse(resolution[0]);
        height = int.Parse(resolution[1]);

        sizeX = f * width / ax;
        sizeY = f * height / ay;

        //PlayerSettings.defaultScreenWidth = width;
        //PlayerSettings.defaultScreenHeight = height;

        shiftX = -(x0 - width / 2.0f) / width;
        shiftY = (y0 - height / 2.0f) / height;

        mainCamera.sensorSize = new Vector2(sizeX, sizeY);     // in mm, mx = 1000/x, my = 1000/y
        mainCamera.focalLength = f;                            // in mm, ax = f * mx, ay = f * my
        mainCamera.lensShift = new Vector2(shiftX, shiftY);    // W/2,H/w for (0,0), 1.0 shift in full W/H in image plane

    }
}

here, you can use your camera_matrix.
now yours is
ax, 0, x0, 0, ay, y0, 0, 0, 1. (so what you have is not fx! its fx*mx=ax)

I didn’t try with distortion. So I cannot help you with it. However I saw in some unity documentation of giving some waving effect. Maybe you can give distortion as effect, but I won’t be like giving distortion coefficient to reproducing your distortion

4737242–449024–printed_version.pdf (1.51 MB)

4 Likes

Thank you so much for this detailed answer! The notes and the resource you provided were really really good.

I have a follow-up question though. In this answer (https://answers.unity.com/questions/814701/how-to-simulate-unity-pinhole-camera-from-its-intr.html?childToView=1645305), you mentioned that there is a minus sign in LensShiftX, which I don’t see in the note - did you miss that by mistake?

A

Ahhhh… that one … If you see my original answer from other post, you can see I wrote “//somehow this is opposite sign” I have no idea to be honest. I am assuming this is rather caused by convention difference … :p, like when it comes to lens shift, which direction it starts & where is origin of image something like these always confuse me

Thank you!

Hi Sir,

i have same problem. i have the parameter matrix of my camera and i wann visualise it in Unity could u help me please with the program anf thank u

[code=CSharp]%YAML:1.0
---
calibration_time: "Fri Oct  2 16:43:44 2020"
image_width: 640
image_height: 480
board_width: 9
board_height: 6
square_size: 5.2000001072883606e-02
aspectRatio: 1.
flags: 2
camera_matrix: !!opencv-matrix
   rows: 3
   cols: 3
   dt: d
   data: [ 6.4054031826016183e+02, 0., 3.0338619644214515e+02, 0.,
       6.4054031826016183e+02, 2.5601243873490392e+02, 0., 0., 1. ]
distortion_coefficients: !!opencv-matrix
   rows: 5
   cols: 1
   dt: d
   data: [ -7.3933578764705618e-02, 4.7089239158550916e-01,
       5.4172605723194515e-03, -5.6869323277609161e-03,
       -1.0417712178987861e+00 ]
avg_reprojection_error: 3.5360094587309865e-01

[/code]