コード例 #1
0
            public GridNode(CameraCalibration _CameraCalibration)
            {
                if (_CameraCalibration == null)
                {
                    throw new Exception("Invalid camera calibration to build grid node!");
                }

                m_CameraCalibration = _CameraCalibration;

                // Build normalized EV infos
                Convert2EV(m_CameraCalibration.m_CameraShotInfos.m_ISOSpeed,
                           m_CameraCalibration.m_CameraShotInfos.m_ShutterSpeed,
                           m_CameraCalibration.m_CameraShotInfos.m_Aperture,
                           out m_EV_ISOSpeed, out m_EV_ShutterSpeed, out m_EV_Aperture);
            }
コード例 #2
0
ファイル: Form1.cs プロジェクト: Patapom/GodComplex
        private void buttonLoadCalibration_Click( object sender, EventArgs e )
        {
            string	OldFileName = GetRegKey( "LastCalibrationFilename", m_ApplicationPath );
            openFileDialogCalibration.InitialDirectory = System.IO.Path.GetDirectoryName( OldFileName );
            openFileDialogCalibration.FileName = System.IO.Path.GetFileName( OldFileName );

            if ( openFileDialogCalibration.ShowDialog( this ) != DialogResult.OK )
             				return;

            SetRegKey( "LastCalibrationFilename", openFileDialogCalibration.FileName );

            try
            {
                CameraCalibration	NewCalibration = new CameraCalibration();
                NewCalibration.Load( new System.IO.FileInfo( openFileDialogCalibration.FileName ) );
                m_Calibration = NewCalibration;
                UpdateUIFromCalibration();
            }
            catch ( Exception _e )
            {
                MessageBox( "An error occurred while loading calibration file:\r\n\r\n", _e );
            }
        }
コード例 #3
0
ファイル: Form1.cs プロジェクト: Patapom/GodComplex
        private void StartCalibrationPicking( CameraCalibration.Probe _Probe )
        {
            if ( m_BitmapXYZ == null )
            {	// No image loaded you moron!
                MessageBox( "Can't start calibration as no image is currently loaded!", MessageBoxButtons.OK, MessageBoxIcon.Exclamation );
                return;
            }

            outputPanel.StartCalibrationTargetPicking( ( ImageUtility.float2 _Center, float _Radius ) => {
                IntegrateLuminance( _Probe, _Center, _Radius );
            } );
        }
コード例 #4
0
ファイル: Form1.cs プロジェクト: Patapom/GodComplex
        /// <summary>
        /// Integrates luminance for the provided probe by sampling luminances in the provided disc
        /// </summary>
        /// <param name="_Probe"></param>
        /// <param name="_Center"></param>
        /// <param name="_Radius"></param>
        private void IntegrateLuminance( CameraCalibration.Probe _Probe, ImageUtility.float2 _Center, float _Radius )
        {
            ImageUtility.float3	MinXYZ, MaxXYZ;
            float	BlackValues, SaturatedValues;
            ImageUtility.float3	AverageXYZ = IntegrateLuminance( _Center.x, _Center.y, _Radius, out MinXYZ, out MaxXYZ, out BlackValues, out SaturatedValues );

            bool	DisableProbe = false;
            if ( BlackValues > BLACK_VALUES_TOLERANCE &&
                MessageBox( "This probe has more than 5% luminance values that are too dark, it's advised you don't use it to calibrate the camera as its values will not be useful.\r\n" +
                            "\r\nDo you wish to disable this probe?",
                            MessageBoxButtons.YesNo, MessageBoxIcon.Warning ) == DialogResult.Yes )
            {
                DisableProbe = true;
            }
            else if ( SaturatedValues > SATURATED_VALUES_TOLERANCE &&
                MessageBox( "This probe has more than 5% luminance values that are saturated, it's advised you don't use it to calibrate the camera as its values will not be useful.\r\n" +
                            "\r\nDo you wish to disable this probe?",
                            MessageBoxButtons.YesNo, MessageBoxIcon.Warning ) == DialogResult.Yes )
            {
                DisableProbe = true;
            }

            if ( DisableProbe )
            {	// Disable probe
                _Probe.m_IsAvailable = false;
                _Probe.m_LuminanceMeasured = 0.0f;
                UpdateUIFromCalibration();
                return;
            }

            _Probe.m_LuminanceMeasured = checkBoxCalibrationUseAverageLuminance.Checked ? AverageXYZ.y : MaxXYZ.y;

            // We now have valid measurement disc infos
            _Probe.m_MeasurementDiscIsAvailable = true;
            _Probe.m_MeasurementCenterX = _Center.x;
            _Probe.m_MeasurementCenterY = _Center.y;
            _Probe.m_MeasurementRadius = _Radius;

            CommitImageToCurrentCalibration();	// We used the current image as reference for this calibration so commit its data
        }
