Exemplo n.º 1
0
        private static CoordinateSystemGrid FindForLineCalibration(CalibrationHelper calibrationHelper)
        {
            CoordinateSystemGrid grid        = new CoordinateSystemGrid();
            RectangleF           imageBounds = new RectangleF(PointF.Empty, calibrationHelper.ImageSize);

            // The clip window is an inflated version of the image to account for distortion.
            RectangleF clipWindow = imageBounds.CenteredScale(1.3f);

            // Create a fake plane to act as the user-defined projected plane.
            QuadrilateralF quadImage = new QuadrilateralF(imageBounds.Deflate(2.0f));
            PointF         a         = calibrationHelper.GetPointFromRectified(quadImage.A);
            PointF         b         = calibrationHelper.GetPointFromRectified(quadImage.B);
            PointF         d         = calibrationHelper.GetPointFromRectified(quadImage.D);
            RectangleF     plane     = new RectangleF(0, 0, b.X - a.X, a.Y - d.Y);

            // Define the extended plane (for vanishing point replacement and drawing stop condition) as the reprojection of the whole image.
            QuadrilateralF extendedPlane = ReprojectImageBounds(calibrationHelper, new QuadrilateralF(imageBounds));

            CalibrationPlane calibrator = new CalibrationPlane();

            calibrator.Initialize(plane.Size, quadImage);
            PointF originImage     = calibrationHelper.GetOrigin();
            PointF originRectified = originImage;

            if (calibrationHelper.DistortionHelper != null && calibrationHelper.DistortionHelper.Initialized)
            {
                originRectified = calibrationHelper.DistortionHelper.Undistort(originImage);
            }

            calibrator.SetOrigin(originRectified);

            // From this point on we are mostly in the same situation as for plane calibration.

            // stepping size is the same in both directions.
            int   targetSteps = 15;
            float width       = extendedPlane.B.X - extendedPlane.A.X;
            float step        = RangeHelper.FindUsableStepSize(width, targetSteps);

            CreateVerticalGridLines(grid, 0, -step, calibrator, clipWindow, plane, extendedPlane, true, false, PointF.Empty);
            CreateVerticalGridLines(grid, step, step, calibrator, clipWindow, plane, extendedPlane, true, false, PointF.Empty);
            CreateHorizontalGridLines(grid, 0, -step, calibrator, clipWindow, plane, extendedPlane, true, false, PointF.Empty);
            CreateHorizontalGridLines(grid, step, step, calibrator, clipWindow, plane, extendedPlane, true, false, PointF.Empty);

            return(grid);
        }
Exemplo n.º 2
0
        private static QuadrilateralF ReprojectImageBounds(CalibrationHelper calibrationHelper, QuadrilateralF quadImage)
        {
            // Project image bounds from image space to plane space, using the line calibration setup.
            // This can be used to define safe boundaries.
            // The method cannot be used with plane calibration as image points can be above the vanishing line. (reproject behind the camera).
            // The quad passed in is assumed to be a rectangle.
            if (calibrationHelper.CalibratorType != CalibratorType.Line)
            {
                throw new ArgumentException("Unsupported operation.");
            }

            PointF         a     = calibrationHelper.GetPointFromRectified(quadImage.A);
            PointF         b     = calibrationHelper.GetPointFromRectified(quadImage.B);
            PointF         c     = calibrationHelper.GetPointFromRectified(quadImage.C);
            PointF         d     = calibrationHelper.GetPointFromRectified(quadImage.D);
            QuadrilateralF plane = new QuadrilateralF(a, b, c, d);

            return(plane);
        }
