Unity Physical Camera如何使用真实摄像头内参

通过OpneCV等工具提供的标定方法[1],获得真实摄像头的针孔模型内参矩阵$K$:

$$K= {\begin{bmatrix} {f_x}&0&{c_x} \newline 0&{f_y}&{c_y} \newline 0&0&1 \end{bmatrix}}$$

Unity的Physcial Camera[2]仿真了真实世界的摄像头,可以将标定后的内参矩阵信息输入到Unity的Physcial Camera中,方便两者配合使用。

Unity中的转换方法:

using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Runtime.InteropServices;
using UnityEngine;
using UnityEngine.UI;

public class MyCamera : MonoBehaviour
{
public string camera_name = "Integrated Camera"; // USB Video Device //Integrated Camera //Virtual Camera
public int width = 1280;
public int height = 720;
public int fps = 120;
public float focal = 28F;
public float fx = 1087.4199F;
public float fy = 1087.4199F;
public float cx = 640F;
public float cy = 360F;
public float skew = 0F;
public AspectRatioFitter fit;
private RawImage cambackground = null;
private Camera cam_obj = null;
private WebCamTexture cam = null;
private volatile Color32[] cam_data = null;
private Texture2D tex = null;

IEnumerator Start()
{
cambackground = GameObject.FindWithTag("CamBackground").GetComponent<RawImage>();
cam_obj = GameObject.FindWithTag("MainCamera").GetComponent<Camera>();

yield return Application.RequestUserAuthorization(UserAuthorization.WebCam);

if (Application.HasUserAuthorization(UserAuthorization.WebCam))
{
WebCamDevice[] devices = WebCamTexture.devices;

if (devices.Length == 0)
{
Debug.Log("No camera detected!");
yield break;
}

bool find_camera = false;

for (int i = 0; i < devices.Length; i++)
{
Debug.Log("Found camera:" + devices[i].name);
if (camera_name.Equals(devices[i].name)) {
find_camera = true;
}
}

if (!find_camera)
{
Debug.Log("Unable to find camera: " + camera_name + "\n");
Debug.Log("Open the first camera" + devices[0].name + "\n");
camera_name = devices[0].name;
}

cam = new WebCamTexture(camera_name, width, height, fps);

WebCamTexture.allowThreadedTextureCreation = true;
WebCamTexture.streamingTextureDiscardUnusedMips = true;

cam.Play();

width = cam.width;
height = cam.height;

// ******************************************************
// Transfer Real Camera Inrinsic Parameters to Unity Physical Camera Parameters
cam_obj.usePhysicalProperties = true;
cam_obj.focalLength = focal;
cam_obj.sensorSize = new Vector2(focal * width / fx,
focal * height / fy);
cam_obj.lensShift = new Vector2(-(cx - width * 0.5f) / width,
(cy - height * 0.5f) / height);
// ******************************************************

Debug.Log(camera_name +" Running...\n");
}
}

void Update()
{
if (cam == null || !cam.isPlaying) return;

if (cam_data == null)
{
cam_data = new Color32[width * height];
tex = new Texture2D(width, height);
}

cam_data = cam.GetPixels32();
tex.SetPixels32(cam_data);
tex.Apply();
cambackground.texture = tex;

fit.aspectRatio = (float)cam.width / (float)cam.height;

}
}

其中float focal为任意设定的参数(因为无法通过标定获得),一般选择一个靠近真实值的值。


  1. https://docs.opencv.org/master/dc/dbb/tutorial_py_calibration.html

  2. https://docs.unity3d.com/Manual/PhysicalCameras.html