Пример #1
0
 public static CalibrationResult Make(CalibrationData[] data)
 {
     return new CalibrationResult()
     {
         TransformToCamera = BuildTransform(),
         TransformToProjector = BuildTransform()
     };
 }
Пример #2
0
        public static CalibrationData GetLocalCorners(PointF[] cameraCorners, Projector projector, Camera camera, Size pattern)
        {
            if (false)
            {
                projector.DrawBackground(Color.Black);
                var noi = new Image<Bgr, byte>(camera.TakePicture(5));
                projector.DrawBackground(Color.FromArgb(0, 255, 0));
                var fulli = new Image<Bgr, byte>(camera.TakePicture(5));
                projector.DrawPhaseMod(4, 0f, true, Color.FromArgb(0, 255, 0));
                var img = new Image<Bgr, byte>(camera.TakePicture(5));

                var max = (fulli - noi).Split()[1];
                var cur = (img - noi).Split()[1];
                var map = new Bitmap(cur.Width, cur.Height);
                DebugWindow.DrawBitmap(max.Bitmap);
                DebugWindow.DrawBitmap(cur.Bitmap);
                using (var fast = new FastBitmap(map))
                {
                    for (int y = 0; y < cur.Height; y++)
                    {
                        for (int x = 0; x < cur.Width; x++)
                        {
                            var ii = cur[(int)y, (int)x].Intensity / max[(int)y, (int)x].Intensity;
                            if (ii > 1)
                                ii = 1;
                            var i = (byte)(ii * 255);
                            fast[x, y] = Color.FromArgb(i, i, i);
                        }
                    }
                }
                if (DebugWindow != null)
                    DebugWindow.DrawBitmap(map);
            }

            //Determine rough checkerboard coordinates in projector space with graycode or binary structured light

            var rough = DetectRoughCorners(cameraCorners, projector, camera, Color.Green);

            //Improve accuracy with PhaseModulation
            //var phine = PhineTune(projector, camera, cameraCorners, rough, 32);
            //var phine2 = PhineTune(projector, camera, cameraCorners, rough, 64);
            //var phine3 = PhineTune(projector, camera, cameraCorners, phine2, 128);

            projector.DrawPoints(rough, 5);

            //Determine corners in projector space
            //var projectorCorners = DetectProjectorCorners(nolight, cameraCorners, projOutline, projector, camera);
            //Save corners in camera and projector space and store along side global coordinates that matches current checkerboard
            var data = new CalibrationData() { CameraCorners = cameraCorners, ProjectorCorners = rough };
            return data;
        }
Пример #3
0
        public static StereoCalibrationResult Calibrate(CalibrationData[] data, Camera camera, Projector projector, Size pattern, float checkerBoardSize)
        {
            var globals = GenerateCheckerBoard(pattern, checkerBoardSize);
            var datas = data;
            var globalCorners = datas.Select(row => globals).ToArray();
            var cameraCorners = datas.Select(row => Properize(row.CameraCorners, pattern)
                )
                .ToArray();
            var projectorCorners = datas.Select(row => Properize(row.ProjectorCorners, pattern)

                ).ToArray();

            //for (var i = 0; i < datas.Length; i++)
            //{
            //    var withCorners = camera.TakePicture(0);
            //    QuickDraw.Start(withCorners)
            //        .Color(Color.White)
            //        .DrawPoint(cameraCorners[i].Take(11).ToArray(), 5)
            //        .Finish();
            //    DebugWindow.DrawBitmap(withCorners);
            //    projector.DrawPoints(projectorCorners[i].Take(11).ToArray(), 4);
            //}

            IntrinsicCameraParameters cameraIntrinsics = new IntrinsicCameraParameters();
            cameraIntrinsics.IntrinsicMatrix = new Matrix<double>(new double[,]
            {
            { 4.884, 0, 0.032 },
            { 0, 4.884 * 3.0 / 4.0, -0.037 },
            { 0, 0, 1 } });
            cameraIntrinsics.DistortionCoeffs = new Matrix<double>(new double[,] {
                {-0.00575},
                {0.000442},
                {-0.000107},
                {0},
                {0},
                {0},
                {0},
                {0},
            });
            ExtrinsicCameraParameters[] cameraExtrinsicsArray;
            var cerr = Emgu.CV.CameraCalibration.CalibrateCamera(globalCorners, cameraCorners,
                camera.Size, cameraIntrinsics, Emgu.CV.CvEnum.CALIB_TYPE.CV_CALIB_USE_INTRINSIC_GUESS,
                out cameraExtrinsicsArray);

            IntrinsicCameraParameters projectorIntrinsics = new IntrinsicCameraParameters();
            //projectorIntrinsics.IntrinsicMatrix = new Matrix<double>(new double[,] { { 531.15f * 4f / 3f, 0, 1 }, { 0, 531.15f, 1 }, { 0, 0, 1 } });
            projectorIntrinsics.IntrinsicMatrix = new Matrix<double>(new double[,]
            {
                {2151.0712684548571, 0, projector.Size.Width / 2},
                {0, 1974.541465816948, projector.Size.Height / 2},
                {0,0,1}
            });

            ExtrinsicCameraParameters[] projectorExtrinsicsArray;
            var perr = Emgu.CV.CameraCalibration.CalibrateCamera(globalCorners, projectorCorners,
                projector.Size, projectorIntrinsics,
                Emgu.CV.CvEnum.CALIB_TYPE.CV_CALIB_RATIONAL_MODEL,
                out projectorExtrinsicsArray);

            //Matrix<double> foundamental, essential;
            //ExtrinsicCameraParameters camera2projectorExtrinsics;
            //Emgu.CV.CameraCalibration.StereoCalibrate(globalCorners,
            //    cameraCorners,
            //    projectorCorners,
            //    cameraIntrinsics,
            //    projectorIntrinsics,
            //    camera.Size,
            //    Emgu.CV.CvEnum.CALIB_TYPE.DEFAULT,
            //    new MCvTermCriteria(16, 0.01),
            //    out camera2projectorExtrinsics,
            //    out foundamental,
            //    out essential);

            return new StereoCalibrationResult()
            {
                cameraIntrinsic = cameraIntrinsics,
                cameraExtrinsic = cameraExtrinsicsArray.First(),
                projectorIntrinsic = projectorIntrinsics,
                projectorExtrinsic = projectorExtrinsicsArray.First(),
                cameraToProjectorExtrinsic = null
            };
        }
