需求:当我在看视频学习的时候,需要屏幕指定区域的内容保存起来,采用常见的XX截图软件,你需要选择区域选择路径保存,把文件命名为有意义的名称,效率极其低下。作为一名计算机专业人员强调思考能力、动手能力和内功修炼层级,所以这点事情还是很简单的。

软件界面

  • 项目整体介绍
  • 配置文件之Json解析与保存
  • 屏幕取点之Hook实现
  • Qt 右下角弹窗之最简实现
  • 百度 OCR 之 Post 请求
    • Python 获取 access_token
    • Python Post 获取识别结果
    • Qt 实现 Post 获取识别结果
  • 解决 Qt之https传输问题
  • 思考
  • 加好友 & 工程下载
  • 下一篇文章预告

项目整体介绍

assist : 主界面,主要包含交互逻辑,多屏支持。
uiservant: 为界面提供辅助函数,其它逻辑处理
winhook: 设置键盘鼠标钩子,取点使用
network: 百度OCR API请求
采用集成工具QtCreator IDE设计师直接布局就OK了,Qt布局功能真心强大。

配置文件之Json解析与保存

Qt主要有 QJsonObject,QJsonArray,QJsonParseError, QJsonDocument 实现Json解析与格式化以及保存功能,采用组合的结构性模式。

[{"automatic_recognition_name_area": "360 184 220 30","screenshot_doc_folder": "D:/CommonUser/Documents/","screenshot_picture_area": "360 150 1140 810","screenshot_picture_prefix_name": "线性代数","subject": "可汗学院_线性代数"},{"automatic_recognition_name_area": "12 27 450 40","screenshot_doc_folder": "D:/CommonUser/Documents","screenshot_picture_area": "00 0 120 200","screenshot_picture_prefix_name": "机器学习","subject": "哈弗公开课_机器学习"}
]

对应 Json解析代码

