/// <summary> /// 进行特征点匹配 /// </summary> /// <param name="sourceImage">对应的查询(原始)图像</param> /// <param name="searchImage">对应的训练(模板)图像(宽高不得超过被查询图像)</param> /// <param name="featureMatchType">特征点匹配算法</param> /// <param name="argument">匹配参数(可选)</param> /// <returns></returns> public static FeatureMatchResult FeatureMatch(Mat sourceImage, Mat searchImage, FeatureMatchType featureMatchType = FeatureMatchType.Sift, FeatureMatchArgument argument = null) { if (searchImage.Empty()) { throw new ArgumentOutOfRangeException(nameof(searchImage), "不允许使用空的查询(原始)图像进行识别"); } if (sourceImage.Empty()) { throw new ArgumentOutOfRangeException(nameof(searchImage), "不允许使用空的查询(原始)图像进行识别"); } if (sourceImage.Type() == searchImage.Type()) { return(argument == null ? Match.FeatureMatch.Match(sourceImage, searchImage, featureMatchType) : Match.FeatureMatch.Match(sourceImage, searchImage, featureMatchType, argument)); } using var sourceMat = new Mat(sourceImage.Rows, sourceImage.Cols, MatType.CV_8UC1); using var searchMat = new Mat(searchImage.Rows, searchImage.Cols, MatType.CV_8UC1); Cv2.CvtColor(sourceImage, sourceMat, ColorConversionCodes.BGR2GRAY); Cv2.CvtColor(searchImage, searchMat, ColorConversionCodes.BGR2GRAY); return(argument == null ? Match.FeatureMatch.Match(sourceMat, sourceMat, featureMatchType) : Match.FeatureMatch.Match(sourceMat, sourceMat, featureMatchType, argument)); }
public void CreateFeatureProviderTest(FeatureMatchType featureType) { var provider = FeatureMatchFactory.CreateFeatureProvider(featureType); Assert.IsNotNull(provider); Assert.AreEqual(featureType, provider.MatchFeatureType); }
public void FeatureMatchTest(double ratio, int threshold, FeatureMatchType type) { var imageFolder = Path.GetFullPath(@".\_TestResources\CvMatchTest"); var sourceImage = Path.Combine(imageFolder, "source.png"); var testImage1 = Path.Combine(imageFolder, "test1.png"); //Îļþ²âÊÔ var matchResult = CvMatch.FeatureMatch(sourceImage, testImage1, type, new FeatureMatchArgument() { Ratio = ratio, RansacThreshold = (uint)threshold, ExtensionConfig = new Dictionary <string, object>() { { MatchArgument.ConsoleOutput, true }, { MatchArgument.PreviewMatchResult, true } } }); Assert.IsTrue(matchResult.Success && matchResult.MatchItems.Any()); //Bitmap²âÊÔ using var sourceBitmap = new Bitmap(sourceImage); using var testBitmap1 = new Bitmap(testImage1); matchResult = CvMatch.FeatureMatch(sourceImage, testImage1, type, new FeatureMatchArgument() { Ratio = ratio, RansacThreshold = (uint)threshold, ExtensionConfig = new Dictionary <string, object>() { { MatchArgument.ConsoleOutput, true }, { MatchArgument.PreviewMatchResult, true } } }); Assert.IsTrue(matchResult.Success && matchResult.MatchItems.Any()); }
/// <summary> /// 进行特征点匹配 /// </summary> /// <param name="sourceMat">对应的查询(原始)图像</param> /// <param name="searchMat">对应的训练(模板)图像</param> /// <param name="featureMatchType">特征点匹配算法</param> /// <returns></returns> internal static FeatureMatchResult Match(Mat sourceMat, Mat searchMat, FeatureMatchType featureMatchType) { var featureProvider = FeatureMatchFactory.CreateFeatureProvider(featureMatchType); if (featureProvider == null) { return(new FeatureMatchResult() { Success = false }); } return(featureProvider.Match(sourceMat, searchMat)); }
/// <summary> /// 根据<see cref="FeatureMatchType"/>创建<see cref="IFeatureProvider"/>的实例 /// </summary> /// <param name="featureType"></param> /// <returns></returns> public static IFeatureProvider CreateFeatureProvider(FeatureMatchType featureType) { //通过反射获取所有的 IFeatureProvider var types = Assembly.GetExecutingAssembly().GetTypes() .Where(x => x.GetInterfaces().Contains(typeof(IFeatureProvider)) && !x.IsAbstract && x.IsClass).ToList(); if (!types.Any()) { return(null); } var type = types.FirstOrDefault(x => GetMatchFeatureTypeFromAttribute(x) == featureType); if (type == null) { return(null); } return(Activator.CreateInstance(type) as IFeatureProvider); }
public AlgorithmResult DetectFeatureMatch( string modelName, string observedeName, FeatureDetectType detectType, FeatureMatchType matchType, int k, double uniquenessThreshold) { AlgorithmResult result = new AlgorithmResult(); Image <Bgr, byte> modelImage = ImageHelper.GetImage(modelName); Image <Bgr, byte> observedImage = ImageHelper.GetImage(observedeName); Mat resultImage = new Mat(); // Get features from modelImage var modelKeyPoints = new VectorOfKeyPoint(); var modelDescriptors = new UMat(); GetDetector(detectType).DetectAndCompute( modelImage.Convert <Gray, byte>(), null, modelKeyPoints, modelDescriptors, false); // Get features from observedImage var observedKeyPoints = new VectorOfKeyPoint(); var observedDescriptors = new UMat(); GetDetector(detectType).DetectAndCompute( observedImage.Convert <Gray, byte>(), null, observedKeyPoints, observedDescriptors, false); // Perform match with selected matcher var matches = new VectorOfVectorOfDMatch(); if (matchType == FeatureMatchType.Flann) { // TODO: Add parameters for GetIndexParams var flannMatcher = new FlannBasedMatcher(new AutotunedIndexParams(), new SearchParams()); flannMatcher.Add(modelDescriptors); flannMatcher.KnnMatch( observedDescriptors, matches, k, null); } else { // TODO: Add parameters for DistanceType var bfMatcher = new BFMatcher(DistanceType.L2); bfMatcher.Add(modelDescriptors); bfMatcher.KnnMatch( observedDescriptors, matches, k, null); } // Find homography Mat homography = null; var mask = new Mat(matches.Size, 1, DepthType.Cv8U, 1); mask.SetTo(new MCvScalar(255)); VoteForUniqueness(matches, uniquenessThreshold, mask); // If 4 or more patches continue int nonZeroCount = CvInvoke.CountNonZero(mask); if (nonZeroCount >= 4) { // Filter for majority scale and rotation nonZeroCount = VoteForSizeAndOrientation( modelKeyPoints, observedKeyPoints, matches, mask, 1.5, 20); // If 4 or more patches continue if (nonZeroCount >= 4) { homography = GetHomographyMatrixFromMatchedFeatures(modelKeyPoints, observedKeyPoints, matches, mask, 2); } } // Draw the matched keypoints DrawMatches( modelImage, modelKeyPoints, observedImage, observedKeyPoints, matches, resultImage, new MCvScalar(255, 255, 255), new MCvScalar(255, 255, 255), mask); // Draw the projected region on the image if (homography != null) { // Draw a rectangle along the projected model Rectangle rect = new Rectangle(Point.Empty, modelImage.Size); PointF[] pts = new PointF[] { new PointF(rect.Left, rect.Bottom), new PointF(rect.Right, rect.Bottom), new PointF(rect.Right, rect.Top), new PointF(rect.Left, rect.Top) }; // Transform the perspective of the points array based on the homography // And get a rotated rectangle for the homography pts = CvInvoke.PerspectiveTransform(pts, homography); Point[] points = Array.ConvertAll(pts, Point.Round); using (VectorOfPoint vp = new VectorOfPoint(points)) { CvInvoke.Polylines(resultImage, vp, true, new MCvScalar(255, 0, 0, 255), 5); } } result.ImageArray = ImageHelper.SetImage(resultImage.ToImage <Bgr, byte>()); return(result); }
/// <summary> /// 进行特征点匹配 /// </summary> /// <param name="sourceImage">对应的查询(原始)图像</param> /// <param name="searchImage">对应的训练(模板)图像(宽高不得超过被查询图像)</param> /// <param name="featureMatchType">特征点匹配算法</param> /// <param name="argument">匹配参数(可选)</param> /// <returns></returns> public static FeatureMatchResult FeatureMatch(Bitmap sourceImage, Bitmap searchImage, FeatureMatchType featureMatchType = FeatureMatchType.Sift, FeatureMatchArgument argument = null) { if (sourceImage == null) { throw new ArgumentNullException(nameof(sourceImage)); } if (searchImage == null) { throw new ArgumentNullException(nameof(searchImage)); } using var sourceMat = OpenCvSharp.Extensions.BitmapConverter.ToMat(sourceImage); using var searchMat = OpenCvSharp.Extensions.BitmapConverter.ToMat(searchImage); if (sourceMat.Width < searchMat.Width || sourceMat.Height < searchMat.Height) { throw new ArgumentException("对应的训练(模板)图像sourceImage,宽高不得超过searchImage。"); } return(FeatureMatch(sourceMat, searchMat, featureMatchType, argument)); }
/// <summary> /// 进行特征点匹配 /// </summary> /// <param name="sourceImage">对应的查询(原始)图像</param> /// <param name="searchImage">对应的训练(模板)图像(宽高不得超过被查询图像)</param> /// <param name="featureMatchType">特征点匹配算法</param> /// <param name="argument">匹配参数(可选)</param> /// <returns></returns> public static FeatureMatchResult FeatureMatch(string sourceImage, string searchImage, FeatureMatchType featureMatchType = FeatureMatchType.Sift, FeatureMatchArgument argument = null) { if (!File.Exists(sourceImage)) { throw new FileNotFoundException(sourceImage); } if (!File.Exists(searchImage)) { throw new FileNotFoundException(searchImage); } using var sourceMat = new Mat(sourceImage); using var searchMat = new Mat(searchImage); if (sourceMat.Width < searchMat.Width || sourceMat.Height < searchMat.Height) { throw new ArgumentException("对应的训练(模板)图像sourceImage,宽高不得超过searchImage。"); } return(FeatureMatch(sourceMat, searchMat, featureMatchType, argument)); }
public FeatureProviderTypeAttribute(FeatureMatchType type) { FeatureMatchType = type; }