基于VS+Opencv2.4.10微信跳一跳辅助工具

 更新时间:2018年01月10日 11:00:01   作者:att0206  
这篇文章主要为大家详细介绍了基于VS+Opencv2.4.10微信跳一跳辅助工具,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

最近微信的跳一跳小程序可谓火了一把,不是因为它本身多好玩,而是有大部分的程序员们加入其中,利用各种领域方法,实现了微信跳一跳的外挂,分数轻松上千或上万。之前也看了基于Python开源的代码,GitHub上现在的star已经快超过1W了,简直不敢想。趁着今天礼拜天,在实验室中也简单的实现了一下微信跳一跳的辅助工具,精度还不够高,我跑了一下才到90,纯属娱乐好玩的,后期再继续改进,主要是依赖C++来实现了一下。
环境: Win10+VS2012+Opencv2.4.10+ADB工具
环境的搭建请查阅相关资料!

主要思路:

通过adb图像获取部分大家可以查阅相关资料,代码也很简单:

adb shell screencap -p /sdcard/autojump.png
adb pull /sdcard/autojump.png

利用上面两行代码即可将手机当前的屏幕进行截图并且上传到工程文件路径下。

首先就是在上传的autojump.png图片上进行模板匹配,匹配出小人,并计算小人的坐标;
然后就是通过Canny()函数进行图像的边缘检测,这里使用的阈值为5,10基本可以检测出所有边缘信息;
然后根据一般下一个要跳的地点始终在小人的左半屏或又半屏部分这一先验知识,来进行查找范围的确定,进行行扫描,扫描到的第一个值为255的即返回当前坐标值;然后通过计算与小人坐标的距离即可得到下一步要跳跃的距离,(注:本代码中在下一个坐标的纵坐标进行+50处理,由于本文中只利用了一个关键点进行测试的,这样做是显然不合理的,接下来可以再利用第二个关键点进行下一个跳跃目标中心点的计算),由于本人手机是1080*1920的所以再得到距离过后乘以一个跳跃系数1.35,(这里不同分辨率的手机系数是不一样的),这样就得到了跳跃按压时间,从而通过system()命令进行调用ADB工具进行与手机通讯实现模拟人的点击。本文仅仅是简单的实现了一下看看效果,如果想跑高分还得进行代码的优化与更改!其次因为每次按压的地点肯定是不一样的,而本文也采用简单的同一位置按压,这样做很容易被腾讯反作弊给查出来的,所以这里可以添加一个随机数从而可以简单的避免位置重复!

代码如下:

/*
 时间:2018-1-7
 地点:SHNU
 功能:wechat简单跳一跳C++代码的实现,有待改进,仅供学习之用!欢迎大家提出新算法
*/

#include<opencv2/opencv.hpp>
#include<iostream>
#include<math.h>

using namespace cv;
using namespace std;

//全局变量定义区
Mat srcImage;
Mat dstImage;
Mat Character;
//get_screenshot();获取手机上的图像
void get_screenshot();
//Canny_Dec();边缘检测
void Canny_Dec(Mat& srcImage);
//获取Character坐标
Point get_Character_Loc(Mat& srcImage,Mat& Tem_img);
//获取下一个要跳的点
Point get_next_img_Loc(Mat& srcImage,Point& Character_Loc);
//计算距离
int get_distance(Point& first_point,Point& next_point);
//跳跃
void jump(int&g_distance);
int main(int argc,char** argv)
{
 system("color 3F");
 while (true)
 {
 get_screenshot();
 srcImage = imread("autojump.png");
 dstImage = srcImage.clone();
 Character = imread("./Template/character.png");
 //imshow("Character",Character);
 //cvtColor(srcImage,srcImage,CV_BGR2GRAY);
 Point next_p = get_Character_Loc(srcImage,Character);
 cout<<"next_p:"<<1111<<endl;

 Point get_next = get_next_img_Loc(srcImage,next_p);

 int g_distance = get_distance(next_p,get_next);

 jump(g_distance);
 //cout<<"get_next_img_Loc:"<<get_next<<endl;
 circle(dstImage,get_next,8,Scalar(0,221,2));
 //imshow("test",dstImage);
 imwrite("Canny.png",dstImage);
 _sleep(1500);
 }
 return 0;
}