QString Assist::loadConf()
{QString key;QJsonParseError err;QByteArray data;QJsonObject obj;QJsonObject::iterator it;QString OK = m_uiservant.fileReadAll(m_uiservant.getMapString("conf_file_path"), data);if(!m_uiservant.isOK(OK)){return OK;}QJsonDocument doc = QJsonDocument::fromJson(data,&err);if(err.error != QJsonParseError::NoError){return "parse json error!";}if (!doc.isArray()){return "assist_conf.json error format";}QJsonArray ary = doc.array();for(int i=0;i< ary.size();++i){stConf conf;obj = ary.at(i).toObject();key = "subject";if((it = obj.find(key))==obj.end()){continue;}conf.qstrSubject = it.value().toString();key = "screenshot_picture_prefix_name";if((it = obj.find(key))==obj.end()){continue;}conf.qstrPicName = it.value().toString();// 其它实现...m_lsConf.push_back(conf);}return m_uiservant.SUCCEEDED_STRING;
}

Json 保存

QString Assist::saveConf()
{QString qstrFilePath = m_uiservant.getMapString("conf_file_path");QJsonObject obj;QJsonDocument doc;QJsonArray ary;for(QList<stConf>::iterator it = m_lsConf.begin(); it!=m_lsConf.end(); ++it){obj.insert("subject", it->qstrSubject);obj.insert("screenshot_doc_folder", it->qstrDocFolder);obj.insert("screenshot_picture_prefix_name", it->qstrPicName);obj.insert("automatic_recognition_name_area", it->qstrPicNameArea);obj.insert("screenshot_picture_area", it->qstrScrShotArea);ary.append(obj);obj = QJsonObject();}doc.setArray(ary);QString ret = m_uiservant.fileWrite(qstrFilePath, doc.toJson());if(!m_uiservant.isOK(ret)){return ret;}return m_uiservant.SUCCEEDED_STRING;
}

屏幕取点之Hook实现

之前做过一个自动化工具,录制屏幕取点采用C#实现,生成自定义脚本文件,获取当鼠标处于停在某处时,按下 Alt 键就生成点坐标。现在由于交互比较简单,采用比较三种交互方式,鼠标左键录制x,y坐标,右键录制w,h, 中间键停止录制。
怎么实现HOOK,参考非常棒的一篇文章:QT中安装不使用dll的全局钩子
采用Windows底层API, SetWindowsHookEx 实现,具体实现参照工程源码。

以下为获取点之后

HHOOK WinHook::keyHook=NULL;
HHOOK WinHook::mouseHook=NULL;
QWidget* WinHook::m_pWidget = NULL;LRESULT CALLBACK keyProc(int,WPARAM,LPARAM lParam )
{KBDLLHOOKSTRUCT *pkbhs = (KBDLLHOOKSTRUCT *) lParam;if(pkbhs->vkCode==VK_F12){WinHook::unHook();}return 0;
}LRESULT CALLBACK mouseProc(int nCode, WPARAM wParam,LPARAM lParam)
{if (nCode == HC_ACTION){LPMOUSEHOOKSTRUCT p = (MOUSEHOOKSTRUCT*)lParam;((Assist*)WinHook::m_pWidget)->acceptPoint(wParam, p->pt.x, p->pt.y);}return 0;
}void WinHook::setHook(QWidget* widget)
{m_pWidget = widget;keyHook =SetWindowsHookEx( WH_KEYBOARD_LL,keyProc,GetModuleHandle(NULL),0);mouseHook =SetWindowsHookEx( WH_MOUSE_LL,mouseProc,GetModuleHandle(NULL),0);
}
void WinHook::unHook()
{UnhookWindowsHookEx(keyHook);UnhookWindowsHookEx(mouseHook);keyHook = NULL;mouseHook = NULL;m_pWidget = NULL;
}

Qt 右下角弹窗之最简实现

当处于全屏时,需要提示采用保证是否成功,否则没有成功截图不是白忙活了吗?

    label = new QLabel;label->setWindowFlags(Qt::FramelessWindowHint|Qt::Popup);label->adjustSize();label->setWordWrap(true);label->setAlignment(Qt::AlignCenter);

注意此处 setWindowFlags Qt::FramelessWindowHint|Qt::Popup,无边框,Qt::Popup 保证全屏下不会被遮挡,这一点很重要!

void Assist::showTips(QString tips, bool bStatusShow, int stayLong)
{if(bStatusShow){ui->status_label->setText(tips);}label->setText(tips);QRect rect = m_uiservant.getScreenRect();label->setMaximumWidth(200);label->setMaximumHeight(100);label->setMinimumWidth(200);label->setMinimumHeight(100);QFont font;font.setPointSize(12);label->setFont(font);label->setStyleSheet(QLatin1String("color:red;"));label->setGeometry(int(rect.width()-label->width()), int((rect.height()-label->height()-50)), label->width(), label->height());label->show();QTimer::singleShot(stayLong, this, SLOT(slotHideFinishedLabel()));
}void Assist::slotHideFinishedLabel()
{label->hide();
}

设置位置,采用计时器实现,是不是很简单呢?

百度 OCR 之 Post 请求

Qt浏览器采用Chorm内核,对于网络请求自然不在话下,只不过Qt4与Qt5的迁移变化比较大,还是很痛苦的!前同事为了业务需要,竟然在一个软件里面插入两个Qt浏览器,真挺厉害的!

吐槽一下百度的官方API文档,请求与返回的字段有些出入,有些吐血。第一次使用它,感觉没有阿里/讯飞提供的服务体验棒。不过百度的 OCR 速度还可以,之前采用打码兔平台API(额,最近打码兔平台即将关闭了,辛亏只充5元人民币)

在获取图片文字主要做了三件事:

  1. 注册百度开发者账号,注册应用
  2. 获取上传图片需要的 access_token
  3. 上传Base64+urlencode编码之后的图片。

在第3步操作上花了好几个小时折腾,终于看清并理解含义。

图像数据,base64编码后进行urlencode,
要求base64编码和urlencode后大小不超过4M,
最短边至少15px,最长边最大4096px,
支持jpg/png/bmp格式,当image字段存在时url字段失效

为什么需要 base64编码之后还要进行 urlencode

Base64编码 使用的字符:
大小写字母各26个,
加上10个数字,
加号“+”,斜杠“/”,
一共64个字符,
等号=用来作为后缀用途。
其中的+, /, = 都是需要urlencode的,所以无法取代。

采用 python编码只需要几行代码就实现了

Python 获取 access_token

from urllib import parse,request
import sslhost = 'https://aip.baidubce.com/oauth/2.0/token?grant_type=client_credentials&client_id=Bjm0X1hsLxrxsyA3hyuSUuke&client_secret=P6CBRGWnmTUSOboM0Dao5ZUI51SW8ODE'
req = request.Request(host,headers={'Content-Type':'application/json; charset=UTF-8'})
res = request.urlopen(req)
res = res.read()
print(res)

Python Post 获取识别结果

from urllib import parse,request
import ssl
import base64
host = 'https://aip.baidubce.com/rest/2.0/ocr/v1/general_basic/token?access_token=24.ae2a4c83a7a4778a2d12395b62b68099.2592000.1529261360.282335-11263768'
with open(r"D:\CommonUser\Documents\BookCode\QT\Test\screen_assist\ss.png", 'rb') as f:data = base64.b64encode(f.read())
textmod={'image': data,}
textmod = parse.urlencode(textmod).encode(encoding='utf-8')
req = request.Request(host,headers={'Content-Type':'application/x-www-form-urlencoded'},data=textmod,)
res = request.urlopen(req)
res = res.read()
print(res)

是不是很简答?此处使用我在百度注册的Id,请试一试就好,不然我不高兴就撤销这个应用。

Qt 实现 Post 获取识别结果

OK,试着用Qt实现 Post 请求,实现第三步的功能:

EMRequestTypeFlags NetWorker::fetchPictureOCR(QString access_token,QByteArray base64_img,QString language_type,QString detect_direction,QString detect_language,QString probability)
{QNetworkRequest request;QUrl url("https://aip.baidubce.com/rest/2.0/ocr/v1/general_basic");QUrlQuery query;query.addQueryItem("access_token",access_token);url.setQuery(query);request.setUrl(url);request.setRawHeader(QByteArray("Content-Type"), QByteArray("application/x-www-form-urlencoded"));base64_img = base64_img.toPercentEncoding();QByteArray postData;postData.append(QString("image=").toLatin1()+base64_img);postData.append(QString("&language_type="+language_type).toLatin1());postData.append(QString("&detect_direction="+detect_direction).toLatin1());postData.append(QString("&detect_language="+detect_language).toLatin1());postData.append(QString("&probability="+probability).toLatin1());QNetworkReply* reply = mNetmanager->post(request,postData);reply->ignoreSslErrors();connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(slotError(QNetworkReply::NetworkError)));connect(reply, SIGNAL(sslErrors(QList<QSslError>)), this, SLOT(slotSslErrors(QList<QSslError>)));mRequest[reply] = emRequestAccessOCR;return mRequest[reply];
}

