现在的手游基本都是重复操作,一个动作要等好久,结束之后继续另一个动作.很麻烦,所以动起了自己写一个游戏辅助的心思.

这个辅助本身没什么难度,就是通过不断的截图,然后从这个截图中找出预先截好的能代表相应动作的按钮或者触发条件的小图.

找到之后获取该子区域的左上角坐标,然后通过windows API调用鼠标或者键盘做操作就行了.

这里面最难的也就是找图了,因为要精准找图,而且最好能适应不同的分辨率下找图,所以在模板匹配的基础上,就有了SIFT和SURF的特征点找图方式.

在写的过程中查找资料,大都是C++ 或者python的, 很少有原生的C#实现, 所以我就直接拿来翻译过来了(稍作改动).

SIFT算法

public static Bitmap MatchPicBySift(Bitmap imgSrc, Bitmap imgSub)
{
using (Mat matSrc = imgSrc.ToMat())
using (Mat matTo = imgSub.ToMat())
using (Mat matSrcRet = new Mat())
using (Mat matToRet = new Mat())
{
KeyPoint[] keyPointsSrc, keyPointsTo;
using (var sift = OpenCvSharp.XFeatures2D.SIFT.Create())
{
sift.DetectAndCompute(matSrc, null, out keyPointsSrc, matSrcRet);
sift.DetectAndCompute(matTo, null, out keyPointsTo, matToRet);
}
using (var bfMatcher = new OpenCvSharp.BFMatcher())
{
var matches = bfMatcher.KnnMatch(matSrcRet, matToRet, k: ); var pointsSrc = new List<Point2f>();
var pointsDst = new List<Point2f>();
var goodMatches = new List<DMatch>();
foreach (DMatch[] items in matches.Where(x => x.Length > ))
{
if (items[].Distance < 0.5 * items[].Distance)
{
pointsSrc.Add(keyPointsSrc[items[].QueryIdx].Pt);
pointsDst.Add(keyPointsTo[items[].TrainIdx].Pt);
goodMatches.Add(items[]);
Console.WriteLine($"{keyPointsSrc[items[0].QueryIdx].Pt.X}, {keyPointsSrc[items[0].QueryIdx].Pt.Y}");
}
} var outMat = new Mat(); // 算法RANSAC对匹配的结果做过滤
var pSrc = pointsSrc.ConvertAll(Point2fToPoint2d);
var pDst = pointsDst.ConvertAll(Point2fToPoint2d);
var outMask = new Mat();
// 如果原始的匹配结果为空, 则跳过过滤步骤
if (pSrc.Count > && pDst.Count > )
Cv2.FindHomography(pSrc, pDst, HomographyMethods.Ransac, mask: outMask);
// 如果通过RANSAC处理后的匹配点大于10个,才应用过滤. 否则使用原始的匹配点结果(匹配点过少的时候通过RANSAC处理后,可能会得到0个匹配点的结果).
if (outMask.Rows > )
{
byte[] maskBytes = new byte[outMask.Rows * outMask.Cols];
outMask.GetArray(, , maskBytes);
Cv2.DrawMatches(matSrc, keyPointsSrc, matTo, keyPointsTo, goodMatches, outMat, matchesMask: maskBytes, flags: DrawMatchesFlags.NotDrawSinglePoints);
}
else
Cv2.DrawMatches(matSrc, keyPointsSrc, matTo, keyPointsTo, goodMatches, outMat, flags: DrawMatchesFlags.NotDrawSinglePoints);
return OpenCvSharp.Extensions.BitmapConverter.ToBitmap(outMat);
}
}
}

SURF算法

