首先截取匹配模板,然后使用rootsift特征匹配,最后定位目標。
對于微弱變化,還是能夠識別定位的,對于傳統算法來說已經不錯了。
目標定位效果:
?使用的模板圖片。
using OpenCvSharp;
using OpenCvSharp.Features2D;using Point = OpenCvSharp.Point;namespace WinFormsApp8
{public partial class Form1 : Form{public Form1(){InitializeComponent();}// 轉換為RootSIFT描述子static void ConvertToRootSIFT(Mat descriptors){// L1歸一化for (int i = 0; i < descriptors.Rows; i++){var row = descriptors.Row(i);double sum = Cv2.Norm(row, NormTypes.L1);row /= sum;}// 平方根處理Cv2.Sqrt(descriptors, descriptors);}// 特征匹配static List<DMatch> MatchFeatures(Mat queryDescriptors, Mat sceneDescriptors){var matcher = new BFMatcher(NormTypes.L2);var matches = matcher.KnnMatch(queryDescriptors, sceneDescriptors, 2);// 應用比率測試var goodMatches = new List<DMatch>();foreach (var match in matches){if (match[0].Distance < 0.75 * match[1].Distance){goodMatches.Add(match[0]);}}return goodMatches;}// 繪制結果static void DrawResult(Mat image, RotatedRect rect){// 繪制旋轉矩形Point2f[] vertices = rect.Points();for (int i = 0; i < 4; i++){Cv2.Line(image, (Point)vertices[i], (Point)vertices[(i + 1) % 4],new Scalar(0, 255, 0), 3);}// 繪制矩形中心Cv2.Circle(image, (Point)rect.Center, 5, new Scalar(0, 0, 255), -1);}private void button1_Click(object sender, EventArgs e){try{Mat queryImage = Cv2.ImRead("2.bmp", ImreadModes.Color);using var queryGray = new Mat();Cv2.CvtColor(queryImage, queryGray, ColorConversionCodes.BGR2GRAY);using var sceneImage = new Mat(Environment.CurrentDirectory + "\\s.bmp", ImreadModes.Color);if (queryImage.Empty() || sceneImage.Empty()){Console.WriteLine("無法加載圖像!");return;}// 轉換為灰度圖using var sceneGray = new Mat();Cv2.CvtColor(sceneImage, sceneGray, ColorConversionCodes.BGR2GRAY);// 初始化SIFT檢測器var sift = SIFT.Create();// 檢測關鍵點和計算描述子KeyPoint[] queryKeypoints, sceneKeypoints;Mat queryDescriptors = new Mat(), sceneDescriptors = new Mat();sift.DetectAndCompute(queryGray, null, out queryKeypoints, queryDescriptors);sift.DetectAndCompute(sceneGray, null, out sceneKeypoints, sceneDescriptors);// 轉換為RootSIFT描述子ConvertToRootSIFT(queryDescriptors);ConvertToRootSIFT(sceneDescriptors);// 特征匹配var matches = MatchFeatures(queryDescriptors, sceneDescriptors);// 獲取匹配點對var queryPoints = matches.Select(m => queryKeypoints[m.QueryIdx].Pt).ToArray();var scenePoints = matches.Select(m => sceneKeypoints[m.TrainIdx].Pt).ToArray();if (queryPoints.Length >= 8 && scenePoints.Length >= 8)//這里數字可以改{// 計算單應性矩陣var homography = Cv2.FindHomography(InputArray.Create(queryPoints),InputArray.Create(scenePoints),HomographyMethods.Ransac, 5.0);// 獲取查詢圖像的四個角點var queryCorners = new Point2f[]{new Point2f(0, 0),new Point2f(queryImage.Cols, 0),new Point2f(queryImage.Cols, queryImage.Rows),new Point2f(0, queryImage.Rows)};// 變換到場景圖像中var sceneCorners = Cv2.PerspectiveTransform(queryCorners, homography);// 計算最小外接矩形var minRect = Cv2.MinAreaRect(sceneCorners);// 繪制結果DrawResult(sceneImage, minRect);// 顯示結果// 轉換為軸對齊矩形// Rect boundingRect = Cv2.BoundingRect(minRect.Points().Select(p => new Point((int)p.X, (int)p.Y)).ToArray());Cv2.ImShow("pic", sceneImage);Cv2.WaitKey(0);}else{MessageBox.Show("沒有足夠的匹配點來計算變換矩陣");}}catch (Exception ex){MessageBox.Show(ex.Message);}}}
}
【免費】RootSIFT的目標定位,opencvsharp資源-CSDN文庫https://download.csdn.net/download/vokxchh/90968508