Exemple #1
0
 /// <summary>
 /// Creates a traffic sign match
 /// </summary>
 /// <param name="candidate"> candidate sign </param>
 /// <param name="knownSign"> known sign </param>
 /// <param name="matchScore"> match score </param>
 /// <param name="matches"> feature matches </param>
 /// <param name="homography"> homography matrix </param>
 public TrafficSignMatch(TrafficSign candidate, TrafficSign knownSign, int matchScore, VectorOfVectorOfDMatch matches, Mat homography)
 {
     Candidate  = candidate;
     KnownSign  = knownSign;
     MatchScore = matchScore;
     Matches    = matches;
     Homography = homography;
 }
        /// <summary>
        /// Detects the keypoints and computes the features for a sign
        /// </summary>
        /// <param name="sign"> Sign to update </param>
        private void UpdateDescriptors(TrafficSign sign)
        {
            Mat desc            = new Mat();
            VectorOfKeyPoint kp = new VectorOfKeyPoint();

            detector.DetectAndCompute(sign.ImageGray, null, kp, desc, false);
            sign.Features  = desc;
            sign.KeyPoints = kp;
        }
        /// <summary>
        /// Converts contours to candidates and deny small or big contours
        /// </summary>
        /// <param name="contours"> contours of blobs </param>
        /// <param name="context"> original color image </param>
        /// <returns> Sign Candidates </returns>
        private List <TrafficSign> ContoursToCandidates(VectorOfVectorOfPoint contours, Image <Bgr, byte> context)
        {
            List <TrafficSign> goodCandidates = new List <TrafficSign>();
            List <Rectangle>   boxes          = new List <Rectangle>();

            // Iterate over contours
            for (int i = 0; i < contours.Size; i++)
            {
                Rectangle bb = CvInvoke.BoundingRectangle(contours[i]);
                // Deny small
                if (bb.Height < 20)
                {
                    continue;
                }
                if (bb.Width < 20)
                {
                    continue;
                }

                // Deny strange shape
                if ((double)bb.Width / bb.Height < 0.80)
                {
                    continue;
                }

                // Merge overlapping BBs
                Rectangle rectToRemove = Rectangle.Empty;
                boxes.ForEach(other =>
                {
                    if (other.IntersectsWith(bb))
                    {
                        bb           = CvInvoke.cvMaxRect(bb, other);
                        rectToRemove = other;
                    }
                });
                if (!rectToRemove.IsEmpty)
                {
                    boxes.Remove(rectToRemove);
                }
                Rectangle paddedRoi = new Rectangle(bb.Location, bb.Size);
                paddedRoi.Inflate(CandidatePadding, CandidatePadding);
                boxes.Add(paddedRoi);
            }

            // Convert boxes to Candidate objects
            boxes.ForEach(paddedRoi =>
            {
                TrafficSign newCandidate        = new TrafficSign(context.Copy(paddedRoi), null);
                newCandidate.BoundingBoxInScene = paddedRoi;
                goodCandidates.Add(newCandidate);
            });
            return(goodCandidates);
        }
        /// <summary>
        /// Match this sign to an other sign
        /// </summary>
        /// <param name="otherSign"> other traffic sign </param>
        /// <returns> matched features as matches </returns>
        public VectorOfVectorOfDMatch MatchToOtherSign(TrafficSign otherSign)
        {
            if (!IsKnownSign)
            {
                throw new Exception("Only known signs support matching.");
            }
            if (otherSign.Features.Cols < 1)
            {
                throw new Exception("Other sign has no descriptors to match.");
            }
            if (Features.Cols < 1)
            {
                throw new Exception("Current sign has no features to match.");
            }
            VectorOfVectorOfDMatch matches = new VectorOfVectorOfDMatch();

            matcher.KnnMatch(otherSign.features, matches, 2, null);
            return(matches);
        }
 /// <summary>
 /// Reads known signs from folder
 /// </summary>
 public void ReadKnownSigns()
 {
     if (!Directory.Exists(KnownSignsPath))
     {
         throw new Exception("Cannot open folder: " + KnownSignsPath);
     }
     KnownSigns = new List <TrafficSign>();
     foreach (string file in Directory.EnumerateFiles(KnownSignsPath))
     {
         try
         {
             TrafficSign sign = new TrafficSign(new Image <Bgr, byte>(file), Path.GetFileName(file));
             UpdateDescriptors(sign);
             KnownSigns.Add(sign);
         } catch (Exception ex)
         {
             // Log problem
             Console.WriteLine(ex.Message);
         }
     }
 }
        /// <summary>
        /// Computes a score for a match, higher is better
        /// </summary>
        /// <param name="homography"> homography matrix </param>
        /// <param name="known"> known sign </param>
        /// <param name="candidate"> candidate sign </param>
        /// <returns> score of the match </returns>
        public int ScoreMatch(Mat homography, TrafficSign known, TrafficSign candidate)
        {
            // Default score
            int score = -1;

            if (homography == null)
            {
                return(0);
            }

            // Create rectangle and transorm based on homography
            Rectangle rect = new Rectangle(Point.Empty, known.ImageGray.Size);

            PointF[] pts = new PointF[]
            {
                new PointF(rect.Left, rect.Top),
                new PointF(rect.Right, rect.Top),
                new PointF(rect.Right, rect.Bottom),
                new PointF(rect.Left, rect.Bottom)
            };
            pts = CvInvoke.PerspectiveTransform(pts, homography);

            // Check transformed recatangle
            // Scene corners should form rectangular shape
            // Check relative positions left upper
            if ((pts[0].X > pts[1].X) || (pts[0].X > pts[2].X))
            {
                return(0);
            }
            if ((pts[0].Y > pts[2].Y) || (pts[0].Y > pts[3].Y))
            {
                return(0);
            }

            // Check relative positions right upper
            if ((pts[1].X < pts[0].X) || (pts[1].X < pts[3].X))
            {
                return(0);
            }
            if ((pts[1].Y > pts[2].Y) || (pts[1].Y > pts[3].Y))
            {
                return(0);
            }

            // Check relative positions right lower
            if ((pts[2].X < pts[0].X) || (pts[2].X < pts[3].X))
            {
                return(0);
            }
            if ((pts[2].Y < pts[0].Y) || (pts[2].Y < pts[1].Y))
            {
                return(0);
            }

            // Check relative positions left lower
            if ((pts[3].Y > pts[1].X) || (pts[3].X > pts[2].X))
            {
                return(0);
            }
            if ((pts[3].Y < pts[0].Y) || (pts[3].Y < pts[1].Y))
            {
                return(0);
            }

            score = 1;

            // Low score for strange shaped rectangles
            double dia1 = Math.Sqrt(Math.Pow(pts[2].X - pts[0].X, 2) + Math.Pow(pts[2].Y - pts[0].Y, 2));
            double dia2 = Math.Sqrt(Math.Pow(pts[1].X - pts[3].X, 2) + Math.Pow(pts[3].Y - pts[1].Y, 2));

            if (dia1 * dia2 < known.ImageGray.Size.Height / 5)
            {
                return(score);
            }

            double edgeRatioMax = 0.2;

            if (Math.Abs(1.0 - (dia1 / dia2)) > edgeRatioMax)
            {
                return(score);
            }
            score = 2;

            // Check based on template  matching
            Image <Gray, byte> perspective = new Image <Gray, byte>(known.ImageGray.Size);
            Image <Gray, byte> templateRes = new Image <Gray, byte>(known.ImageGray.Size);
            double             maxValue    = 0;
            Point  maxLoc   = new Point();
            double minValue = 0;
            Point  minLoc   = new Point();

            CvInvoke.WarpPerspective(known.ImageGray, perspective, homography, known.ImageGray.Size, Emgu.CV.CvEnum.Inter.Linear);
            CvInvoke.MatchTemplate(candidate.ImageGray, perspective, templateRes, TemplateMatchingType.Ccoeff, null);
            CvInvoke.MinMaxLoc(templateRes, ref minValue, ref maxValue, ref minLoc, ref maxLoc);

            return(score + (int)maxValue);
        }