public static void FindMatches(Mat modelImage, Mat observedImage, out VectorOfKeyPoint modelKeyPoints, out VectorOfKeyPoint observedKeyPoints, VectorOfVectorOfDMatch matches, out Mat mask, out Mat homography, MatchingTechnique matchingTechnique, float keyPointFilter = 1, double detectorParameter = -1) { int k = 2; double uniquenessThreshold = 0.8; homography = null; modelKeyPoints = new VectorOfKeyPoint(); observedKeyPoints = new VectorOfKeyPoint(); Feature2D detector; Feature2D descriptor; DistanceType distanceType; if (matchingTechnique == MatchingTechnique.FAST) { if (detectorParameter <= 0) { detectorParameter = 20; } detector = new FastDetector((int)detectorParameter); descriptor = new BriefDescriptorExtractor(); distanceType = DistanceType.Hamming; } else if (matchingTechnique == MatchingTechnique.ORB) { if (detectorParameter <= 0) { detectorParameter = 100000; } detector = new ORBDetector((int)detectorParameter); descriptor = detector; distanceType = DistanceType.Hamming; } else if (matchingTechnique == MatchingTechnique.SURF) { if (detectorParameter <= 0) { detectorParameter = 300; } detector = new SURF(detectorParameter); descriptor = detector; distanceType = DistanceType.L2; } else { throw new NotImplementedException($"{matchingTechnique} not supported."); } // Extract features from model image. UMat modelDescriptors = new UMat(); detector.DetectRaw(modelImage, modelKeyPoints, null); Console.WriteLine($"modelKeyPoints: {modelKeyPoints.Size}"); if (keyPointFilter < 2) { modelKeyPoints = GetBestKeypointsPercent(modelKeyPoints, keyPointFilter); } else { modelKeyPoints = GetBestKeypointsCount(modelKeyPoints, (int)keyPointFilter); } descriptor.Compute(modelImage, modelKeyPoints, modelDescriptors); // Extract features from observed image. UMat observedDescriptors = new UMat(); detector.DetectRaw(observedImage, observedKeyPoints, null); Console.WriteLine($"observedKeyPoints: {observedKeyPoints.Size}"); if (keyPointFilter < 2) { observedKeyPoints = GetBestKeypointsPercent(observedKeyPoints, keyPointFilter); } else { observedKeyPoints = GetBestKeypointsCount(observedKeyPoints, (int)keyPointFilter); } descriptor.Compute(observedImage, observedKeyPoints, observedDescriptors); // Match keypoints. BFMatcher matcher = new BFMatcher(distanceType); matcher.Add(modelDescriptors); matcher.KnnMatch(observedDescriptors, matches, k, null); mask = new Mat(matches.Size, 1, DepthType.Cv8U, 1); mask.SetTo(new MCvScalar(255)); Features2DToolbox.VoteForUniqueness(matches, uniquenessThreshold, mask); int nonZeroCount = CvInvoke.CountNonZero(mask); if (nonZeroCount >= 4) { nonZeroCount = Features2DToolbox.VoteForSizeAndOrientation(modelKeyPoints, observedKeyPoints, matches, mask, 1.5, 20); if (nonZeroCount >= 4) { homography = Features2DToolbox.GetHomographyMatrixFromMatchedFeatures(modelKeyPoints, observedKeyPoints, matches, mask, 2); } } }
/// <summary> /// Draw the model image and observed image, the matched features and homography projection. /// </summary> /// <param name="modelImage">The model image</param> /// <param name="observedImage">The observed image</param> /// <returns>The model image and observed image, the matched features and homography projection.</returns> public Bitmap GetImageWithDrawnMatches(Bitmap modelImage, Bitmap observedImage, MatchingTechnique matchingTechnique) { VectorOfKeyPoint modelKeyPoints; VectorOfKeyPoint observedKeyPoints; using (Image <Bgr, byte> modelImg = new Image <Bgr, byte>(modelImage)) using (Image <Bgr, byte> observedImg = new Image <Bgr, byte>(observedImage)) using (Emgu.CV.Mat modelMat = modelImg.Mat) using (Emgu.CV.Mat observedMat = observedImg.Mat) using (VectorOfVectorOfDMatch matches = new VectorOfVectorOfDMatch()) { ImageFeatureDetector.FindMatches(modelMat, observedMat, out modelKeyPoints, out observedKeyPoints, matches, out Mat mask, out Mat homography, matchingTechnique); try { using (Mat result = new Mat()) { Features2DToolbox.DrawMatches(modelMat, modelKeyPoints, observedMat, observedKeyPoints, matches, result, new MCvScalar(255, 0, 0), new MCvScalar(0, 0, 255), mask); return(result.ToBitmap()); } } catch (Exception) { throw; } finally { mask?.Dispose(); homography?.Dispose(); } } }