application/x-www-form-urlencoded 格式是一种非常通用数据传输格式,关键字=值&关键字=值 的形式传输数据。

实现base64的urlencod很简单,base64_img.toPercentEncoding(); 关键是一定要理解。

解决 Qt之https传输问题

https和ssl协议广泛应用,Qt并没有直接去实现这些协议,但是内部具有支持调用协议的接口,没有 libeay32.dllssleay32.dll 会爆出一大堆警告,百度API里面明确支持 https 协议,必须要有这两个文件。在本地一搜索,一大堆软件包含这两个dll,比如:QQ,WeChat, IQIYI… 等都含有。我直接采用 WeChat的这两个文件不好使,找到了一篇文章,请参照下载并放在应用程序所在目录。

思考

我一直使用Qt,主要是Qt支持跨平台,安卓,IOS,MAC, Linux, Window, WinCE,车载操作系统 …,而且还和Python完美融合, 具有一些 Python 的影子,事实上现代标准 C++ 也在向 Python学习,不过它花哨的语法,让我有些不爽。

亮点一:我尝试在C++ 中融入脚本的思考,采用典型的词典代替其它变量声明:

void setMapString(QString qstrKey, QString qstrValue);
QString getMapString(QString qstrKey, QString qstrDefaultValue="");

我不希望一个类里面充满了大量的变量声明,统统塞入map里面,整个类就瘦了,干净很多。

亮点二 :代码分层,那些以简单为由,直接把逻辑与界面揉在一起的开发指导人员是在误导他人。

一个看似很简单的软件,其实是花了好几天来完成,做一件事情,不急不躁,坚持做完,你就胜利了。

加好友 & 工程下载

下一篇文章预告

当我看到旋转的风车,走动的唐老鸭,米老鼠,我就在想他们只不过是绘画出来的,我怎么能根据一幅画实现线条拆离以及动画的重组? 那么,你有更好的思路吗?欢迎加好友讨论 。

