OpenCvSharp 通過特徵點匹配圖片

2021-03-02 移動開發和人工智慧

現在的手遊基本都是重複操作,一個動作要等好久,結束之後繼續另一個動作.很麻煩,所以動起了自己寫一個遊戲輔助的心思.

這個輔助本身沒什麼難度,就是通過不斷的截圖,然後從這個截圖中找出預先截好的能代表相應動作的按鈕或者觸發條件的小圖.

找到之後獲取該子區域的左上角坐標,然後通過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: 2);

var pointsSrc = new List<Point2f>();
var pointsDst = new List<Point2f>();
var goodMatches = new List<DMatch>();
foreach (DMatch[] items in matches.Where(x => x.Length > 1))
{
if (items[0].Distance < 0.5 * items[1].Distance)
{
pointsSrc.Add(keyPointsSrc[items[0].QueryIdx].Pt);
pointsDst.Add(keyPointsTo[items[0].TrainIdx].Pt);
goodMatches.Add(items[0]);
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 > 0 && pDst.Count > 0)
Cv2.FindHomography(pSrc, pDst, HomographyMethods.Ransac, mask: outMask);
// 如果通過RANSAC處理後的匹配點大於10個,才應用過濾. 否則使用原始的匹配點結果(匹配點過少的時候通過RANSAC處理後,可能會得到0個匹配點的結果).
if (outMask.Rows > 10)
{
byte[] maskBytes = new byte[outMask.Rows * outMask.Cols];
outMask.GetArray(0, 0, 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 = 400)
{
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,4,3,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 = 1000;//反向逼近
double maxDistance = 0;
for (int i = 0; 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 = 0; i < matSrcRet.Rows; i++)
{
double distance = matches[i].Distance;
if (distance < Math.Max(minDistance * 2, 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 > 0 && pDst.Count > 0)
Cv2.FindHomography(pSrc, pDst, HomographyMethods.Ransac, mask: outMask);
// 如果通過RANSAC處理後的匹配點大於10個,才應用過濾. 否則使用原始的匹配點結果(匹配點過少的時候通過RANSAC處理後,可能會得到0個匹配點的結果).
if (outMask.Rows > 10)
{
byte[] maskBytes = new byte[outMask.Rows * outMask.Cols];
outMask.GetArray(0, 0, 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();
}
}

相關焦點

  • 特徵點檢測-SIFT
    再識Harris我們用這兩個「良好」去檢驗Harris,很容易得到Harris不具備尺度不變性(空間縮放后角點數量、相對位置會變化),但是具備旋轉不變性(旋轉後的角點還是角點,但是要識別兩張旋轉圖像之間的關係,需要獨立設定角點匹配算法)。從原理上講就是圖片縮放前後的相關矩陣不相似,導致求解特徵點會不同。
  • opencv教程-光流法
    opencv裡的光流法有兩種,稀疏光流法 和 稠密光流法。簡單理解的話光流就是一個向量,包含在一定時間間隔內x方向位置的變化、y方向位置的變化,所以其三個主要因素就是dx,dy,dt。基本假設:(1):相鄰幀亮度恆定(2):相鄰幀物體運動較小(3):同一物體具有相同運動1:稀疏光流法 cv.calcOpticalFlowPyrLK只匹配指定的點比如前一張圖片的角點。
  • OpenCV 4.5 發布!
    https://github.com/opencv/opencv/wiki/ChangeLog#version450在我愛計算機視覺公眾號後臺回復「opencv」,即可收到包含4.5版本的OpenCV各版本的下載。
  • 使用Python+OpenCV進行面部合成
    原文 http://www.learnopencv.com/face-morph-using-opencv-cpp-python/
  • 手把手:使用OpenCV進行面部合成— C++ / Python
    給定兩張圖片I和J,通過混合而成一張中間圖M。圖片I和J的混合程度由參數α控制,α的值在0和1之間(0≤α≤1)。當α= 0時,圖片M看似I;當α= 1時,圖片M看似J。簡單來講,你可以用以下方程在每個像素點(x,y)混合圖片但是,用以上方程(假設α= 0.5)得到的國務卿希拉蕊•柯林頓與參議員特德•克魯茲的混合圖片,是下面這個有點糟糕的結果。
  • 使用OpenCv和Dlib進行打哈欠檢測
    安裝OpenCv和Dlib庫OpenCv的安裝如下:pip install opencv-pythonDlib的安裝如下:pip install cmake>pip install dlib導入Opencv,Dlib和Numpy庫設置dat文件我們將.dat文件放置到工作目錄中,它是一個可以識別面部特徵並提供信息的模型。
  • opencv-python獲取圖像:面向對象與面向過程
    獲取圖像的方式有:1,讀取本地圖片,2,調用筆記本自帶攝像頭或usb攝像頭,3,調用網絡攝像頭。這裡需要注意以下,opencv讀取圖片默認通道為BGR的格式,當在其他UI用戶界面顯示圖像時注意轉換一下通道順序,例如BGR轉換成RGB:Image1=cv2.cvtColor(image, cv2.COLOR_BGR2RGB)下面讀取一張圖片並顯示
  • card是卡片,sharp是尖銳的,那card sharp是什麼意思?
    我們知道card的意思是「卡片」,sharp的意思是「尖銳的」,那card sharp是什麼意思呢?card sharp的意思是「a person who earns money by playing cards dishonestly」,即「(玩紙牌時)作弊贏錢的人,耍老千的人」。
  • Python中如何利用Opencv打開視頻或圖像並用PyQt控制項顯示
    一、python中opencv打開圖像方法:import cv2filename='dog.jpg'img=cv2.imread(filename)cv2.imshow('Main Window',img)cv2.waitKey() #任意鍵退出cv2.destroyAllWindows()
  • 計算機視覺的研究是如何通過感知來獲取圖像特徵的
    計算機視覺的研究是如何通過感知來獲取圖像特徵的,不同的數據集(如車輛數據集或行人數據集)數據的實時性有不同的要求。那麼如何測試已有數據集,並做目標檢測、定位、跟蹤等任務。數據集中哪些信息對於cnn來說是不重要的?
  • 傾斜影像密集匹配三維點雲自動識別分類研究
    為了充分發揮實景三維成果的價值,實驗室針對傾斜影像密集匹配點雲的自動分類進行了研究,希望為實景三維成果的深度應用提供一種思路。點雲是現實世界三維數位化的一種表達方式,主要包括雷射掃描點雲和影像密集匹配點雲兩類。其中,雷射掃描點雲可以通過機載、地面、車載、手持等方式獲取,它們均具備回波強度、回波次數等信息,可以方便地對建築物、植被、地面等進行準確分類。
  • OpenCV黑魔法之隱身衣 | 附源碼
    如果對你有所幫助,給我點讚 & 在看,讓我知道對你有幫助哈!如果你是個哈利波特迷,你就會知道什麼是隱形衣。是的!這是哈利波特用來隱身的隱形衣。當然,我們都知道隱形衣不是真的——它都是圖形上的詭計。在這篇文章中,我們將學習如何使用OpenCV中的簡單計算機視覺技術創建我們自己的「隱形衣」。
  • 基於python+opencv的圖像目標區域自動提取
    檢測矩形並提取坐標需要對圖像進行預處理、邊緣檢測、提取輪廓、檢測凸包、角點檢測。通過OpenCV提供的cv2.imread可以讀入原始圖片,讀入的圖片被表示成一個三維數組的結構,可以通過數組下標訪問每一個點的顏色信息。
  • 在PPT設計中,如何讓圖片與文字匹配?一個辦法輕鬆解決
    圖片在PPT中的重要性不言而喻。有調查表明:傳輸到大腦的信息90%都是視覺信息,而大腦處理視覺信息的速度是文字信息的60000倍。在PPT當中,一張優質、契合主題的圖片,可以抵得上千言萬語。最好的解釋往往都是圖文並茂的。正所謂一圖勝千言。
  • 基於ADCensus的改進雙目立體匹配算法
    立體匹配是雙目視覺中的重 要做成部分,通過立體匹配找出同一視點在左右兩幅圖 像的坐標位置,從而計算得到視差圖,得到圖像的深 度信息[2]。匹配的正確性直接關係到深度圖計算的準確 性,所以,如何優化及聚合匹配代價使匹配算法有更高 的匹配率,是匹配算法優化的首要目標[3]。
  • 清華推非對稱遮擋感知的特徵匹配模塊
    3月26日消息,在論文《MaskFlownet: Asymmetric Feature Matching with Learnable Occlusion Mask》中,清華大學的研究人員提出了一種非對稱遮擋感知的特徵匹配模塊,該模塊可以學習一種粗糙遮擋掩模,該掩模在特徵warping後立即過濾無用 (遮擋) 區域,而不需要任何顯式監督。
  • 血型說:詳細解讀AB型血的性格特徵和情感匹配
    A、B、O、AB,4種類型的血型,分別有著自己的性格特徵。「血型說」將對四種血型的性格特徵,及其與其他血型的匹配程度一起進行詳細的解讀。
  • 血型說:詳細解讀O型血的性格特徵和情感匹配
    A、B、O、AB,4種類型的血型,分別有著自己的性格特徵。「血型說」將對四種血型的性格特徵,及其與其他血型的匹配程度一起進行詳細的解讀。
  • 談談OpenCV中的四邊形
    首先拋出一個問題,給定一系列二維平面上的的點,這些點是可以組成一個封閉的二維圖形。