Exemplo n.º 3
0
        private void CreateScatterPlot()
        {
            PlotModel model = new PlotModel();

            model.PlotType = PlotType.Cartesian;
            model.Title    = this.tbTitle.Text;

            double padding = 0.1;

            LinearAxis xAxis = new LinearAxis();

            xAxis.MajorGridlineColor = OxyColor.FromArgb(40, 0, 0, 139);
            xAxis.MajorGridlineStyle = LineStyle.Solid;
            xAxis.MinorGridlineColor = OxyColor.FromArgb(20, 0, 0, 139);
            xAxis.MinorGridlineStyle = LineStyle.Solid;
            xAxis.Position           = AxisPosition.Bottom;
            xAxis.MinimumPadding     = 0.1;
            xAxis.MaximumPadding     = 0.1;
            xAxis.Title = tbXAxis.Text;
            model.Axes.Add(xAxis);

            LinearAxis yAxis = new LinearAxis();

            yAxis.MajorGridlineColor = OxyColor.FromArgb(40, 0, 0, 139);
            yAxis.MajorGridlineStyle = LineStyle.Solid;
            yAxis.MinorGridlineColor = OxyColor.FromArgb(20, 0, 0, 139);
            yAxis.MinorGridlineStyle = LineStyle.Solid;
            yAxis.MinimumPadding     = 0.1;
            yAxis.MaximumPadding     = 0.1;
            yAxis.Title = tbYAxis.Text;
            model.Axes.Add(yAxis);

            ScatterSeries series = new ScatterSeries();

            series.MarkerType   = MarkerType.Plus;
            series.MarkerStroke = OxyColors.Black;

            float yDataMinimum = float.MaxValue;
            float yDataMaximum = float.MinValue;
            float xDataMinimum = float.MaxValue;
            float xDataMaximum = float.MinValue;

            foreach (TimedPoint point in points)
            {
                PointF p = metadata.CalibrationHelper.GetPointAtTime(point.Point, point.T);
                series.Points.Add(new ScatterPoint(p.X, p.Y));

                yDataMinimum = Math.Min(yDataMinimum, p.Y);
                yDataMaximum = Math.Max(yDataMaximum, p.Y);
                xDataMinimum = Math.Min(xDataMinimum, p.X);
                xDataMaximum = Math.Min(xDataMaximum, p.X);
            }

            model.Series.Add(series);

            if (metadata.CalibrationHelper.CalibratorType == CalibratorType.Plane)
            {
                cbCalibrationPlane.Checked = true;
                cbCalibrationPlane.Enabled = true;

                CalibrationHelper calibrator = metadata.CalibrationHelper;
                QuadrilateralF    quadImage  = calibrator.CalibrationByPlane_GetProjectedQuad();
                PointF            a          = calibrator.GetPointFromRectified(quadImage.A);
                PointF            b          = calibrator.GetPointFromRectified(quadImage.B);
                PointF            c          = calibrator.GetPointFromRectified(quadImage.C);
                PointF            d          = calibrator.GetPointFromRectified(quadImage.D);

                rectangleAnnotation          = new RectangleAnnotation();
                rectangleAnnotation.MinimumX = a.X;
                rectangleAnnotation.MaximumX = b.X;
                rectangleAnnotation.MinimumY = d.Y;
                rectangleAnnotation.MaximumY = a.Y;
                rectangleAnnotation.Fill     = OxyColor.FromArgb(96, 173, 223, 247);
                rectangleAnnotation.Layer    = AnnotationLayer.BelowAxes;
                model.Annotations.Add(rectangleAnnotation);

                if (a.Y > yDataMaximum || d.Y < yDataMinimum)
                {
                    yDataMaximum = Math.Max(yDataMaximum, a.Y);
                    yDataMinimum = Math.Min(yDataMinimum, d.Y);

                    double yPadding = (yDataMaximum - yDataMinimum) * padding;
                    yAxis.Maximum = yDataMaximum + yPadding;
                    yAxis.Minimum = yDataMinimum - yPadding;
                }

                if (b.X > xDataMaximum || a.X < xDataMinimum)
                {
                    xDataMaximum = Math.Max(xDataMaximum, b.X);
                    xDataMinimum = Math.Min(xDataMinimum, a.X);

                    double xPadding = (xDataMaximum - xDataMinimum) * padding;
                    xAxis.Maximum = xDataMaximum + xPadding;
                    xAxis.Minimum = xDataMinimum - xPadding;
                }
            }
            else
            {
                cbCalibrationPlane.Checked = false;
                cbCalibrationPlane.Enabled = false;
            }

            plotScatter.Model = model;
        }