void get_screenshot()
{
 system("adb shell screencap -p /sdcard/autojump.png");
 system("adb pull /sdcard/autojump.png");
}

Point get_Character_Loc(Mat& srcImage,Mat& Tem_img)
{
 matchTemplate(srcImage,Tem_img,dstImage,CV_TM_SQDIFF);
 double minVal,maxVal;
 Point minLoc,maxLoc,matchLoc;
 minMaxLoc(dstImage,&minVal,&maxVal,&minLoc,&maxLoc,Mat());
 matchLoc = minLoc; //matchLoc是最佳匹配的区域左上角点

 rectangle(srcImage,Rect(matchLoc,Size(Character.cols,Character.rows)),Scalar(255,255,0),1,8,0);
 //Canny(srcImage,srcImage,1,10);
 putText(srcImage,"Wang",Point(matchLoc.x+Character.cols*0.5,matchLoc.y+Character.rows),1,2,Scalar(0,0,255));//画出Character小人的坐标
 return Point(matchLoc.x+Character.cols*0.5,matchLoc.y+Character.rows);
}

Point get_next_img_Loc(Mat& srcImage,Point& Character_Loc)
{
 cout<<"get_next_img_Loc"<<endl;
 cvtColor(srcImage,srcImage,CV_BGR2GRAY);
 Canny(srcImage,srcImage,5,10);
 imwrite("get_next_img_Loc.png",srcImage);
 //imshow("get",srcImage);
 cout<<"Character_Loc.x:"<<Character_Loc.x<<endl;
 if(Character_Loc.x < 540)
 {
  for(int j = int(srcImage.rows*0.2);j<int(srcImage.rows*0.8);j++)
  {
   uchar* data = srcImage.ptr<uchar>(j);
   for(int i = 1079;i > 540 ;i--)
   {

    if(data[i] == 255)
    {
     return Point(i,j);
     //cout<<"Point:"<<Point(i,j)<<endl;
    }
   }
  }
 }
 else
 {
  for(int j = int(srcImage.rows*0.2);j<int(srcImage.rows*0.8);j++)
  {
   uchar* data = srcImage.ptr<uchar>(j);
   for(int i = 0;i<540;i++)
   {
    if(data[i] == 255)
     return Point(i,j);
   }
  }
 }
}

int get_distance(Point& first_point,Point& next_point)
{
 int A = first_point.x - next_point.x;
 int B = first_point.y - (next_point.y+50);
 return int(pow(pow(A,2)+pow(B,2),0.5));
}

void jump(int&g_distance)
{
 char AA[50];
 int distance_ = g_distance * 1.35;
 sprintf(AA,"adb shell input swipe 320 410 320 410 %d",distance_);
 cout<<AA<<endl;
 system(AA);
}

边缘检测图片:

这里写图片描述

下一个关键点定位:

这里写图片描述

上图中画出的小圈圈,不太清晰,将就着看下!小菜水平有限,仅仅是基于好玩就弄了下!

结果:用开源的随便跑跑几百,自己的怎么跑,90 【累哭】

这里写图片描述

华丽的分割线————————————————

又来更新一下啦!

晚上不想看论文就想到了之前的跳一跳,经过一边显示命令窗口输出和一边显示Canny()边缘化处理终于找到了上次跑的分数低的原因啦!

主要原因如下所示:

这里写图片描述

如上所示,由于之前选取的Canny()中的阈值为1和10,这导致一旦要跳到的下一个目标物体的颜色和背景色很接近时就很容易使得边缘的梯度小于10,因此就不会被认为是边缘,从而导致上面的这种情况出现。索性今天就将阈值设为3和8,并在Canny()函数前面加上了一个高斯滤波器。如下:

GaussianBlur(srcImage,srcImage,Size(3,3),0);

还有就是上面的_sleep(1500)函数,这里如果闲时间比较久的话也是可以改为1000的,速度上有所提升。
同时加上按压位置的随机数,使得每次按压点都是在(320,410)—(350,460)之间。代码如下:

 int rand_x = int(320+rand()%50); //加上随机数使得每次按压都是在点(320,410)-(370,460)之间
 int rand_y = int(410+rand()%50);
 sprintf(AA,"adb shell input swipe %d %d %d %d %d",rand_x,rand_y,rand_x,rand_y,distance_);

