private void trainModel(String plantCategoryName, List <String> eachLeafSpecies)
        {
            BFMatcher match;

            if (!categoryBfmatcherMapping.ContainsKey(plantCategoryName))
            {
                match = new BFMatcher(DistanceType.L2);
                categoryBfmatcherMapping.Add(plantCategoryName, match);
            }
            else
            {
                //Find values associated with key
                match = categoryBfmatcherMapping[plantCategoryName];
            }
            foreach (String leaf in eachLeafSpecies)
            {
                using (Image <Bgr, Byte> image = loadImage(leaf))
                {
                    using (PreProcess preProcessAlgorithm = new PreProcess(image))
                    {
                        using (Image <Hsv, Byte> HSVImage = preProcessAlgorithm._ImageToHSV())
                        {
                            using (Image <Gray, Byte> grayScaleImage = preProcessAlgorithm._ImageToGrayScaleUsingConvert())
                            {
                                using (FeatureExtractAlgorithm featureSet = new FeatureExtractAlgorithm(grayScaleImage))
                                {
                                    KeyPoints leafDescriptor = featureSet.SIFTDescriptor();
                                    match.Add(leafDescriptor.Descriptor);
                                }
                            }
                        }
                    }
                }
            }
        }
        public KeyPoints SIFTDescriptor()
        {
            KeyPoints result = new KeyPoints();
            //SiFT Descriptor
            SIFT             siftAlgo           = null;
            VectorOfKeyPoint modelKeyPointsSift = null;

            try
            {
                siftAlgo           = new SIFT();
                modelKeyPointsSift = new VectorOfKeyPoint();

                MKeyPoint[] siftPoints = siftAlgo.Detect(preProcessedImageInGrayScale);
                modelKeyPointsSift.Push(siftPoints);
                UMat siftDescriptors = new UMat();
                siftAlgo.DetectAndCompute(preProcessedImageInGrayScale, null, modelKeyPointsSift, siftDescriptors, true);
                Image <Gray, Byte> outputImage = new Image <Gray, byte>(
                    preProcessedImageInGrayScale.Width,
                    preProcessedImageInGrayScale.Height);
                Features2DToolbox.DrawKeypoints(
                    preProcessedImageInGrayScale,
                    modelKeyPointsSift,
                    outputImage,
                    new Bgr(255, 255, 255),
                    Features2DToolbox.KeypointDrawType.Default);

                string folderName = @"C:\Projects\LeafService\SiftImage";
                string pathString = System.IO.Path.Combine(folderName, "Sift" + DateTime.UtcNow.Ticks);
                System.IO.Directory.CreateDirectory(pathString);
                if (Directory.Exists(pathString))
                {
                    string newFilePath = Path.Combine(pathString, "SiftImage" + DateTime.UtcNow.Ticks);
                    outputImage.Save(folderName + ".jpg");
                    outputImage.Save(@"C:\Projects\LeafService\SIFTgray.jpg");
                }


                //outputImage.Save("sift.jpg");
                result.Descriptor = siftDescriptors;
                result.Points     = siftPoints;
                return(result);
            }
            finally
            {
                siftAlgo.Dispose();
                modelKeyPointsSift.Dispose();
            }
        }
        public MatcherResult knnMatch(KeyPoints queryDescriptor, BFMatcher matcher, string leafCategory, int distanceCutoff = int.MaxValue, PreProcessedImage trainingData = null)
        {
            MatcherResult result = new MatcherResult();

            result.Category = leafCategory;

            using (VectorOfVectorOfDMatch vectorMatchesForSift = new VectorOfVectorOfDMatch())
            {
                matcher.KnnMatch(queryDescriptor.Descriptor, vectorMatchesForSift, 2, null);

                int numberOfMatches = 0;

                Dictionary <int, int> counts      = new Dictionary <int, int>();
                List <MDMatch>        goodMatches = new List <MDMatch>(vectorMatchesForSift.Size);
                for (int i = 0; i < vectorMatchesForSift.Size; i++)
                {
                    // Do Ratio test: Reject matches where ratio of closest match with second closest if greater than 0.8
                    if (
                        (vectorMatchesForSift[i].Size == 1 ||
                         vectorMatchesForSift[i][0].Distance < 0.75 * vectorMatchesForSift[i][1].Distance) &&
                        vectorMatchesForSift[i][0].Distance < distanceCutoff)
                    {
                        goodMatches.Add(vectorMatchesForSift[i][0]);
                        numberOfMatches++;
                    }
                }

                //goodMatches = clusterBasedOnPoseEstimation(goodMatches, queryDescriptor, trainingData);

                int maxResults = int.MaxValue;
                result.MatchingPoints = goodMatches.Count;
                if (!goodMatches.Any())
                {
                    result.MatchDistance        = float.MaxValue;
                    result.AverageDistance      = 0;
                    result.MatchDistanceWeight  = 0;
                    result.MatchingPointsWeight = 0;
                }
                else
                {
                    result.MatchDistance        = goodMatches.OrderBy(item => item.Distance).Take(maxResults).Sum(item => item.Distance);
                    result.AverageDistance      = result.MatchDistance / result.MatchingPoints;
                    result.MatchDistanceWeight  = 1 / Math.Pow(result.AverageDistance, 2);
                    result.MatchingPointsWeight = result.MatchingPoints * result.MatchingPoints;
                }
            }
            return(result);
        }
