Exemple #1
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);
        }
Exemple #2
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);
        }
        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);
        }
Exemple #4
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);
        }
        private IEnumerable <LineSegment2D> GetLinesFromFocusImage(Image <Bgr, byte> focus, CircleF circle, DebugState debugState)
        {
            Mat vspeedMask = new Mat(focus.Size, DepthType.Cv8U, 3);

            vspeedMask.SetTo(new MCvScalar(1));
            CvInvoke.Circle(vspeedMask, new Point(focus.Width / 2, focus.Height / 2), (int)(circle.Radius - 12), new Bgr(Color.White).MCvScalar, -1);

            var vspeed_inner_hsv = focus.Copy(vspeedMask.ToImage <Gray, byte>()).Convert <Hsv, byte>()
                                   .DynLowInRange(_dyn_lower_only_needle, new Hsv(180, 255, 255));
            var clean_inner_no_blobs = Utils.RemoveBlobs(vspeed_inner_hsv, 1, 10);
            var cannyEdges3          = new Mat();

            CvInvoke.Canny(clean_inner_no_blobs, cannyEdges3, 10, 250);

            Mat dialatedCanny = new Mat();

            CvInvoke.Dilate(cannyEdges3, dialatedCanny, null, new Point(-1, -1), 1, BorderType.Default, new Gray(0).MCvScalar);

            debugState.Add(vspeed_inner_hsv);
            debugState.Add(clean_inner_no_blobs);
            debugState.Add(cannyEdges3.ToImage <Gray, byte>());
            debugState.Add(dialatedCanny);

            var lines = CvInvoke.HoughLinesP(dialatedCanny, 1, Math.PI / 45, 30, 20, 1).Where(p => p.Length > 18);

            Rectangle centerBox          = GetCenterBoxFromImage(focus);
            var       linesInCenterImage = new List <LineSegment2D>();

            foreach (var line in lines)
            {
                if (centerBox.Contains(line.P1))
                {
                    linesInCenterImage.Add(new LineSegment2D(line.P2, line.P1));
                }
                else if (centerBox.Contains(line.P2))
                {
                    linesInCenterImage.Add(new LineSegment2D(line.P1, line.P2));
                }
            }

            return(linesInCenterImage.OrderByDescending(l => l.Length));
        }
Exemple #6
0
        public double ReadValue(IndicatorData data, DebugState debugState)
        {
            if (RollIndicator.TryFindRollCircleInFullFrame(data, out var circle))
            {
                var firstCrop = new Rectangle((int)circle.Center.X + 500, (int)circle.Center.Y - 180, 100, 150);
                var focus     = data.Frame.SafeCopy(firstCrop);

                var vs_blackImg = focus.Convert <Hsv, byte>().InRange(new Hsv(0, 120, 0), new Hsv(180, 255, 255));

                var blobs = Utils.DetectAndFilterBlobs(vs_blackImg.PyrUp().PyrDown(), 1500, 2500);
                if (blobs.Any())
                {
                    var landingGearFrame = focus.Copy(blobs.First().BoundingBox);

                    var hsv       = landingGearFrame.Convert <Hsv, byte>();
                    var black_img = hsv.DynLowInRange(dyn_lower, new Hsv(180, 255, 255));
                    debugState.Add(landingGearFrame);
                    debugState.Add(black_img);

                    blobs = Utils.DetectAndFilterBlobs(black_img, 200, 1500);
                    if (blobs.Any())
                    {
                        var blob = blobs.First();
                        var ret  = (landingGearFrame.Height / 2) - blob.Centroid.Y;

                        if (ret > 4)
                        {
                            return(1);
                        }
                        else if (ret < -4)
                        {
                            return(-1);
                        }
                    }
                }
            }
            return(double.NaN);
        }
