因此,在业余时间,我喜欢尝试通过计算机视觉技术自动化各种游戏。通常,与滤镜和像素检测匹配的模板可以正常工作。但是,我最近决定尝试使用功能匹配来浏览关卡。我的意图是保存整个探索地图的过滤图像。
然后每隔几秒从屏幕上复制一次Minimap,并以相同的方式过滤它,并使用Surf将其与我的完整地图相匹配,这应该有希望给我一个玩家当前位置(比赛的中心将是玩家所在的位置)在地图上)。下面是这个工作的一个很好的例子(左边找到匹配的完整地图,右边是迷你地图图像。
我遇到的问题是EMGU库中的冲浪匹配似乎在许多情况下发现不正确的匹配。
有时它并非如下所示:
我可以看到发生的事情是它的发现更好地匹配地图上不同位置的关键点,因为Surf应该是比例不变的。我不太了解EMGU库或冲浪来限制它,以便它只接受像最初的好的匹配,并抛弃这些不良的匹配,或调整它,以便那些不稳定的匹配是好的。
我正在使用新的2.4 EMGU代码库,我的SURF匹配代码如下。我真的很想得到它,以便它只返回总是相同大小的匹配(正常小地图大小的缩放比例与整个地图上的缩放比例),这样我就不会得到一些疯狂形状的匹配
public Point MinimapMatch(Bitmap Minimap, Bitmap FullMap)
{
Image<Gray, Byte> modelImage = new Image<Gray, byte>(Minimap);
Image<Gray, Byte> observedImage = new Image<Gray, byte>(FullMap);
HomographyMatrix homography = null;
SURFDetector surfCPU = new SURFDetector(100, false);
VectorOfKeyPoint modelKeyPoints;
VectorOfKeyPoint observedKeyPoints;
Matrix<int> indices;
Matrix<byte> mask;
int k = 6;
double uniquenessThreshold = 0.9;
try
{
//extract features from the object image
modelKeyPoints = surfCPU.DetectKeyPointsRaw(modelImage, null);
Matrix<float> modelDescriptors = surfCPU.ComputeDescriptorsRaw(modelImage, null, modelKeyPoints);
// extract features from the observed image
observedKeyPoints = surfCPU.DetectKeyPointsRaw(observedImage, null);
Matrix<float> observedDescriptors = surfCPU.ComputeDescriptorsRaw(observedImage, null, observedKeyPoints);
BruteForceMatcher<float> matcher = new BruteForceMatcher<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);
}
if (homography != null)
{ //draw a rectangle along the projected model
Rectangle rect = modelImage.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)};
homography.ProjectPoints(pts);
Array.ConvertAll<PointF, Point>(pts, Point.Round);
Image<Bgr, Byte> result = Features2DToolbox.DrawMatches(modelImage, modelKeyPoints, observedImage, observedKeyPoints, indices, new Bgr(255, 255, 255), new Bgr(255, 255, 255), mask, Features2DToolbox.KeypointDrawType.DEFAULT);
result.DrawPolyline(Array.ConvertAll<PointF, Point>(pts, Point.Round), true, new Bgr(Color.Red), 5);
return new Point(Convert.ToInt32((pts[0].X + pts[1].X) / 2), Convert.ToInt32((pts[0].Y + pts[3].Y) / 2));
}
}
catch (Exception e)
{
return new Point(0, 0);
}
return new Point(0,0);
}
答案 0 :(得分:1)
您有一个特定的情况,即在提取的关键点周围都有黑色区域。 当涉及到特征匹配时,请记住它发生在与提取的关键点相对应的描述符之间。
SURF描述符描述了一个补丁而不是单个关键点,并且在您的场景中可能是导致匹配性能不佳的原因。
[编辑]
分析您的场景可能的候选方法是包含部分轮廓匹配的方法。我不认为你已经发现它已经在opencv开箱即用,所以我可以建议你一篇好文章“ 外部轮廓的高效部分形状匹配“由Donoser提供,您可以从citeseerx中获取并且非常容易实现。