Example #1
0
        public double ReadValue(IndicatorData data, DebugState debugState)
        {
            if (TryFindCircleInFullFrame(data, out var circle))
            {
                var focus = data.Frame.Copy(Math2.CropCircle(circle, 10));
                debugState.Add(focus);

                List <double> ret = new List <double>();
                foreach (var line in GetLinesFromFocusImage(focus, circle, debugState))
                {
                    CvInvoke.Line(focus, line.P1, line.P2, new Bgr(Color.Yellow).MCvScalar, 2);

                    var knots = ReadKnotsFromNeedleLine(line);

                    if (IsValueInExpectedRange(knots))
                    {
                        ret.Add(knots);
                    }
                }

                return(CalculateResultFromAllResults(ret, debugState));
            }
            else
            {
                debugState.SetError("No circles");
            }
            return(double.NaN);
        }
Example #2
0
        public double ReadValue(IndicatorData data, DebugState debugState)
        {
            if (TryFindRollCircleInFullFrame(data, out CircleF rollIndicatorCicle))
            {
                var FocusRect = Math2.CropCircle(rollIndicatorCicle, 10);
                var focus     = data.Frame.SafeCopy(FocusRect);

                debugState.Add(focus);

                // Isolate the outside ring
                Mat maskInnerAlt = new Mat(focus.Size, DepthType.Cv8U, 3);
                maskInnerAlt.SetTo(new MCvScalar(1));
                CvInvoke.Circle(maskInnerAlt, new Point(focus.Size.Width / 2, focus.Size.Height / 2), (int)(rollIndicatorCicle.Radius - (rollIndicatorCicle.Radius * 0.2)), new Bgr(Color.White).MCvScalar, -1);
                CvInvoke.Circle(maskInnerAlt, new Point(focus.Size.Width / 2, focus.Size.Height / 2), (int)(rollIndicatorCicle.Radius - (rollIndicatorCicle.Radius * 0.275)), new Bgr(Color.Black).MCvScalar, -1);

                var outerMovingRingOnly          = focus.Copy(maskInnerAlt.ToImage <Gray, byte>());
                var outerMovingRingWithoutBottom = outerMovingRingOnly.Copy(new Rectangle(0, 0, outerMovingRingOnly.Width, (int)(outerMovingRingOnly.Height))); // - (outerMovingRingOnly.Height * 0.29)
                var ring_hsv_unfiltered          = outerMovingRingWithoutBottom.Convert <Hsv, byte>().InRange(new Hsv(20, 0, 85), new Hsv(180, 255, 255));
                var ring_hsv = Utils.RemoveBlobs(ring_hsv_unfiltered, 1, 500);

                debugState.Add(outerMovingRingOnly);
                debugState.Add(outerMovingRingWithoutBottom);
                debugState.Add(ring_hsv);
                debugState.Add(ring_hsv_unfiltered);

                return(ReadRollAngleFromRingImage(ring_hsv, focus, debugState));
            }
            else
            {
                debugState.SetError($"ROLL: Main circles");
            }
            return(double.NaN);
        }
Example #3
0
        public double ReadValue(IndicatorData data, DebugState debugState)
        {
            if (TryFindCircleInFullFrame(data, out var circle))
            {
                var focus       = data.Frame.SafeCopy(Math2.CropCircle(circle, 15));
                var vs_blackimg = focus.Convert <Hsv, byte>().DynLowInRange(dyn_lower, new Hsv(180, 255, 255));

                debugState.Add(focus);
                debugState.Add(vs_blackimg);

                int margin     = 10;
                var vspeedMask = new Mat(focus.Size, DepthType.Cv8U, 3);
                vspeedMask.SetTo(new MCvScalar(1));
                CvInvoke.Circle(vspeedMask, Point.Round(new PointF(circle.Radius + margin, circle.Radius + margin)), (int)(circle.Radius - (circle.Radius * 0.1)), new Bgr(Color.White).MCvScalar, -1);
                vs_blackimg = vs_blackimg.Copy(vspeedMask.ToImage <Gray, byte>());

                var vspeed_inner_only = vs_blackimg.Copy(new Rectangle(0, 0, vs_blackimg.Width / 2, vs_blackimg.Height));

                debugState.Add(vspeed_inner_only);

                Rectangle center = GetCenterBoxFromImage(focus);
                foreach (var line in CvInvoke.HoughLinesP(vspeed_inner_only, 1, Math.PI / 45.0, 20, 20, 14))
                {
                    if (center.Contains(line.P1) || center.Contains(line.P2))
                    {
                        CvInvoke.Line(focus, line.P1, line.P2, new Bgr(Color.Yellow).MCvScalar, 2);

                        LineSegment2D needleLine;
                        if (center.Contains(line.P1))
                        {
                            needleLine = new LineSegment2D(line.P2, line.P1);
                        }
                        else
                        {
                            needleLine = new LineSegment2D(line.P1, line.P2);
                        }

                        var angle = (Math2.GetPolarHeadingFromLine(needleLine) - 270);
                        // bias up to account for skew
                        angle += 2.75;

                        if (line.Length > 63)
                        {
                            debugState.SetError($"Rejected length: {line.Length}");
                        }
                        return(angle);
                    }
                }
            }
            return(double.NaN);
        }