Пример #4
0
        public static CalibrationResult Calibrate(Projector projector, Camera camera, Emgu.CV.Structure.MCvPoint3D32f[] globalCorners, int iterations = 10, int iterationTimeout = 500)
        {
            //if (PhaseModulation.DetermineAlgorithmIntegrity(8, 10000, 0.01) > 0.15)
            //    throw new Exception("Phase modulation integrity is failing");

            //projector.SetBounds(new RectangleF(0.25f, 0.25f, 0.5f, 0.5f));
            //projector.DrawBinary(3, true, Color.White);
            //Red and blue checkerboard
            //For each orientation of checkerboard:
            //float w = projector.bitmap.Width;
            //float h = projector.bitmap.Height;
            //var ps = new PointF[] {
            //        new PointF(440f, h - 324f), new PointF(640f, h - 168f)
            //    };

            ////projector.SetBounds(DetermineBounds(ps, projector.bitmap.Width, projector.bitmap.Height));
            //projector.SetBounds(DetermineBounds(ps, w, h));
            //projector.DrawBackground(Color.White);

            var datas = new CalibrationData[iterations];
            for (int i = 0; i < iterations; i++)
            {
                //Take pic of checkerboard with no proj light
                projector.DrawBackground(Color.Black);
                //Detect corners in camera space
                PointF[] cameraCorners;
                Bitmap withCorners;
                do
                {
                    var nolight = camera.TakePicture(5);
                    withCorners = camera.TakePicture();
                    cameraCorners = DetectCornersRB(nolight, new Size(7, 4));

                } while (cameraCorners == null);
                //cameraCorners = cameraCorners.Take(1).Union(cameraCorners.Skip(cameraCorners.Length - 1)).ToArray();
                if (DebugWindow != null)
                {
                    QuickDraw.Start(withCorners)
                        .Color(Color.White)
                        .DrawPoint(cameraCorners, 5)
                        .Finish();
                    DebugWindow.DrawBitmap(withCorners);
                }

                //Determine rough checkerboard coordinates in projector space with graycode or binary structured light
                //var smooth = PhaseCalib(projector, camera, cameraCorners);
                //projector.DrawPoints(smooth, 5);
                Func<PointF[]> Pass = () =>
                {
                    var rough = DetectRoughCorners(cameraCorners, projector, camera, Color.Green);

                    //var phine = PhineTune(projector, camera, cameraCorners, rough, 32);
                    var phine2 = PhineTune(projector, camera, cameraCorners, rough, 64);
                    var phine3 = PhineTune(projector, camera, cameraCorners, phine2, 128);
                    return phine3;
                };

                var ids = Range.OfInts(cameraCorners.Length);
                var passes = Range.OfInts(10).ToArray();
                var data = passes.Select(p => Pass()).ToArray();
                var result = ids.Select(row => passes.Select(p => data[p][row])).ToArray();
                var avg = ids.Select(id => new PointF(result[id].Select(r => r.X).Average(),
                    result[id].Select(r => r.Y).Average())).ToArray();
                projector.DrawPoints(avg, 5);
                var avg2 = ids.Select(id => new PointF(
                    result[id].Select(r => new { val= r.X, dist = Math.Abs(avg[id].X - r.X) })
                        .OrderByDescending(row => row.dist).Reverse().Take(5).Select(row => row.val).Average(),
                    result[id].Select(r => new { val = r.Y, dist = Math.Abs(avg[id].Y - r.Y) })
                        .OrderByDescending(row => row.dist).Reverse().Take(5).Select(row => row.val).Average())).ToArray();
                projector.DrawPoints(avg2, 5);
                //var outline = DetermineBounds(rough, projector.bitmap.Width, projector.bitmap.Height);
                //projector.SetBounds(outline);

                /*
                double[] xs, ys;
                {
                    projector.DrawBackground(Color.Black);
                    var nolight = camera.TakePicture(5);
                    projector.DrawBackground(Color.Green);
                    var fulllight = camera.TakePicture(5);
                    projector.DrawBackground(Color.Black);
                    camera.TakePicture(5).Dispose();
                    projector.Draw(PhaseModulation.DrawPhaseModulation(1, -2 * Math.PI / 3, true, Color.Green));
                    var light1 = camera.TakePicture(2);
                    projector.DrawBackground(Color.Black);
                    camera.TakePicture(5).Dispose();
                    projector.Draw(PhaseModulation.DrawPhaseModulation(1, 0, true, Color.Green));
                    var light2 = camera.TakePicture(2);
                    projector.DrawBackground(Color.Black);
                    camera.TakePicture(5).Dispose();
                    projector.Draw(PhaseModulation.DrawPhaseModulation(1, 2 * Math.PI / 3, true, Color.Green));
                    var light3 = camera.TakePicture(2);

                    var pc = PhaseClassifier(nolight, fulllight, projector.bitmap.Width, projector.bitmap.Height);
                    var pc1 = pc(light1);
                    var pc2 = pc(light2);
                    var pc3 = pc(light3);
                    xs = cameraCorners.Select(row => PhaseModulation.IntensityToPhase(pc1((int)row.X, (int)row.Y),
                        pc2((int)row.X, (int)row.Y),
                        pc3((int)row.X, (int)row.Y))).ToArray();

                }

                {
                    projector.DrawBackground(Color.Black);
                    var nolight = camera.TakePicture(5);
                    projector.DrawBackground(Color.Green);
                    var fulllight = camera.TakePicture(5);
                    projector.DrawBackground(Color.Black);
                    camera.TakePicture(5).Dispose();
                    projector.DrawPhaseMod(1, (float)(-2 * Math.PI / 3), false, Color.FromArgb(0, 255, 0));
                    var light1 = camera.TakePicture(2);
                    projector.DrawBackground(Color.Black);
                    camera.TakePicture(5).Dispose();
                    projector.DrawPhaseMod(1, (float)(0), false, Color.FromArgb(0, 255, 0));
                    var light2 = camera.TakePicture(2);
                    projector.DrawBackground(Color.Black);
                    camera.TakePicture(5).Dispose();
                    projector.DrawPhaseMod(1, (float)(2 * Math.PI / 3), false, Color.FromArgb(0, 255, 0));
                    var light3 = camera.TakePicture(2);

                    var pc = PhaseClassifier(nolight, fulllight, projector.bitmap.Width, projector.bitmap.Height);
                    var pc1 = pc(light1);
                    var pc2 = pc(light2);
                    var pc3 = pc(light3);
                    ys = cameraCorners.Select(row => PhaseModulation.IntensityToPhase(pc1((int)row.X, (int)row.Y),
                        pc2((int)row.X, (int)row.Y),
                        pc3((int)row.X, (int)row.Y))).ToArray();

                }

                var resx = xs.Select(row => PhaseModulation.AbsolutePhase(new double[] { row }, new int[] { 1 })).Select(row => row * projector.bitmap.Width).ToArray();
                var resy = ys.Select(row => PhaseModulation.AbsolutePhase(new double[] { row }, new int[] { 1 })).Select(row => row * projector.bitmap.Height).ToArray();
                var res = resx.Zip(resy, (x, y) => new PointF((float)Math.Round(x, 0), (float)Math.Round(y, 0))).ToArray();
                projector.SetBounds(new RectangleF(0, 0, 1, 1));
                projector.DrawPoints(res, 5f);
                 */
                //Determine corners in projector space
                //var projectorCorners = DetectProjectorCorners(nolight, cameraCorners, projOutline, projector, camera);
                //Save corners in camera and projector space and store along side global coordinates that matches current checkerboard
                //var data = new CalibrationData() { CameraCorners = cameraCorners, ProjectorCorners = projectorCorners, GlobalCorners = globalCorners };

                datas[i] = default(CalibrationData);
                Thread.Sleep(iterationTimeout);
            }
            return CalibrationResult.Make(datas);
        }