public static Bitmap MatchPicBySurf(Bitmap imgSrc, Bitmap imgSub, double threshold = )
{
using (Mat matSrc = imgSrc.ToMat())
using (Mat matTo = imgSub.ToMat())
using (Mat matSrcRet = new Mat())
using (Mat matToRet = new Mat())
{
KeyPoint[] keyPointsSrc, keyPointsTo;
using (var surf = OpenCvSharp.XFeatures2D.SURF.Create(threshold,,,true,true))
{
surf.DetectAndCompute(matSrc, null, out keyPointsSrc, matSrcRet);
surf.DetectAndCompute(matTo, null, out keyPointsTo, matToRet);
} using (var flnMatcher = new OpenCvSharp.FlannBasedMatcher())
{
var matches = flnMatcher.Match(matSrcRet, matToRet);
//求最小最大距离
double minDistance = ;//反向逼近
double maxDistance = ;
for (int i = ; i < matSrcRet.Rows; i++)
{
double distance = matches[i].Distance;
if (distance > maxDistance)
{
maxDistance = distance;
}
if (distance < minDistance)
{
minDistance = distance;
}
}
Console.WriteLine($"max distance : {maxDistance}");
Console.WriteLine($"min distance : {minDistance}"); var pointsSrc = new List<Point2f>();
var pointsDst = new List<Point2f>();
//筛选较好的匹配点
var goodMatches = new List<DMatch>();
for (int i = ; i < matSrcRet.Rows; i++)
{
double distance = matches[i].Distance;
if (distance < Math.Max(minDistance * , 0.02))
{
pointsSrc.Add(keyPointsSrc[matches[i].QueryIdx].Pt);
pointsDst.Add(keyPointsTo[matches[i].TrainIdx].Pt);
//距离小于范围的压入新的DMatch
goodMatches.Add(matches[i]);
}
} var outMat = new Mat(); // 算法RANSAC对匹配的结果做过滤
var pSrc = pointsSrc.ConvertAll(Point2fToPoint2d);
var pDst = pointsDst.ConvertAll(Point2fToPoint2d);
var outMask = new Mat();
// 如果原始的匹配结果为空, 则跳过过滤步骤
if (pSrc.Count > && pDst.Count > )
Cv2.FindHomography(pSrc, pDst, HomographyMethods.Ransac, mask: outMask);
// 如果通过RANSAC处理后的匹配点大于10个,才应用过滤. 否则使用原始的匹配点结果(匹配点过少的时候通过RANSAC处理后,可能会得到0个匹配点的结果).
if (outMask.Rows > )
{
byte[] maskBytes = new byte[outMask.Rows * outMask.Cols];
outMask.GetArray(, , maskBytes);
Cv2.DrawMatches(matSrc, keyPointsSrc, matTo, keyPointsTo, goodMatches, outMat, matchesMask: maskBytes, flags: DrawMatchesFlags.NotDrawSinglePoints);
}
else
Cv2.DrawMatches(matSrc, keyPointsSrc, matTo, keyPointsTo, goodMatches, outMat, flags: DrawMatchesFlags.NotDrawSinglePoints);
return OpenCvSharp.Extensions.BitmapConverter.ToBitmap(outMat);
}
}
}

模板匹配

 public static System.Drawing.Point FindPicFromImage(Bitmap imgSrc, Bitmap imgSub, double threshold = 0.9)
{
OpenCvSharp.Mat srcMat = null;
OpenCvSharp.Mat dstMat = null;
OpenCvSharp.OutputArray outArray = null;
try
{
srcMat = imgSrc.ToMat();
dstMat = imgSub.ToMat();
outArray = OpenCvSharp.OutputArray.Create(srcMat); OpenCvSharp.Cv2.MatchTemplate(srcMat, dstMat, outArray, Common.templateMatchModes);
double minValue, maxValue;
OpenCvSharp.Point location, point;
OpenCvSharp.Cv2.MinMaxLoc(OpenCvSharp.InputArray.Create(outArray.GetMat()), out minValue, out maxValue, out location, out point);
Console.WriteLine(maxValue);
if (maxValue >= threshold)
return new System.Drawing.Point(point.X, point.Y);
return System.Drawing.Point.Empty;
}
catch(Exception ex)
{
return System.Drawing.Point.Empty;
}
finally
{
if (srcMat != null)
srcMat.Dispose();
if (dstMat != null)
dstMat.Dispose();
if (outArray != null)
outArray.Dispose();
}
}

