以下是原帖,开发过程,感兴趣的朋友不妨看看
前言
我们不生产代码,我们只是代码的搬运工。
开发这个工具是因为工作中遇到需要用到OCR的场景。
那么问题来了:
-
Q:网上有 天若OCR、PandaOCR 等很多优秀的工具,为什么还要自己开发一个呢?
-
A:个人认为功能太杂了,有很多功能是不需要用到的,而且工具太大还影响了运行效率。
-
Q:为什么是搬运呢?
-
A:刚毕业的时候就做过两年的搬运工,深知改别人的代码是多么的痛苦,既然自己要的功能比较简单,而且自己也跃跃欲试想开发一个,就开始了搬运之旅。另外 天若 OCR V5.0.0开源版 在我的电脑上打开报出了几十个错误,对于几年没碰代码的我来说根本解决不了。QAQ
1 成品展示
先上对比图
左边是刚开始做时的界面,成品界面搬运的是 天若,毕竟是经过很多人验证的界面。
界面展示
然后是功能展示
拖放/浏览文件识别:
拖放识别
截图识别:
截图识别
2 搬运过程
开发一个软件的过程大概分几步:问题出现 -> 方案制定 -> 功能实现 -> 功能完善 -> 优化代码、界面 -> 问题解决。
完成后要增加功能的步骤同上。
2.1 怎么实现文字识别
方案:使用OCR接口,这里我采用了 百度的通用文字识别接口
查看百度的技术文档,其中有一条
access_token
文字识别接口需要参数access_token
,而这个token需要访问百度的 鉴权认证机制接口 才能获取,这都还没开始就遇到问题了,接口什么的都不会,怎么获取啊?!
还好我还在软件行业里面工作,有几个备选方案:
1) 先是用一位同事给我的 HTML+JS 测试访问一下接口,结果出现了跨域的问题,GG。
2) 然后用到了 Postman 工具来访问,成功。
3) 后来才发现,直接把 接口+参数 组成的链接,放到浏览器里面访问(GET),就直接出来了,被其他文档的要求混淆了,吐血。
get access token
2.2 准备好了就开始开发了
想法:先做图片文件识别,截图识别是下一步功能
方案:浏览文件 -> 按钮识别 -> 中间的文本框显示识别结果
于是得到了下图的界面
初始界面
识别接口对接不会写怎么办?
搬!!! 在百度的结束文档里面就有很多语言的demo,直接搬过来改一下token
,加上引用就行。
浏览文件功能不会做怎么办?
搬!!! 通过搜索我们知道,C#浏览文件需要用到 OpenFileDialog
控件
知道了什么控件能实现功能但不知道怎么用(写代码)怎么办?
搬!!! 继续搜索 OpenFileDialog 的用法。
于是第一个版本就出来了:
2.3 结果出来了,但是格式不对
方案:接口返回的,一般都是 json,那么就需要解析一下了
搬!!!
通过搜索,知道了用C#解析json,需要类库Newtonsoft.Json(下载地址 http://json.codeplex.com/)
然后继续搜索能用的demo,发现了这个博客: c#解析json字符串处理(最清晰易懂的方法)
因为返回的接口格式是这样的
{
"log_id": ,
"words_result_num": ,
"words_result": [
{
"words": ""
},
{
"words": ""
}]
}
于是百度给的demo 变成了这样:
返回的结果变成了这样:
json解析
2.4 截图功能
截图功能不会做怎么办?
搬!!!
这个功能花的时间是最长的,对于搬运工来说,重要的是搬运,搜索结果很多都在讲思路;
有些源码又太复杂,太复杂的代码就很难下手,最后找到了一个最合适的博客:截图小工具开发笔记,还包含源码。
这个源码主要有两个步骤,热键 + 截图,热键功能先不要。
面朝黄土背朝天地搬运完成后,截图功能get
截图功能
2.5 截图识别
有了截图功能后,就开始提炼了,把需要的代码留下,没有的删掉。
截图识别功能:截图完毕自动识别,那么调整选区大小、移动选区、保存为文件这些功能就不需要了。
通过搜索结果,得知截图功能的原理:
- 截取整个屏幕
- 把屏幕图像放到窗体Image中
- 绘制选区
- 把选区中的图片截取出来
那么需要把第4步去掉,修改第3步的代码,变成下面的步骤:
- 截取整个屏幕
- 把屏幕图像放到窗体Image中
- 绘制选区
- 绘制完成后直接把图片放到剪切板中
- 通过接口识别剪切板中图片的文字
截图完毕代码变成这样:
private void CutPic_MouseUp(object sender, MouseEventArgs e) // 鼠标松开
{
Cursor.Clip = Rectangle.Empty;
ToolsPanel.Visible = true;
this.Invalidate();
//复制图片到剪切板
Rectangle cropArea = new Rectangle(_SelectedRectangle.X, _SelectedRectangle.Y, _SelectedRectangle.Width, _SelectedRectangle.Height);
if (cropArea.Height > 0 && cropArea.Width > 0) // 宽度和高度必须大于零
{
Bitmap bmpImage = new Bitmap(this._Image);
Bitmap bmpCrop = bmpImage.Clone(cropArea, bmpImage.PixelFormat);
Clipboard.SetImage(bmpCrop);
}
this.DialogResult = DialogResult.OK;
this.Close();
}
截图按钮代码则变成这样:
private void button3_Click(object sender, EventArgs e)
{
this.Visible = false; // 截图时自动隐藏本窗体
System.Threading.Thread.Sleep(200); // 延时,避免把本窗体也截下来
ShowCutPic(); // 截图功能
if (Clipboard.ContainsImage()) // 判断剪切板是否存在图片
{
Image img = Clipboard.GetImage();
textBox1.Text = generalBasic("", img); // 识别剪切版中图片的文字
this.Visible = true;
}
else
{
this.Visible = true;
}
}
其中还搬运了 天若开源的代码,图片转 byte:ImgToBytes();以及对 getFileBase64() 函数做了修改。
截图识别功能完成:
截图识别功能
2.6 优化
功能已经实现了,下一步就是优化,优化过程没什么好说的。
砖已经在这里了,怎么盖房子、怎么盖得好看、怎么盖得稳固,就是考验搬运工的自我修养了。
下图是优化后 github 的提交历史:
github历史
搬运了天若的智能段落合并、界面,以及复制粘贴等小功能
优化界面花了不少时间,大部分都是在找图标(这里提一下阿里巴巴矢量图标库),踩了不少坑,期间各种搜索效果如何实现,控件的每个属性都看了好多遍。
2.7 设置界面
问题:现在的软件还是写死了 token 的,token 到期之后就用不了,不能去改代码这么麻烦吧
方案:把 token 写成 ini 配置,读取配置
不会写 ini 配置怎么办?
搬!!! 通过搜索得知,C#中要写 ini 配置需要用到"kernel32.dll"中的Win32API函数 WritePrivateProfileString()
和 GetPrivateProfileString()
在天若的源码中也有这部分代码,但我搬运的是网上的一篇博客:C#读写INI文件
设置界面只有两个设置,百度的 token、工具的截图热键,于是就有了下图
设置界面
热键功能是下一步要做的
之所以把 Access Token 也保存下来,是因为接口需要图片 base64 和 Access Token 两个参数就足够了
天若的识别代码似乎是识别之前就获取一遍 token,个人认为步骤越少越好
2.8 热键功能
其实热键这个功能可有可无,如果是频繁使用的,那热键是不二之选
热键不会写怎么办?
搬!!! 这个功能直接搬运了天若的代码,因为天若的代码已经是加工过成熟的代码。
其实是一步到位,因为这个功能有三步要搬运的,一是实现热键功能,二是输入框识别键盘功能,三是读取 ini 配置并注册热键功能
一名合格的搬运工,要识别出哪些砖是能用的、哪些砖是好的、哪些砖是自己能搬得动的
热键做好了之后,热键直接触发截图识别按钮对应的代码就行了
3 后记
工具做出来之后就想发出来的,无奈刚好要出差,就晚了半个月
做这个工具更多是因为自己想写写代码,可能是享受开发的过程,可能是享受解决问题的成就感,也可能是着以后继续走开发的道路
最后是成品和源码
版本已更新,请查看贴子顶部的下载连接
成品:https://wws.lanzouj.com/i5G9kg94ozi
源码:https://github.com/YongJunPan/jyocr
github 项目有更新表格识别,因为次数太少就没把成品放出来,感兴趣的朋友可以上去下载
如果喜欢这个贴子,顺手点一下免费评分吧