public void FindMatch(Image <Gray, byte> modelImage, Image <Gray, byte> observedImage, double hessianThresh, int k, double uniquenessThreshold, VectorOfVectorOfDMatch matches, out VectorOfKeyPoint modelKeyPoints, out VectorOfKeyPoint observedKeyPoints, out Mat mask, out Mat homography) { homography = null; modelKeyPoints = new VectorOfKeyPoint(); observedKeyPoints = new VectorOfKeyPoint(); CudaSURFDetector surfCuda = new CudaSURFDetector((float)hessianThresh); using (GpuMat gpuModelImage = new GpuMat(modelImage)) //extract features from the object image using (GpuMat gpuModelKeyPoints = surfCuda.DetectKeyPointsRaw(gpuModelImage, null)) using ( GpuMat gpuModelDescriptors = surfCuda.ComputeDescriptorsRaw(gpuModelImage, null, gpuModelKeyPoints)) using (CudaBFMatcher matcher = new CudaBFMatcher(DistanceType.L2)) { surfCuda.DownloadKeypoints(gpuModelKeyPoints, modelKeyPoints); // extract features from the observed image using (GpuMat gpuObservedImage = new GpuMat(observedImage)) using (GpuMat gpuObservedKeyPoints = surfCuda.DetectKeyPointsRaw(gpuObservedImage, null)) using ( GpuMat gpuObservedDescriptors = surfCuda.ComputeDescriptorsRaw(gpuObservedImage, null, gpuObservedKeyPoints)) { matcher.KnnMatch(gpuObservedDescriptors, gpuModelDescriptors, matches, k); surfCuda.DownloadKeypoints(gpuObservedKeyPoints, observedKeyPoints); 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); } } } } }
public void TestBruteForceHammingDistance() { if (CudaInvoke.HasCuda) { Image <Gray, byte> box = new Image <Gray, byte>("box.png"); FastDetector fast = new FastDetector(100, true); BriefDescriptorExtractor brief = new BriefDescriptorExtractor(32); #region extract features from the object image Stopwatch stopwatch = Stopwatch.StartNew(); VectorOfKeyPoint modelKeypoints = new VectorOfKeyPoint(); fast.DetectRaw(box, modelKeypoints); Mat modelDescriptors = new Mat(); brief.Compute(box, modelKeypoints, modelDescriptors); stopwatch.Stop(); Trace.WriteLine(String.Format("Time to extract feature from model: {0} milli-sec", stopwatch.ElapsedMilliseconds)); #endregion Image <Gray, Byte> observedImage = new Image <Gray, byte>("box_in_scene.png"); #region extract features from the observed image stopwatch.Reset(); stopwatch.Start(); VectorOfKeyPoint observedKeypoints = new VectorOfKeyPoint(); fast.DetectRaw(observedImage, observedKeypoints); Mat observedDescriptors = new Mat(); brief.Compute(observedImage, observedKeypoints, observedDescriptors); stopwatch.Stop(); Trace.WriteLine(String.Format("Time to extract feature from image: {0} milli-sec", stopwatch.ElapsedMilliseconds)); #endregion Mat homography = null; using (GpuMat <Byte> gpuModelDescriptors = new GpuMat <byte>(modelDescriptors)) //initialization of GPU code might took longer time. { stopwatch.Reset(); stopwatch.Start(); CudaBFMatcher hammingMatcher = new CudaBFMatcher(DistanceType.Hamming); //BFMatcher hammingMatcher = new BFMatcher(BFMatcher.DistanceType.Hamming, modelDescriptors); int k = 2; Matrix <int> trainIdx = new Matrix <int>(observedKeypoints.Size, k); Matrix <float> distance = new Matrix <float>(trainIdx.Size); using (GpuMat <Byte> gpuObservedDescriptors = new GpuMat <byte>(observedDescriptors)) //using (GpuMat<int> gpuTrainIdx = new GpuMat<int>(trainIdx.Rows, trainIdx.Cols, 1, true)) //using (GpuMat<float> gpuDistance = new GpuMat<float>(distance.Rows, distance.Cols, 1, true)) using (VectorOfVectorOfDMatch matches = new VectorOfVectorOfDMatch()) { Stopwatch w2 = Stopwatch.StartNew(); //hammingMatcher.KnnMatch(gpuObservedDescriptors, gpuModelDescriptors, matches, k); hammingMatcher.KnnMatch(gpuObservedDescriptors, gpuModelDescriptors, matches, k, null, true); w2.Stop(); Trace.WriteLine(String.Format("Time for feature matching (excluding data transfer): {0} milli-sec", w2.ElapsedMilliseconds)); //gpuTrainIdx.Download(trainIdx); //gpuDistance.Download(distance); Mat mask = new Mat(distance.Rows, 1, DepthType.Cv8U, 1); mask.SetTo(new MCvScalar(255)); Features2DToolbox.VoteForUniqueness(matches, 0.8, 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); } nonZeroCount = CvInvoke.CountNonZero(mask); } stopwatch.Stop(); Trace.WriteLine(String.Format("Time for feature matching (including data transfer): {0} milli-sec", stopwatch.ElapsedMilliseconds)); } } if (homography != null) { Rectangle rect = box.ROI; 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) }; PointF[] points = CvInvoke.PerspectiveTransform(pts, homography); //homography.ProjectPoints(points); //Merge the object image and the observed image into one big image for display Image <Gray, Byte> res = box.ConcateVertical(observedImage); for (int i = 0; i < points.Length; i++) { points[i].Y += box.Height; } res.DrawPolyline(Array.ConvertAll <PointF, Point>(points, Point.Round), true, new Gray(255.0), 5); //ImageViewer.Show(res); } } }
public static void FindMatch(Mat modelImage, Mat observedImage, out long matchTime, out VectorOfKeyPoint modelKeyPoints, out VectorOfKeyPoint observedKeyPoints, VectorOfVectorOfDMatch matches, out Mat mask, out Mat homography) { int k = 2; double uniquenessThreshold = 0.8; double hessianThresh = 300; Stopwatch watch; homography = null; modelKeyPoints = new VectorOfKeyPoint(); observedKeyPoints = new VectorOfKeyPoint(); if (CudaInvoke.HasCuda) { CudaSURF surfCuda = new CudaSURF((float)hessianThresh); using (GpuMat gpuModelImage = new GpuMat(modelImage)) //extract features from the object image using (GpuMat gpuModelKeyPoints = surfCuda.DetectKeyPointsRaw(gpuModelImage, null)) using (GpuMat gpuModelDescriptors = surfCuda.ComputeDescriptorsRaw(gpuModelImage, null, gpuModelKeyPoints)) using (CudaBFMatcher matcher = new CudaBFMatcher(DistanceType.L2)) { surfCuda.DownloadKeypoints(gpuModelKeyPoints, modelKeyPoints); watch = Stopwatch.StartNew(); // extract features from the observed image using (GpuMat gpuObservedImage = new GpuMat(observedImage)) using (GpuMat gpuObservedKeyPoints = surfCuda.DetectKeyPointsRaw(gpuObservedImage, null)) using (GpuMat gpuObservedDescriptors = surfCuda.ComputeDescriptorsRaw(gpuObservedImage, null, gpuObservedKeyPoints)) //using (GpuMat tmp = new GpuMat()) //using (Stream stream = new Stream()) { matcher.KnnMatch(gpuObservedDescriptors, gpuModelDescriptors, matches, k); surfCuda.DownloadKeypoints(gpuObservedKeyPoints, observedKeyPoints); 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); } } } watch.Stop(); } } else { using (UMat uModelImage = modelImage.GetUMat(AccessType.Read)) using (UMat uObservedImage = observedImage.GetUMat(AccessType.Read)) { SURF surfCPU = new SURF(hessianThresh); //extract features from the object image UMat modelDescriptors = new UMat(); surfCPU.DetectAndCompute(uModelImage, null, modelKeyPoints, modelDescriptors, false); watch = Stopwatch.StartNew(); // extract features from the observed image UMat observedDescriptors = new UMat(); surfCPU.DetectAndCompute(uObservedImage, null, observedKeyPoints, observedDescriptors, false); BFMatcher matcher = new BFMatcher(DistanceType.L2); 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); watch.Stop(); } } matchTime = watch.ElapsedMilliseconds; }
/// <summary> /// Finds matching points in the faces using SURF /// </summary> /// <param name="modelImage"> /// The model image. /// </param> /// <param name="observedImage"> /// The observed image. /// </param> /// <param name="matchTime"> /// The match time. /// </param> /// <param name="modelKeyPoints"> /// The model key points. /// </param> /// <param name="observedKeyPoints"> /// The observed key points. /// </param> /// <param name="matches"> /// The matches. /// </param> /// <param name="mask"> /// The mask. /// </param> /// <param name="homography"> /// The homography. /// </param> /// <param name="score"> /// The score. /// </param> private void FindMatch( Mat modelImage, Mat observedImage, out long matchTime, out VectorOfKeyPoint modelKeyPoints, out VectorOfKeyPoint observedKeyPoints, VectorOfVectorOfDMatch matches, out Mat mask, out Mat homography, out long score) { int k = 2; double uniquenessThreshold = 5; Stopwatch watch; homography = null; mask = null; score = 0; modelKeyPoints = new VectorOfKeyPoint(); observedKeyPoints = new VectorOfKeyPoint(); if (Controller.Instance.Cuda) { CudaSURF surfGPU = new CudaSURF(700f, 4, 2, false); using (CudaImage <Gray, byte> gpuModelImage = new CudaImage <Gray, byte>(modelImage)) //extract features from the object image using (GpuMat gpuModelKeyPoints = surfGPU.DetectKeyPointsRaw(gpuModelImage, null)) using (GpuMat gpuModelDescriptors = surfGPU.ComputeDescriptorsRaw(gpuModelImage, null, gpuModelKeyPoints)) using (CudaBFMatcher matcher = new CudaBFMatcher(DistanceType.L2)) { surfGPU.DownloadKeypoints(gpuModelKeyPoints, modelKeyPoints); watch = Stopwatch.StartNew(); // extract features from the observed image using (CudaImage <Gray, Byte> gpuObservedImage = new CudaImage <Gray, byte>(observedImage)) using (GpuMat gpuObservedKeyPoints = surfGPU.DetectKeyPointsRaw(gpuObservedImage, null)) using (GpuMat gpuObservedDescriptors = surfGPU.ComputeDescriptorsRaw( gpuObservedImage, null, gpuObservedKeyPoints)) using (GpuMat <int> gpuMatchIndices = new GpuMat <int>( gpuObservedDescriptors.Size.Height, k, 1, true)) using (GpuMat <float> gpuMatchDist = new GpuMat <float>( gpuObservedDescriptors.Size.Height, k, 1, true)) //using (GpuMat<Byte> gpuMask = new GpuMat<byte>(gpuMatchIndices.Size.Height, 1, 1)) using (Emgu.CV.Cuda.Stream stream = new Emgu.CV.Cuda.Stream()) { matcher.KnnMatch(gpuObservedDescriptors, gpuModelDescriptors, matches, k, null); //indices = new Matrix<int>(gpuMatchIndices.Size); //mask = new Matrix<byte>(gpuMask.Size); mask = new Mat(matches.Size, 1, DepthType.Cv8U, 1); mask.SetTo(new MCvScalar(255)); surfGPU.DownloadKeypoints(gpuObservedKeyPoints, observedKeyPoints); /*//gpu implementation of voteForUniquess * using (GpuMat col0 = gpuMatchDist.Col(0)) * using (GpuMat col1 = gpuMatchDist.Col(1)) * { * CudaInvoke.Multiply(col1, new GpuMat(), col1, 1, DepthType.Default, stream); * CudaInvoke.Compare(col0, col1, mask, CmpType.LessEqual, stream); * }*/ Features2DToolbox.VoteForUniqueness(matches, uniquenessThreshold, mask); //wait for the stream to complete its tasks //We can perform some other CPU intesive stuffs here while we are waiting for the stream to complete. stream.WaitForCompletion(); //gpuMatchIndices.Download(indices); if (CudaInvoke.CountNonZero(mask) >= 4) { int nonZeroCount = Features2DToolbox.VoteForSizeAndOrientation( modelKeyPoints, observedKeyPoints, matches, mask, 1.5, 20); if (nonZeroCount >= 4) { homography = Features2DToolbox.GetHomographyMatrixFromMatchedFeatures( modelKeyPoints, observedKeyPoints, matches, mask, 2); } } watch.Stop(); } for (int i = 0; i < matches.Size; i++) { score++; } } } //else //{ // SURF surfCPU = new SURF(500, 4, 2, false); // //extract features from the object image // modelKeyPoints = new VectorOfKeyPoint(); // Matrix<float> modelDescriptors = surfCPU.DetectAndCompute(modelImage, null, modelKeyPoints); // watch = Stopwatch.StartNew(); // // extract features from the observed image // observedKeyPoints = new VectorOfKeyPoint(); // Matrix<float> observedDescriptors = surfCPU.DetectAndCompute(observedImage, null, observedKeyPoints); // BFMatcher matcher = new BFMatcher<float>(DistanceType.L2); // matcher.Add(modelDescriptors); // indices = new Matrix<int>(observedDescriptors.Rows, k); // using (Matrix<float> dist = new Matrix<float>(observedDescriptors.Rows, k)) // { // matcher.KnnMatch(observedDescriptors, indices, dist, k, null); // mask = new Matrix<byte>(dist.Rows, 1); // mask.SetValue(255); // Features2DToolbox.VoteForUniqueness(dist, uniquenessThreshold, mask); // } // int nonZeroCount = CvInvoke.cvCountNonZero(mask); // if (nonZeroCount >= 4) // { // nonZeroCount = Features2DToolbox.VoteForSizeAndOrientation(modelKeyPoints, observedKeyPoints, indices, mask, 1.5, 20); // if (nonZeroCount >= 4) // homography = Features2DToolbox.GetHomographyMatrixFromMatchedFeatures(modelKeyPoints, observedKeyPoints, indices, mask, 2); // } // watch.Stop(); //} matchTime = 0; }
private string[] FindFeatureMatches(string sourceFile, string[] targetFiles, ObservableCollection <string> output) { //Emgu.CV.CvInvoke // Currently we are only interested in jpg files. targetFiles = targetFiles .Where(targetFile => { var extension = Path.GetExtension(targetFile).ToLower(); return(extension == ".jpg" || extension == ".jpeg"); }) .ToArray(); var matchingFiles = new List <string>(); using var sourceImage = CvInvoke.Imread(sourceFile, ImreadModes.Grayscale); using var sourceMat = new GpuMat(); //CudaInvoke.CvtColor(sourceImage, sourceMat, ColorConversion.Bgr2Bgra); sourceMat.Upload(sourceImage); using var sourceDescriptors = new GpuMat(); using var detector = new CudaORBDetector(); var sourceKeyPoints = detector.Detect(sourceMat, null); detector.Compute(sourceMat, new VectorOfKeyPoint(sourceKeyPoints), sourceDescriptors); //detector.DetectAndCompute(sourceImage, null, sourceKeyPoints, sourceDescriptors, false); Parallel.ForEach(targetFiles, new ParallelOptions { MaxDegreeOfParallelism = 40 }, targetFile => { try { if (targetFile == sourceFile) { return; // No need to match the original file. } if (new FileInfo(targetFile).Length == 0) // We cannot compare empty images. { return; } using var targetImage = CvInvoke.Imread(targetFile, ImreadModes.Grayscale); using var targetMat = new GpuMat(); targetMat.Upload(targetImage); // using var difference = new Mat(); // Cv2.Subtract(sourceImage, targetImage, difference); // // Cv2.Split(difference, out var split); // var r = split[0]; // var g = split[1]; // var b = split[2]; // var completeMatch = Cv2.CountNonZero(r) == 0 && Cv2.CountNonZero(g) == 0 && Cv2.CountNonZero(b) == 0; using var targetDescriptors = new GpuMat(); //var targetKeyPoints = new VectorOfKeyPoint(); using var detector2 = new CudaORBDetector(); var targetKeyPoints = detector2.Detect(targetMat, null); detector2.Compute(targetMat, new VectorOfKeyPoint(targetKeyPoints), targetDescriptors); //detector.DetectAndCompute(targetImage, null, targetKeyPoints, targetDescriptors, false); // Needed to compensate for some crashes. // See: https://stackoverflow.com/questions/25089393/opencv-flannbasedmatcher if (sourceKeyPoints.Length >= 2 && targetKeyPoints.Length >= 2) { using var matches = new VectorOfVectorOfDMatch(); using var matcher = new CudaBFMatcher(DistanceType.Hamming); matcher.KnnMatch(sourceDescriptors, targetDescriptors, matches, KnnMatchValue); var goodPoints = matches.ToArrayOfArray().Where(match => match.Length > 1) .Where(match => match[0].Distance < match[1].Distance * MatchDistance) //.Select(match => match[0]) .ToArray(); var matchCount = sourceKeyPoints.Length >= targetKeyPoints.Length ? sourceKeyPoints.Length : targetKeyPoints.Length; var matchQuality = (float)goodPoints.Length / matchCount; if (matchQuality >= MinimumMatchQuality) { using var outputImage = new Mat(); using var scaledOutputImage = new Mat(); Features2DToolbox.DrawMatches( sourceImage, new VectorOfKeyPoint(sourceKeyPoints), targetImage, new VectorOfKeyPoint(targetKeyPoints), new VectorOfVectorOfDMatch(goodPoints), outputImage, new Bgr(System.Drawing.Color.Yellow).MCvScalar, new Bgr(System.Drawing.Color.Red).MCvScalar); CvInvoke.Resize(outputImage, scaledOutputImage, System.Drawing.Size.Empty, 0.1f, 0.1f); Application.Current?.Dispatcher?.Invoke(() => CvInvoke.Imshow("Match preview", scaledOutputImage)); //Cv2.ImWrite(targetFile + ".comparison.jpg", scaledOutputImage); var sb = new StringBuilder(); sb.AppendLine($"{DateTime.Now} Matching:"); sb.AppendLine($"Source: {sourceFile}"); sb.AppendLine($"Target: {targetFile}"); sb.Append($"Match found with quality: {matchQuality}"); output.Add(sb.ToString()); } } } catch (Exception e) { var sb = new StringBuilder(); var exception = e.ToString().Replace(Environment.NewLine, " "); sb.Append($"{DateTime.Now} Unable to match file: {targetFile}: {exception}"); output.Add(sb.ToString()); } }); return(matchingFiles.ToArray()); }
/// <summary> /// Detect image using SURF /// </summary> /// <param name="modelImage"></param> /// <param name="observedImage"></param> /// <param name="modelKeyPoints"></param> /// <param name="observedKeyPoints"></param> /// <param name="matches"></param> /// <param name="mask"></param> /// <param name="homography"></param> public static void FindMatch(Mat modelImage, Mat observedImage, out VectorOfKeyPoint modelKeyPoints, out VectorOfKeyPoint observedKeyPoints, VectorOfVectorOfDMatch matches, out Mat mask, out Mat homography, out int score) { int k = 2; double uniquenessThreshold = 0.8; double hessianThresh = 300; homography = null; modelKeyPoints = new VectorOfKeyPoint(); observedKeyPoints = new VectorOfKeyPoint(); if (CudaInvoke.HasCuda) { CudaSURF surfCuda = new CudaSURF((float)hessianThresh); using (GpuMat gpuModelImage = new GpuMat(modelImage)) //extract features from the object image using (GpuMat gpuModelKeyPoints = surfCuda.DetectKeyPointsRaw(gpuModelImage, null)) using (GpuMat gpuModelDescriptors = surfCuda.ComputeDescriptorsRaw(gpuModelImage, null, gpuModelKeyPoints)) using (CudaBFMatcher matcher = new CudaBFMatcher(DistanceType.L2)) { surfCuda.DownloadKeypoints(gpuModelKeyPoints, modelKeyPoints); // extract features from the observed image using (GpuMat gpuObservedImage = new GpuMat(observedImage)) using (GpuMat gpuObservedKeyPoints = surfCuda.DetectKeyPointsRaw(gpuObservedImage, null)) using (GpuMat gpuObservedDescriptors = surfCuda.ComputeDescriptorsRaw(gpuObservedImage, null, gpuObservedKeyPoints)) //using (GpuMat tmp = new GpuMat()) //using (Stream stream = new Stream()) { matcher.KnnMatch(gpuObservedDescriptors, gpuModelDescriptors, matches, k); surfCuda.DownloadKeypoints(gpuObservedKeyPoints, observedKeyPoints); mask = new Mat(matches.Size, 1, DepthType.Cv8U, 1); mask.SetTo(new MCvScalar(255)); Features2DToolbox.VoteForUniqueness(matches, uniquenessThreshold, mask); score = 0; for (int i = 0; i < matches.Size; i++) { if ((byte)mask.GetData().GetValue(i, 0) == 0) { continue; } foreach (var e in matches[i].ToArray()) { ++score; } } 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); } } } } } else { using (UMat uModelImage = modelImage.GetUMat(AccessType.Read)) using (UMat uObservedImage = observedImage.GetUMat(AccessType.Read)) { SURF surfCPU = new SURF(hessianThresh); //extract features from the object image UMat modelDescriptors = new UMat(); surfCPU.DetectAndCompute(uModelImage, null, modelKeyPoints, modelDescriptors, false); // extract features from the observed image UMat observedDescriptors = new UMat(); surfCPU.DetectAndCompute(uObservedImage, null, observedKeyPoints, observedDescriptors, false); BFMatcher matcher = new BFMatcher(DistanceType.L2); 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); score = 0; for (int i = 0; i < matches.Size; i++) { //if (mask.GetData(true)[0] == 0) continue; foreach (var e in matches[i].ToArray()) { ++score; } } 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); } } } } }
public static void FindMatch(Mat modelImage, Mat observedImage, out long matchTime, out VectorOfKeyPoint modelKeyPoints, out VectorOfKeyPoint observedKeyPoints, VectorOfVectorOfDMatch matches, out Mat mask, out Mat homography, double hessianThresh) { int k = 2; double uniquenessThreshold = 0.8; //double hessianThresh = 300;设置阈值,这个值越大,最终的特征点越少 Stopwatch sw; homography = null; modelKeyPoints = new VectorOfKeyPoint(); observedKeyPoints = new VectorOfKeyPoint(); #if !__IOS__ //判断是否存在NVIDIA显卡,如果存在就是使用GPU进行计算 if (CudaInvoke.HasCuda) { //SURF算法 //创建一个CudaSurf 侦测器 CudaSURF surfCuda = new CudaSURF((float)hessianThresh); //在Gpu中 使用GpuMat 来替代cv::Mat using (GpuMat gpuModelImage = new GpuMat(modelImage)) //从图像中提取特征点 using (GpuMat gpuModelKeyPoints = surfCuda.DetectKeyPointsRaw(gpuModelImage, null)) //创建特征点描述器 using (GpuMat gupModelDescriptors = surfCuda.ComputeDescriptorsRaw(gpuModelImage, null, gpuModelKeyPoints)) //创建匹配器 using (CudaBFMatcher matcher = new CudaBFMatcher(DistanceType.L2)) { surfCuda.DownloadKeypoints(gpuModelKeyPoints, modelKeyPoints); sw = Stopwatch.StartNew(); using (GpuMat gpuObservedImage = new GpuMat(observedImage)) using (GpuMat gpuObservedKeyPoints = surfCuda.DetectKeyPointsRaw(gpuObservedImage, null)) using (GpuMat gpuObservedDescriptors = surfCuda.ComputeDescriptorsRaw(gpuObservedImage, null, gpuObservedKeyPoints)) //using (GpuMat tmp = new GpuMat()) //using (Stream stream = new Stream()) { matcher.KnnMatch(gpuObservedDescriptors, gpuObservedDescriptors, matches, k); surfCuda.DownloadKeypoints(gpuModelKeyPoints, observedKeyPoints); 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); } } } sw.Stop(); } } else #endif { using (UMat uModelImage = modelImage.ToUMat(AccessType.Read)) using (UMat uObservedImage = observedImage.ToUMat(AccessType.Read)) { //创建surf算法器 SURF surfCPU = new SURF(hessianThresh); //从源的图像提取描述符 UMat modelDescriptors = new UMat(); surfCPU.DetectAndCompute(uModelImage, null, modelKeyPoints, modelDescriptors, false); sw = Stopwatch.StartNew(); //从观察图像中提取描述器 UMat observedDescriptors = new UMat(); surfCPU.DetectAndCompute(uObservedImage, null, observedKeyPoints, observedDescriptors, false); //Brute Force匹配 BFMatcher matcher = new BFMatcher(DistanceType.L2); matcher.Add(modelDescriptors); //matches:VectorOfVectorOfDMatch //observedDescriptors:VectorOfKeyPoint 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) { //使用RANDSAC算法获取单应性矩阵,如果矩阵不能恢复,返回null homography = Features2DToolbox.GetHomographyMatrixFromMatchedFeatures(modelKeyPoints, observedKeyPoints, matches, mask, 2); } } sw.Stop(); } } matchTime = sw.ElapsedMilliseconds; }