C++ OpenCV模擬實現微信跳一跳
前提精要:
本程序參考瞭大量的大佬佬的代碼,在此基礎之上,改編而成。而且其實代碼寫的奇差無比,很容易就掛瞭。然後呢,這裡隻是稍微提供一些思路,作為參考,就醬。
本程序依賴adb.exe和opencv425庫。
本程序還有待優化,很渣很糟糕~
僅供學習交流使用,切勿使用在違規違法的環境之中。
實機演示Gif:
思路:
獲取小黑人的位置,獲得目標方塊的位置,計算兩者的距離,從而計算粗按壓屏幕的時間是多少。
具體實現1:使用mumu模擬器獲取截圖
使用mumu模擬器,模擬手機端,然後使用adb調試工具截圖,保存到本地,然後從OpenCV程序獲取在本地的截圖。
具體實現2:使用adb工具模擬按壓
當計算完距離和時間之後,考慮使用模擬按壓屏幕的方法,控制小人的移動。
具體實現3:按壓的位置剛好在“再來一次”的按鈕上
這樣就算跳失敗瞭,隻要用戶不停下,那麼小程序就會一直的進行跳躍。
獲取小黑人的位置:
很簡單,隻是使用OpenCV的matchTemplate就可以啦,註意使用“TM_CCORR_NORMED”方法。
獲取終點的位置:
這裡使用的是Canny邊緣檢測算法
需要自定義的:
一個文件夾,將圖片,從mumu模擬器,保存到本地的目錄文件夾。和Debug的緩存目錄。
您還可以自定義,程序運行的循環次數:
//最大執行次數 #define MaxRound 100
修改後面的100即可。
還有您的匹配模式圖片位置:
character3.png
完整項目:
項目配置:DebugX64,包含頭文件opencv頭文件,lib選擇為opencv_world425d.dll(好像是這個名字),這個lib一定要有d,因為我們是Debug模式,所以使用這個庫。然後鏈接器的附加輸入,也填入這個選項。
項目依賴:adb、opencv425
下面是完整的項目參考。
項目結構
pch.h
#pragma once #include <opencv2/opencv.hpp> #include <iostream> #include <opencv.hpp> #include <windows.h>
main.cpp
//跳一跳作弊程序
//版本 v1.0.2 作者:CSDN陳千裡
/*
* 程序使用說明:
* 需要配合mumu模擬器使用,電腦需要安裝adb調試工具,和opencv庫。
* 程序原理介紹:
* 通過計算兩點之間的距離,估算跳躍的長度,按壓屏幕的時間間隔
*
* 參考論文:
* https://blog.csdn.net/qq_37406130/article/details/79007335
* https://blog.csdn.net/sundy_2004/article/details/7749093
* https://blog.csdn.net/q5222890/article/details/105533233
* https://blog.csdn.net/qq_47342178/article/details/109779840
* adb swip使用:
* https://blog.csdn.net/u010042669/article/details/104066744
* Canny 邊緣檢測:
* https://blog.csdn.net/hensonwells/article/details/112557073
*/
#include "pch.h"
#include <windows.h>
#include <sstream>
using namespace cv;
Mat srcImage;//存放跳一跳的截圖
Mat blackPeopleTem;//黑色小人匹配圖
std::stringstream ssm; //int轉string
//最大執行次數
#define MaxRound 100
//由於分辨率的不同,微調終點的位置
#define Tuning 0.52f
//Debug函數
void DebugImg(const std::string& fileName, Mat& mat, const Point& point);
void DebugImg(const std::string& fileName, Mat& mat);
//刷新srcImage的信息(截圖)
void refreshSrcImage() {
system("adb shell screencap -p /sdcard/ScreenCatch.png");
//您需要自定義的地方,下面的"C:\\adb"
system("adb pull /sdcard/ScreenCatch.png C:\\adb\\temp");
srcImage = imread("C:\\adb\\temp\\ScreenCatch.png");
}
//尋找跳一跳黑色小人的位置
Point GetNowPoint(Mat& srcImage, Mat& Tem_img) {
cv::Mat image_matched;
matchTemplate(srcImage, Tem_img, image_matched, TM_CCORR_NORMED);// 匹配黑棋子
double minVal, maxVal;
Point minLoc, maxLoc, matchLoc;
DebugImg("黑人匹配圖.png", image_matched);
minMaxLoc(image_matched, &minVal, &maxVal, &minLoc, &maxLoc, Mat());
matchLoc = maxLoc; //matchLoc是最佳匹配的區域左上角點
//調試輸出
DebugImg("1黑人位置.png", srcImage, Point(matchLoc.x + Tem_img.cols, matchLoc.y + Tem_img.rows));
//DebugImg("1黑人位置.png", srcImage, Point(matchLoc.x + Tem_img.cols * 0.5, matchLoc.y + Tem_img.rows));
return Point(matchLoc.x, matchLoc.y);
}
//獲得小方塊的目標點
Point GetNextPoint(Mat& srcImage) {
cv::Point point1;
cv::Point point2;
cv::GaussianBlur(srcImage, srcImage, cv::Size(5, 5), 0); //高斯濾波,降低噪聲
Mat temp, temp2;
//cv::threshold(srcImage, temp, 0, 255, 8);
//srcImage = temp;
Canny(srcImage, temp, 20, 30); //進行邊緣檢測
temp2 = srcImage;
srcImage = temp;
std::vector<std::vector<Point>> contours;
std::vector<Vec4i> hierarchy;
findContours(srcImage, contours, hierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE, Point()); //找到關鍵的角點
//遍歷每一個輪廓,把多餘的輪廓去掉
std::vector<std::vector<cv::Point> >::const_iterator it = contours.begin();
while (it != contours.end()) {
if (it->size() < 150)
it = contours.erase(it);
else
++it;
}
int nYMin = srcImage.rows;
int nXMin = srcImage.cols;
int nYMax = 0;
int nXMax = 0;
int nIdY = 0;
for (int i = 0; i < contours.size(); i++) {
//contours[i]代表的是第i個輪廓,contours[i].size()代表的是第i個輪廓上所有的像素點數
for (int j = 0; j < contours[i].size(); j++) {
if (contours[i][j].y < nYMin) {
nYMin = contours[i][j].y; //找到最低的y值
point1 = contours[i][j]; //記錄 y值最低點坐標
nIdY = i; //記錄哪個區域內的
}
}
}
int minY = srcImage.cols;
for (int j = 0; j < contours[nIdY].size(); j++) { //在哪個區域內繼續變量 找到x最大值
if (contours[nIdY][j].x > nXMax) {
nXMax = contours[nIdY][j].x;
}
}
for (int j = 0; j < contours[nIdY].size(); j++) {//找到x中最大值上的最小值
if (contours[nIdY][j].x == nXMax && contours[nIdY][j].y < minY) {
point2 = contours[nIdY][j];
minY = contours[nIdY][j].y; //記錄X點的最大值
}
}
//調試輸出
DebugImg("2目標點位置.png", temp2, Point(point1.x, point2.y));
DebugImg("邊緣圖.png", srcImage, Point(point1.x, point2.y));
return cv::Point(point1.x, point2.y); //返回中點坐標
}
//計算兩個點的距離
float GetDistance(Point& first_point, Point& next_point) {
float A = first_point.x - next_point.x;
float B = first_point.y - (next_point.y + 50);
float result = pow(pow(A, 2) + pow(B, 2), 0.5);
if (result > 600) {
std::cout << "距離探測失誤" << std::endl;
result = 230;
}
return result;
}
//模擬按壓屏幕跳躍
void Jump(float& g_distance) {
std::cout << "distance:" << g_distance << std::endl;
int time = std::ceil(g_distance * 4 * Tuning);
std::string str_Time, str;
//模擬長按屏幕
ssm.clear();
ssm << time;
ssm >> str_Time;
str = "adb shell input swipe 461 1203 461 1203 " + str_Time;
std::cout << str << std::endl;
system(str.c_str());
}
//主過程
void Process() {
Point pBlackPeople;
Point pFinish;
float dis;
for (int i = 0; i < MaxRound; i++) {
refreshSrcImage();
pBlackPeople = GetNowPoint(srcImage, blackPeopleTem);
pFinish = GetNextPoint(srcImage);
dis = GetDistance(pBlackPeople, pFinish);
Jump(dis);
Sleep(2000);
}
}
int main() {
/*srcImage = imread("C:/adb/Test/1.png");
blackPeopleTem = imread("C:/adb/Resources/character3.png");
GetNowPoint(srcImage, blackPeopleTem);*/
//首先要鏈接端口
system("adb connect 127.0.0.1:7555");
refreshSrcImage();
blackPeopleTem = imread("C:/adb/Resources/character3.png");
//初始化到此結束
Process();
int x = 280; // 裁剪區域起始點 x坐標
int y = 400; // 裁剪區域起始點 y坐標
int width = 100; // 裁剪區域寬度
int height = 100; // 裁剪區域高度
//Rect area(x, y, width, height);
//Mat guide_roi = srcImage(Rect(x, y, width, height));
//測試代碼
//namedWindow("test opencv setup", WINDOW_AUTOSIZE);
//imshow("test opencv setup", srcImage);
//waitKey(0);
return 0;
}
//保存圖片和畫點,用於調試
void DebugImg(const std::string& fileName, Mat& mat, const Point& point) {
Mat temp = mat;
//在圖片上面畫點
circle(temp, point, 5, Scalar(0, 0, 255), -1);
std::string path = "c:/adb/temp/", sR;
sR = path + fileName;
imwrite(sR, temp);
}
void DebugImg(const std::string& fileName, Mat& mat) {
std::string path = "c:/adb/temp/", sR;
sR = path + fileName;
imwrite(sR, mat);
}
到此這篇關於C++ OpenCV模擬實現微信跳一跳的文章就介紹到這瞭,更多相關C++ OpenCV微信跳一跳內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!
推薦閱讀:
- 使用c++實現OpenCV繪制圓端矩形
- OpenCV 輪廓周圍繪制矩形框和圓形框的方法
- OpenCV繪制圓端矩形的示例代碼
- OpenCV邊緣提取算法流程的實現(附DEMO)
- opencv實現圖像傾斜校正