Exemplo n.º 4
0
        private static CoordinateSystemGrid FindForPlaneCalibration(CalibrationHelper calibrationHelper)
        {
            CoordinateSystemGrid grid        = new CoordinateSystemGrid();
            RectangleF           imageBounds = new RectangleF(PointF.Empty, calibrationHelper.ImageSize);
            RectangleF           clipWindow  = imageBounds;

            CalibrationPlane calibrator = calibrationHelper.CalibrationByPlane_GetCalibrator();

            RectangleF plane = new RectangleF(PointF.Empty, calibrator.Size);

            int   targetSteps    = 15;
            float stepVertical   = 1.0f;
            float stepHorizontal = 1.0f;

            // The extended plane is used for vanishing point replacement and iteration stop condition.
            QuadrilateralF extendedPlane;
            bool           orthogonal;

            if (!calibrator.QuadImage.IsRectangle)
            {
                // If perspective plane, define as 2n times the nominal plane centered on origin.
                orthogonal = false;
                float  n = 4;
                PointF a = new PointF(-calibrator.Size.Width * n, calibrator.Size.Height * n);
                PointF b = new PointF(calibrator.Size.Width * n, calibrator.Size.Height * n);
                PointF c = new PointF(calibrator.Size.Width * n, -calibrator.Size.Height * n);
                PointF d = new PointF(-calibrator.Size.Width * n, -calibrator.Size.Height * n);
                extendedPlane = new QuadrilateralF(a, b, c, d);

                QuadrilateralF quadImage = calibrator.QuadImage;

                float projectedWidthLength   = GeometryHelper.GetDistance(quadImage.A, quadImage.B);
                float scaledTargetHorizontal = targetSteps / (calibrationHelper.ImageSize.Width / projectedWidthLength);
                stepHorizontal = RangeHelper.FindUsableStepSize(plane.Width, scaledTargetHorizontal);

                float projectedHeightLength = GeometryHelper.GetDistance(quadImage.A, quadImage.D);
                float scaledTargetVertical  = targetSteps / (calibrationHelper.ImageSize.Height / projectedHeightLength);
                stepVertical = RangeHelper.FindUsableStepSize(plane.Height, scaledTargetVertical);
            }
            else
            {
                // If flat plane (and no distortion) we know there is no way to get any vanishing point inside the image,
                // so we can safely use the whole image reprojection as an extended plane.
                orthogonal = true;
                QuadrilateralF quadImageBounds = new QuadrilateralF(imageBounds);
                PointF         a = calibrationHelper.GetPointFromRectified(quadImageBounds.A);
                PointF         b = calibrationHelper.GetPointFromRectified(quadImageBounds.B);
                PointF         c = calibrationHelper.GetPointFromRectified(quadImageBounds.C);
                PointF         d = calibrationHelper.GetPointFromRectified(quadImageBounds.D);
                extendedPlane = new QuadrilateralF(a, b, c, d);

                float width = extendedPlane.B.X - extendedPlane.A.X;
                stepHorizontal = RangeHelper.FindUsableStepSize(width, targetSteps);

                float height = extendedPlane.A.Y - extendedPlane.D.Y;
                stepVertical = RangeHelper.FindUsableStepSize(height, targetSteps);
            }

            //-------------------------------------------------------------------------------------------------
            // There is a complication with points behind the camera, as they projects above the vanishing line.
            // The general strategy is the following:
            // Find out if the vanishing point is inside the image. Reminder: parallel lines share the same vanishing point.
            // If it is not inside the image, there is no risk, so we take two points on the line and draw an infinite line that we clip against the image bounds.
            // If it is inside the image:
            // Take two points on the line and project them in image space. They are colinear with the vanishing point in image space.
            // Find on which side of the quadrilateral the vanishing point is.
            // If the vanishing point is above the quad, draw a ray from the top of the extended quad, down to infinity.
            // If the vanishing point is below the quad, draw a ray from the bottom of the extended quad, up to infinity.
            //
            // Stepping strategy:
            // We start at origin and progress horizontally and vertically until we find a gridline that is completely clipped out.
            //-------------------------------------------------------------------------------------------------

            // Vertical lines.
            PointF  yVanish        = new PointF(0, float.MinValue);
            bool    yVanishVisible = false;
            Vector3 yv             = calibrator.Project(new Vector3(0, 1, 0));

            if (yv.Z != 0)
            {
                yVanish        = new PointF(yv.X / yv.Z, yv.Y / yv.Z);
                yVanishVisible = clipWindow.Contains(yVanish);
            }

            CreateVerticalGridLines(grid, 0, -stepHorizontal, calibrator, clipWindow, plane, extendedPlane, orthogonal, yVanishVisible, yVanish);
            CreateVerticalGridLines(grid, stepHorizontal, stepHorizontal, calibrator, clipWindow, plane, extendedPlane, orthogonal, yVanishVisible, yVanish);

            // Horizontal lines
            PointF  xVanish        = new PointF(float.MinValue, 0);
            bool    xVanishVisible = false;
            Vector3 xv             = calibrator.Project(new Vector3(1, 0, 0));

            if (xv.Z != 0)
            {
                xVanish        = new PointF(xv.X / xv.Z, xv.Y / xv.Z);
                xVanishVisible = clipWindow.Contains(xVanish);
            }

            CreateHorizontalGridLines(grid, 0, -stepVertical, calibrator, clipWindow, plane, extendedPlane, orthogonal, xVanishVisible, xVanish);
            CreateHorizontalGridLines(grid, stepVertical, stepVertical, calibrator, clipWindow, plane, extendedPlane, orthogonal, xVanishVisible, xVanish);

            return(grid);
        }