// Methods /// <summary> /// Configure the <see cref="ArucoCamera.ImageCameras"/>, the background that will display live webcam video through the /// <see cref="ArucoCamera.ImageTextures"/>. /// </summary> /// <remarks>See https://docs.opencv.org/3.3.0/d4/d94/tutorial_camera_calibration.html and /// https://docs.opencv.org/3.3.0/d9/d0c/group__calib3d.html#details for reference.</remarks> // TODO: handle case of CameraParameters.ImageHeight != ImageTexture.height or CameraParameters.ImageWidth != ImageTexture.width // TODO: handle case of CameraParameters.FixAspectRatio != 0 protected void ConfigureCameraAndBackground() { float imageWidth = CameraParameters.ImageWidths[cameraId]; float imageHeight = CameraParameters.ImageHeights[cameraId]; Vector2 f = CameraParameters.GetCameraFocalLengths(cameraId); Vector2 c = CameraParameters.GetCameraPrincipalPoint(cameraId); // Configure the camera according to the camera parameters if (ImageCameras[cameraId] == null) { ImageCameras[cameraId] = GetComponent <Camera>(); } // Estimate fov using these equations : https://stackoverflow.com/questions/39992968/how-to-calculate-field-of-view-of-the-camera-from-camera-intrinsic-matrix float fovX = 2f * Mathf.Atan(0.5f * imageWidth / f.x) * Mathf.Rad2Deg; float fovY = 2f * Mathf.Atan(0.5f * imageHeight / f.y) * Mathf.Rad2Deg; ImageCameras[cameraId].fieldOfView = fovY; ImageCameras[cameraId].aspect = ImageRatios[cameraId]; // Configure the background plane facing the camera if (cameraBackground == null) { cameraBackground = GameObject.CreatePrimitive(PrimitiveType.Quad); cameraBackground.name = "CameraBackground"; cameraBackground.transform.parent = this.transform; cameraBackground.transform.rotation = Quaternion.identity; cameraBackgroundRenderer = cameraBackground.GetComponent <Renderer>(); cameraBackgroundRenderer.material = Resources.Load("UnlitImage") as Material; } cameraBackgroundRenderer.material.mainTexture = ImageTextures[cameraId]; // Estimate background plane position relative to the camera, considering the first link in remarks: here x=0.5*ImageWidth and y=0.5*ImageHeight // (center of the camera projection), w=Z=cameraBackgroundDistance and we are looking for X=posX and Y=posY float posX = (0.5f * imageWidth - c.x) / f.x * cameraBackgroundDistance; float posY = (0.5f * imageHeight - c.y) / f.y * cameraBackgroundDistance; cameraBackground.transform.position = new Vector3(posX, posY * -1, cameraBackgroundDistance); // c=-1 for posY is because OpenCV (u=0, v=0) camera coordinates origin is top-left, but bottom-left in Unity (see https://docs.unity3d.com/ScriptReference/Camera.html) // Estimate background plane scale, using the same equations used for fov but here we are looking for w=scaleX and h=scaleY float scaleX = 2f * cameraBackgroundDistance * Mathf.Tan(fovX * Mathf.Deg2Rad / 2f); float scaleY = 2f * cameraBackgroundDistance * Mathf.Tan(fovY * Mathf.Deg2Rad / 2f); cameraBackground.transform.localScale = new Vector3(scaleX, scaleY, 1); }