千家信息网

C++ OpenCV如何模拟实现微信跳一跳

发表于:2024-11-25 作者:千家信息网编辑
千家信息网最后更新 2024年11月25日,小编给大家分享一下C++ OpenCV如何模拟实现微信跳一跳,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!实机演示Gif:思路:获取小黑人的位置,获得目标方块的位置,计算两者的距离,
千家信息网最后更新 2024年11月25日C++ OpenCV如何模拟实现微信跳一跳

小编给大家分享一下C++ OpenCV如何模拟实现微信跳一跳,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!

实机演示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 #include #include #include 

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 #include 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> contours;        std::vector hierarchy;        findContours(srcImage, contours, hierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE, Point()); //找到关键的角点        //遍历每一个轮廓,把多余的轮廓去掉        std::vector >::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如何模拟实现微信跳一跳"有了一定的了解,如果想了解更多相关知识,欢迎关注行业资讯频道,感谢各位的阅读!

0