zoukankan      html  css  js  c++  java
  • 【程序员的吃鸡大法】利用OCR文字识别+百度算法搜索,玩转冲顶大会、百万英雄、芝士超人等答题赢奖金游戏

    【先上一张效果图】:

    一、原理:

    其实原理很简单:

    1.手机投屏到电脑;

    2.截取投屏画面的题目部分,进行识别,得到题目和三个答案;

    3.将答案按照一定的算法,进行搜索,得出推荐答案;

    4.添加了一些其他辅助功能,比如:浏览器搜索结果展示、关键字高亮、浏览器可点击等;

    二、二营长,把我的意大利...............代码,呈上来,给友军看看

    1.手机投屏:

        方式很多,这里只列举几个比较常用、且自己感觉简单易用的:

        A.IOS:局域网内,可以利用iTools里的苹果录屏大师(airplay),进行投屏;

        B.安卓:利用连接线,可以用Totall Control,将安卓手机的画面投到电脑上;而且电脑上还能直接操作手机;

        C.模拟器:一般都是安卓模拟器;可以自行下载并安装;

    2.截取画面中的题目和答案

        A.先设置要截图的区域。

        我创建了一个窗体,专门用于设置截图区域,给它取名叫:frmCutter。

        原理:在主窗体打开frmCutter时,就将frmCutter全拼显示。同时截取一张整个屏幕的图片,把它设置成frmCutter窗体的背景图片。

    这样就能在frmCutter上自由地设置了。

        主窗体打开frmCutter窗体时:

     1 // 新建一个和屏幕大小相同的图片
     2 Bitmap catchBmp = new Bitmap(Screen.AllScreens[0].Bounds.Width, Screen.AllScreens[0].Bounds.Height);
     3 
     4 // 创建一个画板,让我们可以在画板上画图
     5 // 这个画板也就是和屏幕大小一样大的图片
     6 // 我们可以通过Graphics这个类在这个空白图片上画图
     7 Graphics g = Graphics.FromImage(catchBmp);
     8 
     9 // 把屏幕图片拷贝到我们创建的空白图片 catchBmp中
    10 g.CopyFromScreen(new Point(0, 0), new Point(0, 0), new Size(Screen.AllScreens[0].Bounds.Width, Screen.AllScreens[0].Bounds.Height));
    11 
    12 // 创建截图窗体
    13 frmCutter _frmCutter = new frmCutter();
    14 _frmCutter.Tag = this;
    15 
    16 // 指示窗体的背景图片为屏幕图片
    17 _frmCutter.BackgroundImage = catchBmp;
    18 
    19 _frmCutter.Width = Screen.AllScreens[0].Bounds.Width;
    20 _frmCutter.Height = Screen.AllScreens[0].Bounds.Height;
    21 DialogResult dr = _frmCutter.ShowDialog();

        然后再frmCutter窗体中,写入几个事件:

      1 //点击鼠标右键时,取消设置
      2 private void frmCutter_MouseClick(object sender, MouseEventArgs e)
      3 {
      4     if (e.Button == MouseButtons.Right)
      5     {
      6         this.DialogResult = DialogResult.OK;
      7         this.Close();
      8     }
      9 }
     10 
     11 //点击鼠标左键时,开始画区域图
     12 private void frmCutter_MouseDown(object sender, MouseEventArgs e)
     13 {
     14     // 鼠标左键按下是开始画图,也就是截图
     15     if (e.Button == MouseButtons.Left)
     16     {
     17         // 如果捕捉没有开始
     18         if (!_catchStart && !_catchFinished)
     19         {
     20             _catchStart = true;
     21 
     22             // 保存此时鼠标按下坐标
     23             Point newPoint = new Point(e.X, e.Y);
     24 
     25             _downPoint = newPoint;
     26 
     27             Tools.StartPoint = newPoint;
     28         }
     29     }
     30 }
     31 
     32 //鼠标移动时,根据移动的鼠标和点击时的第一个点,绘制矩形
     33 private void frmCutter_MouseMove(object sender, MouseEventArgs e)
     34 {
     35     #region 确保截图开始
     36     if (_catchStart && !_catchFinished)
     37     {
     38         // 新建一个图片对象,让它与屏幕图片相同
     39         Bitmap copyBmp = (Bitmap)Tools.ScreenShots.Clone();
     40 
     41         // 获取鼠标按下的坐标
     42         Point newPoint = new Point(_downPoint.X, _downPoint.Y);
     43 
     44         // 新建画板和画笔
     45         Graphics g = Graphics.FromImage(copyBmp);
     46         Pen p = new Pen(Color.Red, 1);
     47 
     48         // 获取矩形的长宽
     49         int width = Math.Abs(e.X - _downPoint.X);
     50         int height = Math.Abs(e.Y - _downPoint.Y);
     51         if (e.X < _downPoint.X)
     52         {
     53             newPoint.X = e.X;
     54         }
     55         if (e.Y < _downPoint.Y)
     56         {
     57             newPoint.Y = e.Y;
     58         }
     59 
     60         _catchRectangle = new Rectangle(newPoint, new Size(width, height));
     61 
     62         Tools.CatchRectangle = new Rectangle(newPoint, new Size(width, height));
     63         Tools.CatchRectangleSize = new Size(width, height);
     64 
     65 
     66         // 将矩形画在画板上
     67         g.DrawRectangle(p, _catchRectangle);
     68 
     69         // 释放目前的画板
     70         g.Dispose();
     71         p.Dispose();
     72         // 从当前窗体创建新的画板
     73         Graphics g1 = this.CreateGraphics();
     74 
     75         // 将刚才所画的图片画到截图窗体上
     76         // 为什么不直接在当前窗体画图呢?
     77         // 如果自己解决将矩形画在窗体上,会造成图片抖动并且有无数个矩形
     78         // 这样实现也属于二次缓冲技术
     79         g1.DrawImage(copyBmp, new Point(0, 0));
     80         g1.Dispose();
     81         // 释放拷贝图片,防止内存被大量消耗
     82         copyBmp.Dispose();
     83     }
     84     #endregion
     85 }
     86 
     87 //鼠标点击后,弹起来时,完成矩形的绘制
     88 private void frmCutter_MouseUp(object sender, MouseEventArgs e)
     89 {
     90     if (e.Button == MouseButtons.Left)
     91     {
     92         // 如果截图已经开始,鼠标左键弹起设置截图完成
     93         if (_catchStart)
     94         {
     95             Tools.EndPoint = new Point(e.X, e.Y);
     96 
     97             _catchStart = false;
     98             _catchFinished = true;
     99         }
    100     }
    101 }
    102 
    103 //双击,确定当前选择的设置
    104 private void frmCutter_MouseDoubleClick(object sender, MouseEventArgs e)
    105 {
    106     if (e.Button == MouseButtons.Left && _catchFinished)
    107     {
    108         if (this.Tag != null)
    109         {
    110             frmMain _frmMain = (frmMain)this.Tag;
    111             if (_frmMain != null)
    112             {
    113                 //_frmMain.btnRead.Focus();
    114                 _frmMain.ReadImageResult();
    115             }
    116         }
    117 
    118         this.DialogResult = DialogResult.OK;
    119         this.Close();
    120     }
    121 }

        B.设置好截图区域后,每次题目出现时,变对该区域截图:

     1 //截取设置的区域屏幕图片
     2 Bitmap _screenShots = new Bitmap(Screen.AllScreens[0].Bounds.Width, Screen.AllScreens[0].Bounds.Height);
     3 // 创建一个画板,让我们可以在画板上画图
     4 // 这个画板也就是和屏幕大小一样大的图片
     5 // 我们可以通过Graphics这个类在这个空白图片上画图
     6 Graphics g_screenShots = Graphics.FromImage(_screenShots);
     7 // 把屏幕图片拷贝到我们创建的空白图片 CatchBmp中
     8 g_screenShots.CopyFromScreen(new Point(0, 0), new Point(0, 0), new Size(Screen.AllScreens[0].Bounds.Width, 
      Screen.AllScreens[0].Bounds.Height)); 9 10 //剪切的图片 11 _catchBmp = new Bitmap(Tools.CatchRectangleSize.Width, Tools.CatchRectangleSize.Height); 12 Graphics g = Graphics.FromImage(_catchBmp); 13 g.DrawImage(_screenShots, new Rectangle(0, 0, Tools.CatchRectangleSize.Width, Tools.CatchRectangleSize.Height),
      Tools.CatchRectangle, GraphicsUnit.Pixel);
    14 g.Dispose(); 15 g_screenShots.Dispose(); 16 17 //显示图像 18 this.imgCut.BackgroundImage = (Image)_catchBmp;

        C.将截到的问题和答案图片,用OCR识别

        比如,我现在设置并截取到了这张图片:

        

        识别图片中的文字,OCR软件和API也不少。以前我用的谷歌tesseract4.0,安装在本机的,没做词库,识别率一般。

    后来发现百度OCR每天免费调用500次,果断转场!事实证明,正确率还是高很多。

        D.得到识别结果,将识别结果处理后,进行百度搜索:

        创建了一个试题实体,后面用起来就方便了:

     1 /// <summary>
     2 /// 试题类
     3 /// </summary>
     4 public class QuestionModel
     5 {
     6     /// <summary>
     7     /// 问题
     8     /// </summary>
     9     public string Question { get; set; }
    10 
    11     /// <summary>
    12     /// 答案1
    13     /// </summary>
    14     public string Answer1 { get; set; }
    15 
    16     /// <summary>
    17     /// 答案2
    18     /// </summary>
    19     public string Answer2 { get; set; }
    20 
    21     /// <summary>
    22     /// 答案3
    23     /// </summary>
    24     public string Answer3 { get; set; }
    25 }

        E.百度搜索,并显示参考答案:

        a).算法搜索:

        1.用题目去百度搜索。在搜索的结果中,查询答案出现的次数。

        2.用题目+答案去搜索。得到每个组合的百度结果个数。

        然后将上述两种方法,根据权重权衡,用户可以自行决定偏向于哪种结果。

        b).辅助搜索:

        右边还放了一个浏览器,可以在得到识别结果的第一时间,呈现出根据题目搜索百度的结果;并且在里面高亮显示3个答案关键字。

    三、坐等吃鸡!

        自动截图、自动识别、自动搜索、自动给出参考答案、自动展现出搜索页面并高亮显示关键字……

        多了一系列的辅助功能,想不吃鸡都难啊~

    (PS:热烈欢迎广大道友一起交流、指点,大家一起更上一层楼!)

    2018.01.25.

    下面给大家推荐两个小福利:

      1. 支付宝领红包,每天都能领取最高99元。领取的红包在支付时可以抵扣现金!
      2. 一款覆盖淘宝、天猫全场商品95%的内部优惠券搜索神器。 
        扫描二维码下载APP后,输入激活码:code888,即可自用省钱 + 分享赚钱!最高帮您节省90%的购物资金!
      3.           
  • 相关阅读:
    泛型系列<9>:使用相应的泛型版本替换Hashtable
    泛型系列<2> 创建泛型类
    泛型系列<5>:链表的实现
    泛型系列<4>使用相应的泛型版本替换Stack和Queue
    泛型系列<8>:使用泛型创建只读集合
    Visual Studio统计有效代码行数
    C++11 现代C++风格的新元素(转)
    神秘海域:顶级工作室“顽皮狗”成长史(中)
    沸腾十五年TX
    为你解惑之WPF经典9问详解
  • 原文地址:https://www.cnblogs.com/donkeysmall/p/8319792.html
Copyright © 2011-2022 走看看