OpenCvSharp 通过特征点匹配图片的更多相关文章

  1. sift、surf、orb 特征提取及最优特征点匹配

    目录 sift sift特征简介 sift特征提取步骤 surf surf特征简介 surf特征提取步骤 orb orb特征简介 orb特征提取算法 代码实现 特征提取 特征匹配 附录 sift si ...

  2. aforge通过角点匹配图片相似度

    我不知道什么原因,人品不好还是啥的 ExhaustiveTemplateMatching这个类无法高精确度的匹配图片 ........... 换一种方式,就好得多 /// <summary> ...

  3. OpenCV使用FLANN进行特征点匹配

    使用FLANN进行特征点匹配 目标 在本教程中我们将涉及以下内容: 使用 FlannBasedMatcher 接口以及函数 FLANN 实现快速高效匹配( 快速最近邻逼近搜索函数库(Fast Appr ...

  4. opencv 增强现实(二):特征点匹配

    import cv2 as cv import numpy as np # def draw_keypoints(img, keypoints): # for kp in keypoints: # x ...

  5. 第二篇 特征点匹配以及openvslam中的相关实现详解

    配置文件 在进入正题之前先做一些铺垫,在openvslam中,配置文件是必须要正确的以.yaml格式提供,通常需要指明使用的相机模型,ORB特征检测参数,跟踪参数等. #==============# ...

  6. (2)特征点匹配,并求旋转矩阵R和位移向量t

    include头文件中有slamBase.h # pragma once // 各种头文件 // C++标准库 #include <fstream> #include <vector ...

  7. 图像特征点匹配C代码

    #include "opencv2/core/core.hpp" #include "highgui.h" #include "opencv2/img ...

  8. [OpenCV]DMatch类和KeyPoints类:特征点匹配

    DMatch struct CV_EXPORTS_W_SIMPLE DMatch { CV_WRAP DMatch() : queryIdx(-), trainIdx(-), imgIdx(-), d ...

  9. opencv surf特征点匹配拼接源码

    http://blog.csdn.net/huixingshao/article/details/42672073 /** * @file SURF_Homography * @brief SURF ...

随机推荐

  1. linux初学者-系统服务的控制

      linux系统中系统服务的控制是比较重要的一部分,这也直接影响到计算机的使用,以下将会介绍一些系统服务的控制. 1.系统服务命令 系统的初始化程序是系统开始的第一个进程,pid为1.可以通过以下命 ...

  2. Win常用软件

    本节只适合windows系统 VScode 下载 安装 双击安装 打开目录方式 右键文件夹->使用VSCode打开 命令行打开 code folder [dzlua@win10:~]$ ls a ...

  3. JAVA-Spring AOP五大通知类型

    一.前置通知 在目标方法执行之前执行的通知 在前置通知方法,可以没有参数,也可以额外接收一个JoinPoint,Spring会自动将该对象传入,代表当前的连接点,通过该对象可以获取目标对象和目标方法相 ...

  4. 前端工程师和设计师必备的chrome插件

    Google Chrome是最好用的几个浏览器之一,今天我来分享下自己收集的一系列Chrome插件,希望对大家的学习和工作有帮助. 注:你可以通过复制链接或者在谷歌商店搜索相应插件的名称来获取以下插件 ...

  5. Codeforces 468C Hack it!

    https://www.luogu.org/problemnew/show/CF468C http://codeforces.com/contest/468/problem/C #include &l ...

  6. 万万没想到,JVM内存结构的面试题可以问的这么难?

    在我的博客中,之前有很多文章介绍过JVM内存结构,相信很多看多我文章的朋友对这部分知识都有一定的了解了. 那么,请大家尝试着回答一下以下问题: 1.JVM管理的内存结构是怎样的? 2.不同的虚拟机在实 ...

  7. http客户端-性能比较系列-第二篇-多线程

    系列文章: 单线程性能测试:https://www.cnblogs.com/victor2302/p/11077208.html 多线程性能测试:https://www.cnblogs.com/vic ...

  8. H5 Handlebars的简单使用

    扫码关注公众号,不定期更新干活 web 开发中,js 解析JSON 是经常的事情.非常繁琐.handlebars 使用了模版,只要你定义一个模版,提供一个json对象,handlebars 就能吧js ...

  9. 『开发技术』GPU训练加速原理(附KerasGPU训练技巧)

    0.深入理解GPU训练加速原理 我们都知道用GPU可以加速神经神经网络训练(相较于CPU),具体的速度对比可以参看我之前写的速度对比博文: [深度应用]·主流深度学习硬件速度对比(CPU,GPU,TP ...

  10. thinkphp 框架两种模式 两种模式:开发调试模式、线上生产模式

    define(‘APP_DEBUG’,true/false);