Exemple #7
0
        private IEnumerable <BlobPack> GetPacksFromImage(Image <Gray, byte> focus, IEnumerable <CvBlob> blobs, DebugState debugState)
        {
            var frame_center = new Point(focus.Width / 2, focus.Height / 2);
            var parts        = new List <BlobPack>();

            foreach (var b in blobs)
            {
                b.BoundingBox.Inflate(2, 2);
                var rotationAngle = Math2.GetPolarHeadingFromLine(new LineSegment2D(Point.Round(b.Centroid), frame_center));

                var rotated_frame       = focus.Rotate(-1 * rotationAngle, new Gray(0));
                var rotated_letter_only = rotated_frame.Copy(new Rectangle(rotated_frame.Width / 2 - 30, 0, 60, 60));

                //  rotated_letter_only = Utils.RemoveBlobs(rotated_letter_only, 1, 3);

                debugState.Add(rotated_letter_only);

                parts.Add(new BlobPack {
                    BlobImage = rotated_letter_only, BlobRationAngle = rotationAngle, BlobBox = b.BoundingBox
                });
            }
            return(parts);
        }
Exemple #8
0
        private double GetGlareShieldSkewAngle(Rectangle focusRect, IndicatorData data, DebugState debugState)
        {
            var topDotRect    = new Rectangle(focusRect.Left - 160, focusRect.Top - 5, 40, 40);
            var bottomDotRect = new Rectangle(focusRect.Left - 170, focusRect.Bottom - 40, 60, 40);

            var topPointBlobs    = GetDotLocationFromFullFrame(data.Frame, focusRect, topDotRect, isTop: true);
            var bottomPointBlobs = GetDotLocationFromFullFrame(data.Frame, focusRect, bottomDotRect, isTop: false);

            double a = double.NaN;

            if (topPointBlobs.Count > 0 && bottomPointBlobs.Count > 0)
            {
                var topPoint    = topPointBlobs.First().Centroid.Add(topDotRect.Location);
                var bottomPoint = bottomPointBlobs.First().Centroid.Add(bottomDotRect.Location);

                a = Math2.GetPolarHeadingFromLine(topPoint, bottomPoint);
                if (a > 180)
                {
                    a  = 360 - a;
                    a *= -1;
                }

                var lineRect = new Rectangle(focusRect.Left - 200, focusRect.Top - 50, 170, focusRect.Bottom + 50 - focusRect.Top);
                var lineImg  = data.Frame.Copy(lineRect);

                var topInLineImg    = new PointF(topPoint.X - lineRect.Location.X, topPoint.Y - lineRect.Location.Y);
                var bottomInLineImg = new PointF(bottomPoint.X - lineRect.Location.X, bottomPoint.Y - lineRect.Location.Y);

                var topRange = lineImg.Convert <Hsv, byte>(); //.InRange(new Hsv(HLow, SLow, VLow), new Hsv(HHigh, SHigh, VHigh));
                CvInvoke.Line(lineImg, topInLineImg.ToPoint(), bottomInLineImg.ToPoint(), new Bgr(Color.Yellow).MCvScalar, 1);
                debugState.Add(lineImg);
                debugState.Add(topRange);

                var dist = Math2.GetDistance(topPoint, bottomPoint);
                if (Math.Abs(a) > 8 || dist < 110 || dist > 120)
                {
                    var biasFrame = Timeline.LatestFrame(f => f.Heading.ForIndicatorUse == null ? double.NaN : ((ExtendedData)f.Heading.ForIndicatorUse).Bias, data.Id);
                    if (biasFrame != null)
                    {
                        a = ((ExtendedData)biasFrame.Heading.ForIndicatorUse).Bias;
                    }
                    else
                    {
                        debugState.SetError("Rejected due to dots angle out of bounds " + a);
                        return(double.NaN);
                    }
                }
            }
            else
            {
                var biasFrame = Timeline.LatestFrame(f => f.Heading.ForIndicatorUse == null ? double.NaN : ((ExtendedData)f.Heading.ForIndicatorUse).Bias, data.Id);
                if (biasFrame != null)
                {
                    a = ((ExtendedData)biasFrame.Heading.ForIndicatorUse).Bias;
                }
                else
                {
                    debugState.SetError("Rejected due to dots angle out of bounds " + a);
                    return(double.NaN);
                }
            }

            ((ExtendedData)Timeline.Data[data.Id].Heading.ForIndicatorUse).Bias = a;
            return(a / 2);
        }
        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);
        }