예제 #4
0
        private void trainModel(String plantCategoryName, List <String> eachLeafSpecies)
        {
            BFMatcher match;

            if (!categoryBfmatcherMapping.ContainsKey(plantCategoryName))
            {
                match = new  BFMatcher(DistanceType.L1);
                categoryBfmatcherMapping.Add(plantCategoryName, match);
            }
            else
            {
                //Find values associated with key
                match = categoryBfmatcherMapping[plantCategoryName];
            }
            foreach (String leaf in eachLeafSpecies)
            {
                PreProcess preProcessAlgorithm     = null;
                FeatureExtractAlgorithm featureSet = null;
                try
                {
                    //Console.WriteLine(leaf + "\n");
                    Image <Bgr, Byte> image = loadImage(leaf);
                    preProcessAlgorithm = new PreProcess(image);
                    //Image<Hsv, Byte> HSVImage = preProcessAlgorithm._ImageToHSV();
                    Image <Gray, Byte> grayScaleImage = preProcessAlgorithm._ImageToGrayScaleUsingConvert();

                    featureSet = new FeatureExtractAlgorithm(grayScaleImage);
                    KeyPoints leafDescriptor = featureSet.SIFTDescriptor();
                    match.Add(leafDescriptor.Descriptor);
                }
                finally
                {
                    if (preProcessAlgorithm != null)
                    {
                        preProcessAlgorithm.Dispose();
                    }

                    if (featureSet != null)
                    {
                        featureSet.Dispose();
                    }
                }
            }
        }
예제 #5
0
        public PreProcessedImage Execute(string imagePath, string category)
        {
            PreProcessedImage result = new PreProcessedImage();

            result.FilePath = imagePath;
            result.Category = category;
            using (PreProcess preProcessAlgorithm = new PreProcess(new Image <Bgr, Byte>(imagePath)))
                using (Image <Gray, Byte> grayScaleImage = preProcessAlgorithm._ImageToGrayScaleUsingConvert())
                {
                    using (FeatureExtractAlgorithm featureSet = new FeatureExtractAlgorithm(grayScaleImage))
                        using (Mat canny = new Mat())
                            using (VectorOfVectorOfPoint contours = new VectorOfVectorOfPoint())
                            {
                                KeyPoints descriptor = featureSet.SIFTDescriptor();
                                result.KeyPoints   = descriptor;
                                result.ContourArea = 0;
                                CvInvoke.Canny(grayScaleImage, canny, 100, 50);
                                int[,] hierarchy        = CvInvoke.FindContourTree(canny, contours, ChainApproxMethod.ChainApproxSimple);
                                result.NumberOfContours = contours.Size;
                                double maxArea  = double.MinValue;
                                int    maxIndex = -1;
                                for (int index = 0; index < contours.Size; index++)
                                {
                                    double area = CvInvoke.ContourArea(contours[index]);
                                    result.ContourArea += area;
                                    if (area > maxArea)
                                    {
                                        maxArea  = area;
                                        maxIndex = index;
                                    }
                                }

                                result.Contour = new VectorOfPoint();

                                CvInvoke.ApproxPolyDP(contours[maxIndex], result.Contour, CvInvoke.ArcLength(contours[maxIndex], true) * 0.02, true);
                                return(result);
                            }
                }
        }
