示例#1
0
        /// <summary>
        ///     获取优秀的匹配点
        /// <para>
        ///     使用 "比较最近邻距离与次近邻距离的SIFT匹配方式" 和 "随机抽样一致(RANSAC)算法" 来进一步获取优秀匹配点
        /// </para>
        /// </summary>
        /// <param name="matches"></param>
        /// <param name="argument"></param>
        /// <param name="sourceKeyPoints"></param>
        /// <param name="searchKeyPoints"></param>
        /// <returns></returns>
        private IList <DMatch> SelectGoodMatches(IEnumerable <DMatch[]> matches, FeatureMatchArgument argument,
                                                 IList <KeyPoint> sourceKeyPoints, IList <KeyPoint> searchKeyPoints)
        {
            var sourcePoints = new List <Point2d>();
            var searchPoints = new List <Point2d>();
            var goodMatches  = new List <DMatch>();

            //比较最近邻距离与次近邻距离的SIFT匹配方式
            foreach (var items in matches)
            {
                if (items.Length == 0)
                {
                    continue;
                }

                if (argument.MatchPoints > 1 &&
                    (items.Length < 2 || items[0].Distance > argument.Ratio * items[1].Distance))
                {
                    continue;
                }

                //此处直接选择欧氏距离小的匹配关键点
                var goodMatch = items[0];
                goodMatches.Add(goodMatch);
                sourcePoints.Add(Point2FToPoint2D(sourceKeyPoints[goodMatch.QueryIdx].Pt));
                searchPoints.Add(Point2FToPoint2D(searchKeyPoints[goodMatch.TrainIdx].Pt));
            }
            argument.OutputDebugMessage($"[FeatureMatch] [SIFT] The number of good matching points is ({goodMatches.Count}).");

            //随机抽样一致(RANSAC)算法 (如果原始的匹配结果为空, 则跳过过滤步骤)
            if (sourcePoints.Count >= MinCorrespondingPointCount && searchPoints.Count >= MinCorrespondingPointCount)
            {
                var inliersMask = new Mat();
                Cv2.FindHomography(sourcePoints, searchPoints, HomographyMethods.Ransac, argument.RansacThreshold, inliersMask);
                // 如果通过RANSAC处理后的匹配点大于10个,才应用过滤. 否则使用原始的匹配点结果(匹配点过少的时候通过RANSAC处理后,可能会得到0个匹配点的结果).
                if (inliersMask.Rows > 10)
                {
                    inliersMask.GetArray(out byte[] maskBytes);
                    var inliers = new List <DMatch>();

                    for (var i = 0; i < maskBytes.Length; i++)
                    {
                        if (maskBytes[i] != 0)
                        {
                            inliers.Add(goodMatches[i]);
                        }
                    }

                    argument.OutputDebugMessage($"[FeatureMatch] [SIFT] The number of good matching RANSAC points is ({inliers.Count}).");
                    return(inliers);
                }
            }
            return(goodMatches);
        }
示例#2
0
        /// <summary>
        ///     进行特征点匹配
        /// </summary>
        /// <param name="sourceMat">对应的查询(原始)图像</param>
        /// <param name="searchMat">对应的训练(模板)图像</param>
        /// <param name="featureMatchType">特征点匹配算法</param>
        /// <param name="argument">匹配参数</param>
        /// <returns></returns>
        internal static FeatureMatchResult Match(Mat sourceMat, Mat searchMat, FeatureMatchType featureMatchType,
                                                 FeatureMatchArgument argument)
        {
            var featureProvider = FeatureMatchFactory.CreateFeatureProvider(featureMatchType);

            if (featureProvider == null)
            {
                return(new FeatureMatchResult()
                {
                    Success = false
                });
            }

            return(featureProvider.Match(sourceMat, searchMat, argument));
        }
示例#3
0
        public override FeatureMatchResult Match(Mat sourceMat, Mat searchMat, FeatureMatchArgument argument)
        {
            //创建SIFT
            using var sift = SIFT.Create();

            //创建特征点描述对象,为下边的特征点匹配做准备
            using var sourceDescriptors = new Mat();
            using var searchDescriptors = new Mat();

            //提取特征点,并进行特征点描述
            sift.DetectAndCompute(sourceMat, null, out var sourceKeyPoints, sourceDescriptors);
            sift.DetectAndCompute(searchMat, null, out var searchKeyPoints, searchDescriptors);

            //创建Brute-force descriptor matcher
            using var bfMatcher = new BFMatcher();
            //对原图特征点描述加入训练
            bfMatcher.Add(new List <Mat>()
            {
                sourceDescriptors
            });
            bfMatcher.Train();
            //获得匹配特征点,并提取最优配对
            var matches = bfMatcher.KnnMatch(sourceDescriptors, searchDescriptors, (int)argument.MatchPoints);

            argument.OutputDebugMessage($"[FeatureMatch] [SIFT] The number of matching points is ({matches.Length}).");

            //即使使用SIFT算法,但此时没有经过点筛选的匹配效果同样糟糕,所进一步获取优秀匹配点
            var goodMatches = SelectGoodMatches(matches, argument, sourceKeyPoints, searchKeyPoints);

            //获取匹配结果
            var matchResult = GetMatchResult(goodMatches, sourceKeyPoints, searchKeyPoints);

            argument.OutputDebugMessage($"[FeatureMatch] [SIFT] The result of the match is ({matchResult.Success}) ({matchResult.MatchItems.Count}).");
            if (matchResult.Success)
            {
                var bestMatch = matchResult.MatchItems[0];
                argument.OutputDebugMessage($"[FeatureMatch] [SIFT] The center point of the best match is ({bestMatch.Point}), and the rect is {bestMatch.Rectangle}.");
            }
            argument.PreviewDebugFeatureMatchResult(matchResult, sourceMat, searchMat, sourceKeyPoints, searchKeyPoints, goodMatches);
            return(matchResult);
        }
示例#4
0
        /// <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));
        }
示例#5
0
        /// <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));
        }
示例#6
0
        /// <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));
        }
示例#7
0
 /// <summary>
 ///     进行特征点匹配
 /// </summary>
 /// <param name="sourceMat">对应的查询(原始)图像</param>
 /// <param name="searchMat">对应的训练(模板)图像</param>
 /// <param name="argument">匹配参数</param>
 /// <returns></returns>
 public abstract FeatureMatchResult Match(Mat sourceMat, Mat searchMat, FeatureMatchArgument argument);