首先截取匹配模板,然后使用rootsift特征匹配,最后定位目标。
对于微弱变化,还是能够识别定位的,对于传统算法来说已经不错了。
目标定位效果:

使用的模板图片。
cs
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