如下图所示:

由上图可知,每次按压的位置都是在变的。

完整版代码如下:

/*
 时间:2018-1-7
 地点:SHNU
 功能:wechat简单跳一跳C++代码的实现,有待改进,仅供学习之用!欢迎大家提出新算法
*/

#include<opencv2/opencv.hpp>
#include<iostream>
#include<math.h>
#include<stdlib.h>//rand()随机数头文件

using namespace cv;
using namespace std;

//全局变量定义区
Mat srcImage;
Mat dstImage;
Mat Character;

static int i = 0;
//get_screenshot();获取手机上的图像
void get_screenshot();
//Canny_Dec();边缘检测
void Canny_Dec(Mat& srcImage);
//获取Character坐标
Point get_Character_Loc(Mat& srcImage,Mat& Tem_img);
//获取下一个要跳的点
Point get_next_img_Loc(Mat& srcImage,Point& Character_Loc);
//计算距离
int get_distance(Point& first_point,Point& next_point);
//跳跃
void jump(int&g_distance);
int main(int argc,char** argv)
{
 system("color 3F");
 while (true)
 {
 get_screenshot();
 srcImage = imread("autojump.png");
 dstImage = srcImage.clone();
 Character = imread("./Template/character.png");
 //imshow("Character",Character);
 //cvtColor(srcImage,srcImage,CV_BGR2GRAY);
 Point next_p = get_Character_Loc(srcImage,Character);
 //cout<<"next_p:"<<1111<<endl;

 Point get_next = get_next_img_Loc(srcImage,next_p);

 int g_distance = get_distance(next_p,get_next);

 jump(g_distance);
 //cout<<"get_next_img_Loc:"<<get_next<<endl;
 circle(dstImage,get_next,8,Scalar(0,221,2));
 //imshow("test",dstImage);
 imwrite("Canny.png",dstImage);
 _sleep(1000);
 }
 return 0;
}

void get_screenshot()
{
 system("adb shell screencap -p /sdcard/autojump.png");
 system("adb pull /sdcard/autojump.png");
}

Point get_Character_Loc(Mat& srcImage,Mat& Tem_img)
{
 matchTemplate(srcImage,Tem_img,dstImage,CV_TM_SQDIFF);
 double minVal,maxVal;
 Point minLoc,maxLoc,matchLoc;
 minMaxLoc(dstImage,&minVal,&maxVal,&minLoc,&maxLoc,Mat());
 matchLoc = minLoc; //matchLoc是最佳匹配的区域左上角点
 cout<<"maxVal:"<<maxVal<<endl;
 rectangle(srcImage,Rect(matchLoc,Size(Character.cols,Character.rows)),Scalar(255,255,0),1,8,0);
 //Canny(srcImage,srcImage,1,10);
 putText(srcImage,"Wang",Point(matchLoc.x+Character.cols*0.5,matchLoc.y+Character.rows),1,2,Scalar(0,0,255));//画出Character小人的坐标
 return Point(matchLoc.x+Character.cols*0.5,matchLoc.y+Character.rows);
}

Point get_next_img_Loc(Mat& srcImage,Point& Character_Loc)
{
 cout<<"get_next_img_Loc"<<endl;
 cvtColor(srcImage,srcImage,CV_BGR2GRAY);
 GaussianBlur(srcImage,srcImage,Size(3,3),0);
 Canny(srcImage,srcImage,3,8);
 char AA[30];
 sprintf(AA,"get_next_img_Loc_%d.png",i);
 cout<<AA<<endl;
 imwrite(AA,srcImage);
 i++;
 //imshow("get",srcImage);
 cout<<"Character_Loc.x:"<<Character_Loc.x<<endl;
 if(Character_Loc.x < 540)
 {
  for(int j = int(srcImage.rows*0.2);j<int(srcImage.rows*0.8);j++)
  {
   uchar* data = srcImage.ptr<uchar>(j);
   for(int i = 1079;i > 540 ;i--)
   {    
    if(data[i] == 255)
    {
     return Point(i,j);
     //cout<<"Point:"<<Point(i,j)<<endl;
    }
   }
  }
 }
 else
 {
  for(int j = int(srcImage.rows*0.2);j<int(srcImage.rows*0.8);j++)
  {
   uchar* data = srcImage.ptr<uchar>(j);
   for(int i = 0;i<540;i++)
   {
    if(data[i] == 255)
     return Point(i,j);
   }
  }
 }
 return Character_Loc;
}