Qt5实现可配置截图及基于百度OCR自动识别标题保存文件相关推荐

  1. Python基于百度OCR的疫情防控截图自动分析检查

    通过腾讯文档收集人员信息,下载后,使用Python基于百度OCR对填报的疫情防控截图信息进行识别和统计分析,5分钟搞定每天人工1小时的检查工作量,提高效率,还提高准确率. 前言 疫情期间,各地.各单位 ...

  2. 基于百度OCR的网站验证码在线识别

    0.问题: 动态识别网站验证码以便后续操作 1.思路: 1.1.获取验证码图片 1.2.使用百度OCR接口在线识别验证码 2.实现: 2.1.获取验证码图片 2.1.1使用webdriver模拟浏览器 ...

  3. python从入门到放弃表情图-[python从入门到放弃]基于百度OCR的文字识别

    先申请百度OCR使用,百度OCR使用文档说明: https://cloud.baidu.com/doc/OCR/s/Rjwvxzm3n.按照文档安装百度aip库,命令行输入魔法如下:pip insta ...

  4. Android 图片文字识别DEMO(基于百度OCR)

    前言   OCR 是 Optical Character Recognition 的缩写,翻译为光学字符识别,指的是针对印刷体字符,采用光学的方式将纸质文档中的文字转换成为黑白点阵的图像文件,通过识别 ...

  5. python 百度ocr识别_Python使用百度Ocr识别文字保存CSV

    1.准备: 1)Python开发环境, 笔者用的是3.7; 工具用的是Pycharm 2)百度云后台创建文字识别的应用, 获取AppID, API key, Secret Key 百度云后台创建文字识 ...

  6. 日语截图翻译软件(百度ocr+python3+pyqt5)

    1.引言: 网上有很多的ocr识别图片转文字再翻译的软件.但是没有翻译日语的.于是想自己做一个对含有日语的图片进行识别并翻译为中文的小工具.这里提一下,如果看这篇文章的人只是希望找个选中文本并翻译的软 ...

  7. 百度OCR“技术+产品+应用”领先业界 为全行业企业开启“降本增效”快速通道

    OCR(文字识别)技术是最早应用于企业降本增效的 AI 方向之一,如今已逐渐下沉为企业智能化升级的一项重要基础设施能力.10月29日,百度智能云线上线下同期举办了TechDay OCR技术创新沙龙,深 ...

  8. php验证码百度ocr识别,利用百度OCR实现验证码自动识别

    在爬取网站的时候都遇到过验证码,那么我们有什么方法让程序自动的识别验证码呢?其实网上已有很多打码平台,但是这些都是需要money.但对于仅仅爬取点数据而接入打码平台实属浪费.所以百度免费ocr正好可以 ...

  9. python 百度ai批量识别_Python基于百度AI的文字识别的示例

    Python基于百度AI的文字识别的示例 使用百度AI的文字识别库,做出的调用示例,其中filePath是图片的路径,可以自行传入一张带有文字的图片,进行识别. 下载baidu-aip这个库,可以直接 ...

最新文章

  1. 批处理作业调度-回溯法
  2. clion 格式化代码 设置空行 最多保留一行
  3. Hinge Loss
  4. (chap4 IP协议) IPV6(IP version 6)
  5. 数据存储之 SQLite 数据库操作(一)
  6. c盘java文件误删_java获取C盘下的隐藏目录文件名称
  7. c#中的long类型示例_C#中带示例的带符号字节数组
  8. off cpu linux,宋宝华: 用off-cpu火焰图进行Linux性能分析
  9. 机器学习系列手记(六):概率图模型之概率图模型的联合概率分布
  10. ModelArts解压OBS上压缩包
  11. 【软件测试】你最常用的web测试-浏览器兼容性测试
  12. Qt 获取当前屏幕分辨率
  13. unity详细解决visualstudio未能找到类型或命明空间名问题
  14. 超简单集成HMS Scan Kit扫码SDK,轻松实现扫码购
  15. 推荐系统中的选择偏差及处理
  16. python怎么求商_如何用python求差商?
  17. batocera 完整包_Batocera Plus 2.0 中文整合版bt下载 8G和150G
  18. c语言for循环多条件判断,解决在for循环内判断条件多次执行
  19. MACD+波动率过滤+追踪止损 期货择时汇总
  20. 滴答清单 TickTick for Mac(待办事项清单)

热门文章

  1. 牛客网-腾讯编程校招真题 编码 Java
  2. JS-对象,包装类--渡一教育(视频笔记)
  3. Pytorch的grad、backward()、zero_grad()
  4. 深度 | 5分钟读懂阿里零售通智慧供应链平台
  5. 在sublime中插入图片
  6. 关于ITIL证书更新的重要通知
  7. 上海出差之行--领略外滩美景、RT-Thread总部之旅、嵌友面基、返程记录
  8. 天梭手表Tissot手表更换电池的方法
  9. [BZOJ1513]Tet-Tetris 3D
  10. 如何将SNS光纤交换机(OEM博科FC交换机)恢复为出厂设置