コード例 #5
0
            public GridNode( CameraCalibration _CameraCalibration )
            {
                if ( _CameraCalibration == null )
                    throw new Exception( "Invalid camera calibration to build grid node!" );

                m_CameraCalibration = _CameraCalibration;

                // Build normalized EV infos
                Convert2EV( m_CameraCalibration.m_CameraShotInfos.m_ISOSpeed,
                            m_CameraCalibration.m_CameraShotInfos.m_ShutterSpeed,
                            m_CameraCalibration.m_CameraShotInfos.m_Aperture,
                            out m_EV_ISOSpeed, out m_EV_ShutterSpeed, out m_EV_Aperture );
            }
コード例 #6
0
        /// <summary>
        /// Prepares the interpolated calibration table to process the pixels in an image shot with the specified shot infos
        /// </summary>
        /// <param name="_ISOSpeed"></param>
        /// <param name="_ShutterSpeed"></param>
        /// <param name="_Aperture"></param>
        public void PrepareCalibrationFor( float _ISOSpeed, float _ShutterSpeed, float _Aperture )
        {
            if ( m_RootNode == null )
                throw new Exception( "Calibration grid hasn't been built: did you provide a valid database path? Does the path contain camera calibration data?" );

            if ( IsPreparedFor( _ISOSpeed, _ShutterSpeed, _Aperture ) )
                return;	// Already prepared!

            //////////////////////////////////////////////////////////////////////////
            // Find the 8 nodes encompassing our values
            // I'm making the delicate assumption that, although the starting node is chosen on the
            //	condition its EV values are strictly inferior to the target we're looking for, all
            //	neighbor nodes should satisfy the condition they're properly placed.
            //
            // This is true for the direct neighbors +X, +Y, +Z that are immediately above target values
            //	but for example, neighbor (+X +Y) may have a very bad aperture value (Z) that may be
            //	above the target aperture...
            //
            // Let's hope the user won't provide too fancy calibrations...
            // (anyway, interpolants are clamped in [0,1] so there's no risk of overshooting)
            //
            ImageUtility.float3	EV;
            GridNode.Convert2EV( _ISOSpeed, _ShutterSpeed, _Aperture, out EV.x, out EV.y, out EV.z );

            // Find the start node
            GridNode		StartNode = FindStartNode( EV.x, EV.y, EV.z );
            m_InterpolationStartNode = StartNode;

            // Build the 8 grid nodes from it
            GridNode[,,]	Grid = new GridNode[2,2,2];
            Grid[0,0,0] = StartNode;
            Grid[1,0,0] = StartNode.m_Neighbors[0][1] != null ? StartNode.m_Neighbors[0][1] : StartNode;		// +X
            Grid[0,1,0] = StartNode.m_Neighbors[1][1] != null ? StartNode.m_Neighbors[1][1] : StartNode;		// +Y
            Grid[0,0,1] = StartNode.m_Neighbors[2][1] != null ? StartNode.m_Neighbors[2][1] : StartNode;		// +Z
            Grid[1,1,0] = Grid[1,0,0].m_Neighbors[1][1] != null ? Grid[1,0,0].m_Neighbors[1][1] : Grid[1,0,0];	// +X +Y
            Grid[0,1,1] = Grid[0,1,0].m_Neighbors[2][1] != null ? Grid[0,1,0].m_Neighbors[2][1] : Grid[0,1,0];	// +Y +Z
            Grid[1,0,1] = Grid[0,0,1].m_Neighbors[0][1] != null ? Grid[0,0,1].m_Neighbors[0][1] : Grid[0,0,1];	// +X +Z
            Grid[1,1,1] = Grid[1,1,0].m_Neighbors[2][1] != null ? Grid[1,1,0].m_Neighbors[2][1] : Grid[1,1,0];	// +X +Y +Z

            //////////////////////////////////////////////////////////////////////////
            // Create the successive interpolants for trilinear interpolation
            //
            // Assume we interpolate on X first (ISO speed), so we need 4 distinct values
            ImageUtility.float4	tX = new ImageUtility.float4(
                    Math.Max( 0.0f, Math.Min( 1.0f, (EV.x - Grid[0,0,0].m_EV_ISOSpeed) / Math.Max( 1e-6f, Grid[1,0,0].m_EV_ISOSpeed - Grid[0,0,0].m_EV_ISOSpeed) ) ),	// Y=0 Z=0
                    Math.Max( 0.0f, Math.Min( 1.0f, (EV.x - Grid[0,1,0].m_EV_ISOSpeed) / Math.Max( 1e-6f, Grid[1,1,0].m_EV_ISOSpeed - Grid[0,1,0].m_EV_ISOSpeed) ) ),	// Y=1 Z=0
                    Math.Max( 0.0f, Math.Min( 1.0f, (EV.x - Grid[0,0,1].m_EV_ISOSpeed) / Math.Max( 1e-6f, Grid[1,0,1].m_EV_ISOSpeed - Grid[0,0,1].m_EV_ISOSpeed) ) ),	// Y=0 Z=1
                    Math.Max( 0.0f, Math.Min( 1.0f, (EV.x - Grid[0,1,1].m_EV_ISOSpeed) / Math.Max( 1e-6f, Grid[1,1,1].m_EV_ISOSpeed - Grid[0,1,1].m_EV_ISOSpeed) ) )	// Y=1 Z=1
                );
            ImageUtility.float4	rX = new ImageUtility.float4( 1.0f - tX.x, 1.0f - tX.y, 1.0f - tX.z, 1.0f - tX.w );

                // Compute the 4 interpolated shutter speeds & apertures
            ImageUtility.float4	ShutterSpeedsX = new ImageUtility.float4(
                    rX.x * Grid[0,0,0].m_EV_ShutterSpeed + tX.x * Grid[1,0,0].m_EV_ShutterSpeed,	// Y=0 Z=0
                    rX.y * Grid[0,1,0].m_EV_ShutterSpeed + tX.y * Grid[1,1,0].m_EV_ShutterSpeed,	// Y=1 Z=0
                    rX.z * Grid[0,0,1].m_EV_ShutterSpeed + tX.z * Grid[1,0,1].m_EV_ShutterSpeed,	// Y=0 Z=1
                    rX.w * Grid[0,1,1].m_EV_ShutterSpeed + tX.w * Grid[1,1,1].m_EV_ShutterSpeed		// Y=1 Z=1
                );
            ImageUtility.float4	AperturesX = new ImageUtility.float4(
                    rX.x * Grid[0,0,0].m_EV_Aperture + tX.x * Grid[1,0,0].m_EV_Aperture,			// Y=0 Z=0
                    rX.y * Grid[0,1,0].m_EV_Aperture + tX.y * Grid[1,1,0].m_EV_Aperture,			// Y=1 Z=0
                    rX.z * Grid[0,0,1].m_EV_Aperture + tX.z * Grid[1,0,1].m_EV_Aperture,			// Y=0 Z=1
                    rX.w * Grid[0,1,1].m_EV_Aperture + tX.w * Grid[1,1,1].m_EV_Aperture				// Y=1 Z=1
                );

            // Next we interpolate on Y (Shutter speed), so we need 2 distinct values
            ImageUtility.float2	tY = new ImageUtility.float2(
                    Math.Max( 0.0f, Math.Min( 1.0f, (EV.y - ShutterSpeedsX.x) / Math.Max( 1e-6f, ShutterSpeedsX.y - ShutterSpeedsX.x) ) ),	// Z=0
                    Math.Max( 0.0f, Math.Min( 1.0f, (EV.y - ShutterSpeedsX.z) / Math.Max( 1e-6f, ShutterSpeedsX.w - ShutterSpeedsX.z) ) )	// Z=1
                );
            ImageUtility.float2	rY = new ImageUtility.float2( 1.0f - tY.x, 1.0f - tY.y );

                // Compute the 2 apertures
            ImageUtility.float2	AperturesY = new ImageUtility.float2(
                    rY.x * AperturesX.x + tY.x * AperturesX.y,
                    rY.y * AperturesX.z + tY.y * AperturesX.w
                );

            // Finally, we interpolate on Z (Aperture), we need only 1 single value
            float	tZ = Math.Max( 0.0f, Math.Min( 1.0f, (EV.z - AperturesY.x) / Math.Max( 1e-6f, AperturesY.y - AperturesY.x) ) );
            float	rZ = 1.0f - tZ;

            //////////////////////////////////////////////////////////////////////////
            // Create the special camera calibration that is the result of the interpolation of the 8 nearest ones in the grid
            m_InterpolatedCalibration = new CameraCalibration();
            m_InterpolatedCalibration.m_CameraShotInfos.m_ISOSpeed = _ISOSpeed;
            m_InterpolatedCalibration.m_CameraShotInfos.m_ShutterSpeed = _ShutterSpeed;
            m_InterpolatedCalibration.m_CameraShotInfos.m_Aperture = _Aperture;

            for ( int ProbeIndex=0; ProbeIndex < REQUIRED_PROBES_COUNT; ProbeIndex++ )
            {
                CameraCalibration.Probe TargetProbe = m_InterpolatedCalibration.m_Reflectances[ProbeIndex];

                float	L000 = Grid[0,0,0].m_CameraCalibration.m_Reflectances[ProbeIndex].m_LuminanceMeasured;
                float	L100 = Grid[1,0,0].m_CameraCalibration.m_Reflectances[ProbeIndex].m_LuminanceMeasured;
                float	L010 = Grid[0,1,0].m_CameraCalibration.m_Reflectances[ProbeIndex].m_LuminanceMeasured;
                float	L110 = Grid[1,1,0].m_CameraCalibration.m_Reflectances[ProbeIndex].m_LuminanceMeasured;
                float	L001 = Grid[0,0,1].m_CameraCalibration.m_Reflectances[ProbeIndex].m_LuminanceMeasured;
                float	L101 = Grid[1,0,1].m_CameraCalibration.m_Reflectances[ProbeIndex].m_LuminanceMeasured;
                float	L011 = Grid[0,1,1].m_CameraCalibration.m_Reflectances[ProbeIndex].m_LuminanceMeasured;
                float	L111 = Grid[1,1,1].m_CameraCalibration.m_Reflectances[ProbeIndex].m_LuminanceMeasured;

                // Interpolate on X (ISO speed)
                float	L00 = rX.x * L000 + tX.x * L100;
                float	L10 = rX.y * L010 + tX.y * L110;
                float	L01 = rX.z * L001 + tX.z * L101;
                float	L11 = rX.w * L011 + tX.w * L111;

                // Interpolate on Y (shutter speed)
                float	L0 = rY.x * L00 + tY.x * L10;
                float	L1 = rY.y * L01 + tY.y * L11;

                // Interpolate on Z (aperture)
                float	L = rZ * L0 + tZ * L1;

                TargetProbe.m_IsAvailable = true;
                TargetProbe.m_LuminanceMeasured = L;
            }

            // Fill missing values
            m_InterpolatedCalibration.UpdateAllLuminances();

            // Reset white reflectance reference because it was set for another setup
            WhiteReflectanceReference = new ImageUtility.float3( 0, 0, -1 );
        }
