Beispiel #1
0
            // 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);
            }