public void Run() { using (var img1 = new Mat(FilePath.Image.SurfBox)) using (var img2 = new Mat(FilePath.Image.SurfBoxinscene)) using (var descriptors1 = new Mat()) using (var descriptors2 = new Mat()) using (var matcher = new BFMatcher(NormTypes.L2SQR)) using (var kaze = KAZE.Create()) { KeyPoint[] keypoints1, keypoints2; kaze.DetectAndCompute(img1, null, out keypoints1, descriptors1); kaze.DetectAndCompute(img2, null, out keypoints2, descriptors2); DMatch[][] matches = matcher.KnnMatch(descriptors1, descriptors2, 2); using (Mat mask = new Mat(matches.Length, 1, MatType.CV_8U)) { mask.SetTo(new Scalar(255)); int nonZero = Cv2.CountNonZero(mask); VoteForUniqueness(matches, mask); nonZero = Cv2.CountNonZero(mask); nonZero = VoteForSizeAndOrientation(keypoints2, keypoints1, matches, mask, 1.5f, 20); List<Point2f> obj = new List<Point2f>(); List<Point2f> scene = new List<Point2f>(); List<DMatch> goodMatchesList = new List<DMatch>(); //iterate through the mask only pulling out nonzero items because they're matches for (int i = 0; i < mask.Rows; i++) { MatIndexer<byte> maskIndexer = mask.GetGenericIndexer<byte>(); if (maskIndexer[i] > 0) { obj.Add(keypoints1[matches[i][0].QueryIdx].Pt); scene.Add(keypoints2[matches[i][0].TrainIdx].Pt); goodMatchesList.Add(matches[i][0]); } } List<Point2d> objPts = obj.ConvertAll(Point2fToPoint2d); List<Point2d> scenePts = scene.ConvertAll(Point2fToPoint2d); if (nonZero >= 4) { Mat homography = Cv2.FindHomography(objPts, scenePts, HomographyMethods.Ransac, 1.5, mask); nonZero = Cv2.CountNonZero(mask); if (homography != null) { Point2f[] objCorners = { new Point2f(0, 0), new Point2f(img1.Cols, 0), new Point2f(img1.Cols, img1.Rows), new Point2f(0, img1.Rows) }; Point2d[] sceneCorners = MyPerspectiveTransform3(objCorners, homography); //This is a good concat horizontal using (Mat img3 = new Mat(Math.Max(img1.Height, img2.Height), img2.Width + img1.Width, MatType.CV_8UC3)) using (Mat left = new Mat(img3, new Rect(0, 0, img1.Width, img1.Height))) using (Mat right = new Mat(img3, new Rect(img1.Width, 0, img2.Width, img2.Height))) { img1.CopyTo(left); img2.CopyTo(right); byte[] maskBytes = new byte[mask.Rows * mask.Cols]; mask.GetArray(0, 0, maskBytes); Cv2.DrawMatches(img1, keypoints1, img2, keypoints2, goodMatchesList, img3, Scalar.All(-1), Scalar.All(-1), maskBytes, DrawMatchesFlags.NotDrawSinglePoints); List<List<Point>> listOfListOfPoint2D = new List<List<Point>>(); List<Point> listOfPoint2D = new List<Point>(); listOfPoint2D.Add(new Point(sceneCorners[0].X + img1.Cols, sceneCorners[0].Y)); listOfPoint2D.Add(new Point(sceneCorners[1].X + img1.Cols, sceneCorners[1].Y)); listOfPoint2D.Add(new Point(sceneCorners[2].X + img1.Cols, sceneCorners[2].Y)); listOfPoint2D.Add(new Point(sceneCorners[3].X + img1.Cols, sceneCorners[3].Y)); listOfListOfPoint2D.Add(listOfPoint2D); img3.Polylines(listOfListOfPoint2D, true, Scalar.LimeGreen, 2); //This works too //Cv2.Line(img3, scene_corners[0] + new Point2d(img1.Cols, 0), scene_corners[1] + new Point2d(img1.Cols, 0), Scalar.LimeGreen); //Cv2.Line(img3, scene_corners[1] + new Point2d(img1.Cols, 0), scene_corners[2] + new Point2d(img1.Cols, 0), Scalar.LimeGreen); //Cv2.Line(img3, scene_corners[2] + new Point2d(img1.Cols, 0), scene_corners[3] + new Point2d(img1.Cols, 0), Scalar.LimeGreen); //Cv2.Line(img3, scene_corners[3] + new Point2d(img1.Cols, 0), scene_corners[0] + new Point2d(img1.Cols, 0), Scalar.LimeGreen); img3.SaveImage("Kaze_Output.png"); Window.ShowImages(img3); } } } } } }
private void MatchBySurf(Mat src1, Mat src2) { var gray1 = new Mat(); var gray2 = new Mat(); Cv2.CvtColor(src1, gray1, ColorConversionCodes.BGR2GRAY); Cv2.CvtColor(src2, gray2, ColorConversionCodes.BGR2GRAY); var surf = SURF.Create(500, 4, 2, true); // Detect the keypoints and generate their descriptors using SURF KeyPoint[] keypoints1, keypoints2; var descriptors1 = new MatOfFloat(); var descriptors2 = new MatOfFloat(); surf.Compute(gray1, null, out keypoints1, descriptors1); surf.Compute(gray2, null, out keypoints2, descriptors2); // Match descriptor vectors var bfMatcher = new BFMatcher(NormTypes.L2, false); var flannMatcher = new FlannBasedMatcher(); DMatch[] bfMatches = bfMatcher.Match(descriptors1, descriptors2); DMatch[] flannMatches = flannMatcher.Match(descriptors1, descriptors2); // Draw matches var bfView = new Mat(); Cv2.DrawMatches(gray1, keypoints1, gray2, keypoints2, bfMatches, bfView); var flannView = new Mat(); Cv2.DrawMatches(gray1, keypoints1, gray2, keypoints2, flannMatches, flannView); using (new Window("SURF matching (by BFMather)", WindowMode.AutoSize, bfView)) using (new Window("SURF matching (by FlannBasedMatcher)", WindowMode.AutoSize, flannView)) { Cv2.WaitKey(); } }
private void FindMatchingFeatures_Click(object sender, EventArgs e) { var file1 = comboBox1.SelectedItem.ToString(); var file2 = comboBox2.SelectedItem.ToString(); using (var img1 = new Mat(file1, ImreadModes.GrayScale)) using (var img2 = new Mat(file2, ImreadModes.GrayScale)) using (var dst = new Mat()) { // find keypoints //var kp1 = FindFeatures(Constants.ImageControl1); //var kp2 = FindFeatures(Constants.ImageControl2); // find descriptors var descriptors1 = new Mat(); var descriptors2 = new Mat(); var kp1 = FindFeaturesDescriptors_ORB(file1, out descriptors1); var kp2 = FindFeaturesDescriptors_ORB(file2, out descriptors2); // find keypoint matches var bfMatcher = new BFMatcher(NormTypes.Hamming2, true); DMatch[] bfMatches = bfMatcher.Match(descriptors1, descriptors2); // draw things Cv2.DrawMatches(img1, kp1, img2, kp2, bfMatches, dst); using (new Window("ORB matching (by BFMatcher)", WindowMode.FreeRatio, dst)) { Cv2.WaitKey(); } } }