int get_distance(Point& first_point,Point& next_point)
{
 int A = first_point.x - next_point.x;
 int B = first_point.y - (next_point.y+50);
 return int(pow(pow(A,2)+pow(B,2),0.5));
}

void jump(int&g_distance)
{
 char AA[50];
 int distance_ = g_distance * 1.35;
 int rand_x = int(320+rand()%50); //加上随机数使得每次按压都是在点(320,410)-(370,460)之间
 int rand_y = int(410+rand()%50);
 sprintf(AA,"adb shell input swipe %d %d %d %d %d",rand_x,rand_y,rand_x,rand_y,distance_);
 cout<<AA<<endl;
 system(AA);
}

通过测试效果如下:轻松得榜首,到五百多时程序依然可以一直在运行,我觉得时间太长,所以就直接弄挂了。不过并不影响榜首的位置!上图:

总结:主要本人刚好也是视觉图像方向的,哈哈,就闲的无聊测试了一把,经过更改和测试。如果不遇到那种与背景色特别相近的,上榜首是没问题的! 嗯,说了这么多,这个博客也就到此结束啦,有问题欢迎留言!

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

相关文章

  • C++模拟实现vector流程详解

    C++模拟实现vector流程详解

    这篇文章主要介绍了C++容器Vector的模拟实现,Vector是一个能够存放任意类型的动态数组,有点类似数组,是一个连续地址空间,下文更多详细内容的介绍,需要的小伙伴可以参考一下
    2022-08-08
  • C++如何使用new来初始化指向类的指针

    C++如何使用new来初始化指向类的指针

    这篇文章主要介绍了C++如何使用new来初始化指向类的指针问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-07-07
  • 利用C语言编辑画图程序的实现方法(推荐)

    利用C语言编辑画图程序的实现方法(推荐)

    下面小编就为大家带来一篇利用C语言编辑画图程序的实现方法(推荐)。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-06-06
  • 详解C++中的万能头文件

    详解C++中的万能头文件

    C++万能头文件它是一个包含了每一个标准库的头文件,接下来通过本文给大家介绍C++中的万能头文件及优缺点,需要的朋友可以参考下
    2023-02-02
  • C++中volatile和mutable关键字用法详解

    C++中volatile和mutable关键字用法详解

    这篇文章主要介绍了C++中volatile和mutable关键字用法详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-02-02
  • 关于C语言动态内存管理介绍

    关于C语言动态内存管理介绍

    大家好,本篇文章主要讲的是关于C语言动态内存管理介绍,感兴趣的同学赶快来看一看吧,对你有帮助的话记得收藏一下
    2022-01-01
  • C语言判断一个数是否是2的幂次方或4的幂次方

    C语言判断一个数是否是2的幂次方或4的幂次方

    本文中我们来看一下如何用C语言判断一个数是否是2的幂次方或4的幂次方的方法,并且判断出来是多少次方,需要的朋友可以参考下
    2016-06-06
  • C++多线程编程和同步机制实例演示

    C++多线程编程和同步机制实例演示

    C++中的多线程编程和同步机制使得程序员可以利用计算机的多核心来提高程序的运行效率和性能,本文将介绍多线程编程和同步机制的基本概念和使用方法
    2023-09-09
  • 简单介绍C++中变量的引用

    简单介绍C++中变量的引用

    这篇文章主要简单介绍了C++中变量的引用,是C++入门学习中的基础知识,需要的朋友可以参考下
    2015-09-09
  • C++你最好不要做的几点小结

    C++你最好不要做的几点小结

    整理如下,主要是方便刚开始接触c++的朋友
    2013-01-01

最新评论