예제 #6
0
        public void startComparingImages(Dictionary <String, BFMatcher> categoryBfmatcherMapping)
        {
            using (PreProcess preProcessAlgorithm = new PreProcess(queryImage))
            {
                using (Image <Gray, Byte> grayScaleImage = preProcessAlgorithm._ImageToGrayScaleUsingConvert())
                {
                    using (FeatureExtractAlgorithm featureSet = new FeatureExtractAlgorithm(grayScaleImage))
                    {
                        using (KeyPoints leafDescriptor = featureSet.SIFTDescriptor())
                        {
                            foreach (var pair in categoryBfmatcherMapping)
                            {
                                if (pair.Key == "abies_concolor")
                                {
                                    continue;
                                }

                                try
                                {
                                    DescriptorMatcher learningAlgo = new DescriptorMatcher();
                                    BFMatcher         bfmatch      = pair.Value;
                                    string            leafCategory = pair.Key;
                                    MatcherResult     result       = learningAlgo.knnMatch(leafDescriptor, bfmatch, leafCategory);
                                    finalResultSet.Add(result);
                                }
                                catch (Exception exception)
                                {
                                    //TODO
                                    //Console.WriteLine(exception.ToString());
                                }
                            }
                            finalResultSet = finalResultSet.OrderByDescending(item => item, new MatcherResultComparer()).Take(3).ToList();
                        }
                    }
                }
            }
        }
        private List <MDMatch> clusterBasedOnPoseEstimation(List <MDMatch> matches, KeyPoints queryKeyPoints, PreProcessedImage trainingData)
        {
            // If no training data is provided then we cannot compute pose (LeafAnalysisV1), hence just return back the original set
            if (trainingData == null ||
                matches == null ||
                !matches.Any())
            {
                return(matches);
            }

            Dictionary <MDMatch, List <MDMatch> > clusters = new Dictionary <MDMatch, List <MDMatch> >(matches.Count);
            List <PoseEstimate> poseEstimates = new List <PoseEstimate>(matches.Count);

            foreach (MDMatch match in matches)
            {
                MKeyPoint queryKeyPoint    = queryKeyPoints.Points[match.QueryIdx];
                MKeyPoint trainingKeyPoint = trainingData.KeyPoints.Points[match.TrainIdx];

                PoseEstimate estimate = new PoseEstimate();
                estimate.Match = match;
                estimate.Dx    = trainingKeyPoint.Point.X - queryKeyPoint.Point.X;
                estimate.Dy    = trainingKeyPoint.Point.Y - queryKeyPoint.Point.Y;
                estimate.Ds    = trainingKeyPoint.Octave / queryKeyPoint.Octave;
                estimate.Do    = trainingKeyPoint.Angle - queryKeyPoint.Angle;

                poseEstimates.Add(estimate);
                // Initialize clusters for each individual match
                // Next we will add other matches which belong to this cluster
                clusters.Add(match, new List <MDMatch>(new MDMatch[] { match }));
            }

            const double errorThreshold = 5;

            // Compute cluster membership
            foreach (PoseEstimate estimate in poseEstimates)
            {
                foreach (PoseEstimate otherEstimate in poseEstimates)
                {
                    // Ignore self
                    if (estimate == otherEstimate)
                    {
                        continue;
                    }

                    double error = estimate.RMSE(otherEstimate);
                    //Console.WriteLine("Error: " + trainingData.Category + ": " + error);
                    if (error < errorThreshold)
                    {
                        clusters[estimate.Match].Add(otherEstimate.Match);
                    }
                }
            }

            // Finally pick the largest cluster
            List <MDMatch> result        = null;
            int            sizeOfCluster = -1;;

            foreach (KeyValuePair <MDMatch, List <MDMatch> > cluster in clusters)
            {
                if (cluster.Value.Count == sizeOfCluster)
                {
                    // Tie breaker: choose the cluster with smaller overall distances
                    if (result.Sum(item => item.Distance) > cluster.Value.Sum(item => item.Distance))
                    {
                        result = cluster.Value;
                    }
                }
                else if (cluster.Value.Count > sizeOfCluster)
                {
                    sizeOfCluster = cluster.Value.Count;
                    result        = cluster.Value;
                }
            }

            return(result);
        }