Example #4
0
        public static bool TryFindRollCircleInFullFrame(IndicatorData data, out CircleF ret)
        {
            ret = default(CircleF);

            if (Timeline.Data[data.Id].Roll.ForIndicatorUse != null)
            {
                // We found our own hint, return it.
                ret = (CircleF)Timeline.Data[data.Id].Roll.ForIndicatorUse;
                return(true);
            }

            var localRect = MovementRect;

            if (data.Id > 0 &&
                Timeline.Data[data.Id - 1] != null &&
                Timeline.Data[data.Id - 1].Roll != null &&
                Timeline.Data[data.Id - 1].Roll.ForIndicatorUse != null)
            {
                // Our hint from last time.
                localRect = Math2.CropCircle((CircleF)Timeline.Data[data.Id - 1].Roll.ForIndicatorUse, 10);
            }

            // Crop and blur
            var cropped_frame = data.Frame.SafeCopy(localRect).PyrUp().PyrDown();

            var MovementFrameGray = new Mat();

            CvInvoke.CvtColor(cropped_frame, MovementFrameGray, ColorConversion.Bgr2Gray);

            // Locate the attitude and possibly vertical speed indicators.
            var circles = CvInvoke.HoughCircles(MovementFrameGray, HoughType.Gradient, 2.0, 20, 10, 180, 60, 80);

            if (circles.Length == 0)
            {
                // Couldn't find initial circle
                return(false);
            }

            // Pick the topmost circle and crop.
            var rollIndicatorCicle = circles.OrderBy(c => c.Center.Y).First();

            rollIndicatorCicle.Radius = 64;
            rollIndicatorCicle.Center = rollIndicatorCicle.Center.Add(localRect.Location);
            ret = rollIndicatorCicle;
            Timeline.Data[data.Id].Roll.ForIndicatorUse = ret;
            return(true);
        }
Example #5
0
        public double ReadValue(IndicatorData data, DebugState debugState)
        {
            if (TryFindCircleInFullFrame(data, out var circ))
            {
                var focusRect            = Math2.CropCircle(circ, 15);
                var focus                = data.Frame.SafeCopy(focusRect);
                var focusHsv             = focus.Convert <Hsv, byte>();
                var focusHsvText         = focusHsv.DynLowInRange(dyn_lower, new Hsv(180, 255, 255));
                var focusHsvTriangleMask = focusHsv.InRange(new Hsv(0, 0, 0), new Hsv(180, 140, 255));
                var focusHsvTextOnly     = focusHsvText.Copy(focusHsvTriangleMask);

                debugState.Add(focus);

                var blobs = Utils.DetectAndFilterBlobs(focusHsvTextOnly, 25, 250).
                            Where(b => b.Centroid.Y >= 5).OrderByDescending(b => b.Area).Take(4);

                var focusHsvOnlyBlobs = Utils.RemoveAllButBlobs(focusHsvTextOnly, blobs);
                debugState.Add(focusHsvOnlyBlobs);

                var parts = GetPacksFromImage(focusHsvOnlyBlobs, blobs, debugState);
                var ret   = ComputeHeadingFromPacks(data.Id, parts, focus, debugState);

                if (!double.IsNaN(ret))
                {
                    // Adjust now that N and S are near-vertical and the blobs are more regular.
                    ret = RefineAngle(ret, focusHsvOnlyBlobs);
                    // Adjust based on the dots on the glareshield.
                    ret += GetGlareShieldSkewAngle(focusRect, data, debugState);
                    // Add a fixed cab skew to account for the vertical perspective.
                    ret -= 1;

                    ret = Math2.ClampAngle(ret);

                    // Proof for the debug info.
                    debugState.Add(focus.Rotate(ret, new Bgr(0, 0, 0)));

                    return(CheckResultValidity(ret, data.Id));
                }
            }
            else
            {
                debugState.SetError("Couldn't find initial circle.");
            }
            return(double.NaN);
        }
