コード例 #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
        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);
        }