您好,登錄后才能下訂單哦!
小編給大家分享一下C++ OpenCV如何模擬實現微信跳一跳,希望大家閱讀完這篇文章之后都有所收獲,下面讓我們一起去探討吧!
獲取小黑人的位置,獲得目標方塊的位置,計算兩者的距離,從而計算粗按壓屏幕的時間是多少。
具體實現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
下面是完整的項目參考。
#pragma once #include <opencv2/opencv.hpp> #include <iostream> #include <opencv.hpp> #include <windows.h>
//跳一跳作弊程序 //版本 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如何模擬實現微信跳一跳”有了一定的了解,如果想了解更多相關知識,歡迎關注億速云行業資訊頻道,感謝各位的閱讀!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。