コード例 #7
0
        /// <summary>
        /// Prepares the interpolated calibration table to process the pixels in an image shot with the specified shot infos
        /// </summary>
        /// <param name="_ISOSpeed"></param>
        /// <param name="_ShutterSpeed"></param>
        /// <param name="_Aperture"></param>
        public void     PrepareCalibrationFor(float _ISOSpeed, float _ShutterSpeed, float _Aperture)
        {
            if (m_RootNode == null)
            {
                throw new Exception("Calibration grid hasn't been built: did you provide a valid database path? Does the path contain camera calibration data?");
            }

            if (IsPreparedFor(_ISOSpeed, _ShutterSpeed, _Aperture))
            {
                return;                 // Already prepared!
            }
            //////////////////////////////////////////////////////////////////////////
            // Find the 8 nodes encompassing our values
            // I'm making the delicate assumption that, although the starting node is chosen on the
            //	condition its EV values are strictly inferior to the target we're looking for, all
            //	neighbor nodes should satisfy the condition they're properly placed.
            //
            // This is true for the direct neighbors +X, +Y, +Z that are immediately above target values
            //	but for example, neighbor (+X +Y) may have a very bad aperture value (Z) that may be
            //	above the target aperture...
            //
            // Let's hope the user won't provide too fancy calibrations...
            // (anyway, interpolants are clamped in [0,1] so there's no risk of overshooting)
            //
            ImageUtility.float3 EV;
            GridNode.Convert2EV(_ISOSpeed, _ShutterSpeed, _Aperture, out EV.x, out EV.y, out EV.z);

            // Find the start node
            GridNode StartNode = FindStartNode(EV.x, EV.y, EV.z);

            m_InterpolationStartNode = StartNode;

            // Build the 8 grid nodes from it
            GridNode[,,]    Grid = new GridNode[2, 2, 2];
            Grid[0, 0, 0]        = StartNode;
            Grid[1, 0, 0]        = StartNode.m_Neighbors[0][1] != null ? StartNode.m_Neighbors[0][1] : StartNode;               // +X
            Grid[0, 1, 0]        = StartNode.m_Neighbors[1][1] != null ? StartNode.m_Neighbors[1][1] : StartNode;               // +Y
            Grid[0, 0, 1]        = StartNode.m_Neighbors[2][1] != null ? StartNode.m_Neighbors[2][1] : StartNode;               // +Z
            Grid[1, 1, 0]        = Grid[1, 0, 0].m_Neighbors[1][1] != null ? Grid[1, 0, 0].m_Neighbors[1][1] : Grid[1, 0, 0];   // +X +Y
            Grid[0, 1, 1]        = Grid[0, 1, 0].m_Neighbors[2][1] != null ? Grid[0, 1, 0].m_Neighbors[2][1] : Grid[0, 1, 0];   // +Y +Z
            Grid[1, 0, 1]        = Grid[0, 0, 1].m_Neighbors[0][1] != null ? Grid[0, 0, 1].m_Neighbors[0][1] : Grid[0, 0, 1];   // +X +Z
            Grid[1, 1, 1]        = Grid[1, 1, 0].m_Neighbors[2][1] != null ? Grid[1, 1, 0].m_Neighbors[2][1] : Grid[1, 1, 0];   // +X +Y +Z

            //////////////////////////////////////////////////////////////////////////
            // Create the successive interpolants for trilinear interpolation
            //
            // Assume we interpolate on X first (ISO speed), so we need 4 distinct values
            ImageUtility.float4 tX = new ImageUtility.float4(
                Math.Max(0.0f, Math.Min(1.0f, (EV.x - Grid[0, 0, 0].m_EV_ISOSpeed) / Math.Max(1e-6f, Grid[1, 0, 0].m_EV_ISOSpeed - Grid[0, 0, 0].m_EV_ISOSpeed))),                              // Y=0 Z=0
                Math.Max(0.0f, Math.Min(1.0f, (EV.x - Grid[0, 1, 0].m_EV_ISOSpeed) / Math.Max(1e-6f, Grid[1, 1, 0].m_EV_ISOSpeed - Grid[0, 1, 0].m_EV_ISOSpeed))),                              // Y=1 Z=0
                Math.Max(0.0f, Math.Min(1.0f, (EV.x - Grid[0, 0, 1].m_EV_ISOSpeed) / Math.Max(1e-6f, Grid[1, 0, 1].m_EV_ISOSpeed - Grid[0, 0, 1].m_EV_ISOSpeed))),                              // Y=0 Z=1
                Math.Max(0.0f, Math.Min(1.0f, (EV.x - Grid[0, 1, 1].m_EV_ISOSpeed) / Math.Max(1e-6f, Grid[1, 1, 1].m_EV_ISOSpeed - Grid[0, 1, 1].m_EV_ISOSpeed)))                               // Y=1 Z=1
                );
            ImageUtility.float4 rX = new ImageUtility.float4(1.0f - tX.x, 1.0f - tX.y, 1.0f - tX.z, 1.0f - tX.w);

            // Compute the 4 interpolated shutter speeds & apertures
            ImageUtility.float4 ShutterSpeedsX = new ImageUtility.float4(
                rX.x * Grid[0, 0, 0].m_EV_ShutterSpeed + tX.x * Grid[1, 0, 0].m_EV_ShutterSpeed,                        // Y=0 Z=0
                rX.y * Grid[0, 1, 0].m_EV_ShutterSpeed + tX.y * Grid[1, 1, 0].m_EV_ShutterSpeed,                        // Y=1 Z=0
                rX.z * Grid[0, 0, 1].m_EV_ShutterSpeed + tX.z * Grid[1, 0, 1].m_EV_ShutterSpeed,                        // Y=0 Z=1
                rX.w * Grid[0, 1, 1].m_EV_ShutterSpeed + tX.w * Grid[1, 1, 1].m_EV_ShutterSpeed                         // Y=1 Z=1
                );
            ImageUtility.float4 AperturesX = new ImageUtility.float4(
                rX.x * Grid[0, 0, 0].m_EV_Aperture + tX.x * Grid[1, 0, 0].m_EV_Aperture,                                        // Y=0 Z=0
                rX.y * Grid[0, 1, 0].m_EV_Aperture + tX.y * Grid[1, 1, 0].m_EV_Aperture,                                        // Y=1 Z=0
                rX.z * Grid[0, 0, 1].m_EV_Aperture + tX.z * Grid[1, 0, 1].m_EV_Aperture,                                        // Y=0 Z=1
                rX.w * Grid[0, 1, 1].m_EV_Aperture + tX.w * Grid[1, 1, 1].m_EV_Aperture                                         // Y=1 Z=1
                );

            // Next we interpolate on Y (Shutter speed), so we need 2 distinct values
            ImageUtility.float2 tY = new ImageUtility.float2(
                Math.Max(0.0f, Math.Min(1.0f, (EV.y - ShutterSpeedsX.x) / Math.Max(1e-6f, ShutterSpeedsX.y - ShutterSpeedsX.x))),                               // Z=0
                Math.Max(0.0f, Math.Min(1.0f, (EV.y - ShutterSpeedsX.z) / Math.Max(1e-6f, ShutterSpeedsX.w - ShutterSpeedsX.z)))                                // Z=1
                );
            ImageUtility.float2 rY = new ImageUtility.float2(1.0f - tY.x, 1.0f - tY.y);

            // Compute the 2 apertures
            ImageUtility.float2 AperturesY = new ImageUtility.float2(
                rY.x * AperturesX.x + tY.x * AperturesX.y,
                rY.y * AperturesX.z + tY.y * AperturesX.w
                );

            // Finally, we interpolate on Z (Aperture), we need only 1 single value
            float tZ = Math.Max(0.0f, Math.Min(1.0f, (EV.z - AperturesY.x) / Math.Max(1e-6f, AperturesY.y - AperturesY.x)));
            float rZ = 1.0f - tZ;


            //////////////////////////////////////////////////////////////////////////
            // Create the special camera calibration that is the result of the interpolation of the 8 nearest ones in the grid
            m_InterpolatedCalibration = new CameraCalibration();
            m_InterpolatedCalibration.m_CameraShotInfos.m_ISOSpeed     = _ISOSpeed;
            m_InterpolatedCalibration.m_CameraShotInfos.m_ShutterSpeed = _ShutterSpeed;
            m_InterpolatedCalibration.m_CameraShotInfos.m_Aperture     = _Aperture;

            for (int ProbeIndex = 0; ProbeIndex < REQUIRED_PROBES_COUNT; ProbeIndex++)
            {
                CameraCalibration.Probe TargetProbe = m_InterpolatedCalibration.m_Reflectances[ProbeIndex];

                float L000 = Grid[0, 0, 0].m_CameraCalibration.m_Reflectances[ProbeIndex].m_LuminanceMeasured;
                float L100 = Grid[1, 0, 0].m_CameraCalibration.m_Reflectances[ProbeIndex].m_LuminanceMeasured;
                float L010 = Grid[0, 1, 0].m_CameraCalibration.m_Reflectances[ProbeIndex].m_LuminanceMeasured;
                float L110 = Grid[1, 1, 0].m_CameraCalibration.m_Reflectances[ProbeIndex].m_LuminanceMeasured;
                float L001 = Grid[0, 0, 1].m_CameraCalibration.m_Reflectances[ProbeIndex].m_LuminanceMeasured;
                float L101 = Grid[1, 0, 1].m_CameraCalibration.m_Reflectances[ProbeIndex].m_LuminanceMeasured;
                float L011 = Grid[0, 1, 1].m_CameraCalibration.m_Reflectances[ProbeIndex].m_LuminanceMeasured;
                float L111 = Grid[1, 1, 1].m_CameraCalibration.m_Reflectances[ProbeIndex].m_LuminanceMeasured;

                // Interpolate on X (ISO speed)
                float L00 = rX.x * L000 + tX.x * L100;
                float L10 = rX.y * L010 + tX.y * L110;
                float L01 = rX.z * L001 + tX.z * L101;
                float L11 = rX.w * L011 + tX.w * L111;

                // Interpolate on Y (shutter speed)
                float L0 = rY.x * L00 + tY.x * L10;
                float L1 = rY.y * L01 + tY.y * L11;

                // Interpolate on Z (aperture)
                float L = rZ * L0 + tZ * L1;

                TargetProbe.m_IsAvailable       = true;
                TargetProbe.m_LuminanceMeasured = L;
            }

            // Fill missing values
            m_InterpolatedCalibration.UpdateAllLuminances();

            // Reset white reflectance reference because it was set for another setup
            WhiteReflectanceReference = new ImageUtility.float3(0, 0, -1);
        }