Example #6
0
        private static bool TryFindCircleInFullFrame(IndicatorData data, out CircleF ret)
        {
            ret = default(CircleF);

            if (RollIndicator.TryFindRollCircleInFullFrame(data, out var circle))
            {
                circle.Center = new PointF(circle.Center.X + 140, circle.Center.Y + 70);
                circle.Radius = 55;
                var firstCrop = Math2.CropCircle(circle, 10);
                var focus     = data.Frame.SafeCopy(firstCrop);

                var circles = CvInvoke.HoughCircles(focus.Convert <Hsv, byte>()[2], HoughType.Gradient, 2.0, 20, 10, 180, 45, 55);
                if (circles.Length == 1)
                {
                    circles[0].Center = circles[0].Center.Add(firstCrop.Location);
                    circles[0].Radius = 50;
                    ret = circles[0];
                    return(true);
                }
            }
            return(false);
        }
Example #7
0
        private static bool TryFindCircleInFullFrame(IndicatorData data, out CircleF ret)
        {
            ret = default(CircleF);

            if (RollIndicator.TryFindRollCircleInFullFrame(data, out var circle))
            {
                circle.Center = new PointF(circle.Center.X + 1055, circle.Center.Y - 20);
                circle.Radius = 70;
                var firstCrop = Math2.CropCircle(circle, 40);
                var focus     = data.Frame.SafeCopy(firstCrop);
                var focusHsv  = focus.Convert <Hsv, byte>().PyrUp().PyrDown();

                var circles = CvInvoke.HoughCircles(focusHsv[2], HoughType.Gradient, 2.0, 80, 10, 80, 60, 80);
                if (circles.Length == 1)
                {
                    var circ = circles[0];
                    circles[0].Center = circles[0].Center.Add(firstCrop.Location);
                    circles[0].Radius = 64;
                    ret = circles[0];
                    return(true);
                }
            }
            return(false);
        }
Example #8
0
        public double ReadValue(IndicatorData data, DebugState debugState)
        {
            if (TryFindCircleInFullFrame(data, out var circle))
            {
                var focus          = data.Frame.SafeCopy(Math2.CropCircle(circle, 15));
                var vs_blackimg    = focus.Convert <Hsv, byte>().DynLowInRange(dyn_lower, new Hsv(180, 255, 255)).PyrUp().PyrDown();
                var markedup_frame = vs_blackimg.Convert <Bgr, byte>();
                debugState.Add(focus);
                debugState.Add(vs_blackimg);
                debugState.Add(markedup_frame);

                var cannyEdges3 = new Mat();
                CvInvoke.Canny(vs_blackimg, cannyEdges3, 10, 120);
                Mat dialatedCanny = new Mat();
                CvInvoke.Dilate(cannyEdges3, dialatedCanny, null, new Point(-1, -1), 1, BorderType.Default, new Gray(0).MCvScalar);

                Rectangle center = GetCenterBoxFromImage(focus);
                CvInvoke.Rectangle(markedup_frame, center, new Bgr(Color.Red).MCvScalar, 1);

                var lines = CvInvoke.HoughLinesP(dialatedCanny, 1, Math.PI / 45.0, 20, 16, 0).OrderByDescending(l => l.Length);
                foreach (var line in lines)
                {
                    CvInvoke.Line(markedup_frame, line.P1, line.P2, new Bgr(Color.Red).MCvScalar, 1);

                    if (center.Contains(line.P1) || center.Contains(line.P2))
                    {
                        LineSegment2D needleLine;
                        if (center.Contains(line.P1))
                        {
                            needleLine = new LineSegment2D(line.P2, line.P1);
                        }
                        else
                        {
                            needleLine = new LineSegment2D(line.P1, line.P2);
                        }

                        var angle    = Math2.GetPolarHeadingFromLine(needleLine);
                        var hundreds = Math.Round((angle / 360) * 999);

                        CvInvoke.Line(focus, needleLine.P1, needleLine.P2, new Bgr(Color.Yellow).MCvScalar, 2);

                        var candidates = new List <double>();
                        for (var i = 0; i < 9; i++)
                        {
                            candidates.Add(hundreds + (i * 1000));
                        }

                        var ret = candidates.OrderBy(c => Math.Abs(c - Timeline.Altitude)).First();

                        if (!double.IsNaN(Timeline.Altitude))
                        {
                            var delta = Math.Abs(ret - Timeline.Altitude);
                            if (delta > 400)
                            {
                                debugState.SetError($"Bad value {delta} > 400");
                                return(double.NaN);
                            }
                        }
                        else
                        {
                            return(0);
                        }

                        return(ret);
                    }
                }
            }
            return(double.NaN);
        }