自制 Windows 小工具 ———— 文字识别助手
自制 Windows 小工具 ———— 文字识别助手
- 背景
- 问题分析
- 工具准备
- 第一部分:屏幕截图的实现
- 文字识别
- 结果展示
- 保持原格式
- 事件绑定
背景
使用电脑的时候经常遇到图片上满是文字,想复制却有心无力的情况。又或者浏览器不允许复制这样的恶心设置。
什么?你说微信,QQ都有这样的工具?难道你要为了一个简单的文字提取而专门登录这样的重器?又或者网络被小偷偷走了呢?
问题分析
其实这个功能能主要包括两个方面的内容
- 屏幕截图(选择要复制的内容)
- 文字识别
我们依次实现就好了
工具准备
- python(建议3.10.4,亲测这个版本匹配cnocr没有问题)
- cnocr (python 第三方库)
- pyautogui (python 第三方库)
python自己准备,这里不做多余的讲述。
pyautogui,cnocr直接pip install pyautogui
pip install cnocr
即可
一定要找一个有免费网络的地方,不要用手机流量哦,后面有重磅炸弹
第一次安装cnocr后,win + r
打开cmd
,运行python
然后输入from cnocr import CnOcr
,第一次他会下载文字识别包。
这里有个提示,如果网络中断了,那么下一次再打开,他就会报错。
解决方法也很简单,只需要根据报错信息的第1行(注意去掉最后的文件名)找到下载路径删除下载了一半的zip文件,然后再重新下载就好了
第一部分:屏幕截图的实现
屏幕截图的话,我们使用pyautogui.screenshot()
就好,可以传入左上角坐标和宽高控制区域
关键是获取用户选择的区域
一个可行的方法是用tkinter
创建透明窗口,让用户既可以看见桌面,我们也可以获取鼠标事件
因为要多次调用,方便起见,我们封装一个模块 Screencut.py
import tkinter as tk
import pyautogui
import time#鼠标左键按下
def button_1(event):global x, y ,xstart,ystartx, y = event.x, event.yxstart,ystart = event.x, event.yxstart,ystart = event.x, event.y cv.configure(height=1)cv.configure(width=1)cv.place(x=event.x, y=event.y)#鼠标左键按下并移动
def b1_Motion(event):global x, yx, y = event.x, event.yglobal cvcv.configure(height = event.y - ystart)cv.configure(width = event.x - xstart)#鼠标左键松开
def buttonRelease_1(event):global x, y,xstart,ystartx, y = event.x, event.yif x == xstart and y == ystart:returnglobal cvglobal rootPstart=[0,0]cv.place_forget()root.attributes("-alpha", 0) img = pyautogui.screenshot(region=[xstart,ystart,x-xstart,y-ystart]) # x,y,w,himg.save('screenshot.png')sys_out()# 退出
def sys_out(even = True):global root#from tkinter import messagebox#if messagebox.askokcancel('Exit','Confirm to exit?'):root.destroy()def GetPic():global rootroot = tk.Tk()root.overrideredirect(True) # 隐藏窗口的标题栏# root.attributes("-alpha", 0.3) # 窗口透明度70 %root.attributes("-alpha", 0.3) # 窗口透明度60 %root.attributes("-topmost", 1)#root.geometry("300x200+10+10") # 设置窗口大小与位置root.geometry("{0}x{1}+0+0".format(root.winfo_screenwidth(), root.winfo_screenheight()))root.configure(bg="black")# 再创建1个Canvas用于圈选global cv, x, y, xstart, ystartcv = tk.Canvas(root)x, y = 0, 0xstart,ystart = 0 ,0# 绑定事件到Esc键,当按下Esc键就会调用sys_out函数,弹出对话框root.bind('<Escape>',sys_out)root.bind("<Button-1>", button_1)root.bind("<B1-Motion>", b1_Motion)root.bind("<ButtonRelease-1>", buttonRelease_1)root.mainloop()
思路难度不大,按部就班的走就好,自行看代码理解,每次调用GetPic()
会弹出窗口让用户选择,并且将截好的图片保存在screenshot.png
中
文字识别
有了图片,下一步就是文字识别了。
模式很简单,传入screenshot.png
,返回一个识别结果的列表,不会使用cnocr的同学自行百度,也可以直接看代码,非常简单,因为是功能的主体,所以放到主程序中,就叫TextOCR.py
把
from cnocr import CnOcr
import screenshot # 自己封装的功能
def TextOCR(): ScreenCut.GetPic() # 首先调用GetPic获取截图ocr = CnOcr() # 调用识别工具result = ocr.ocr('screenshot.png') # 返回识别结果的列表print(result) # 输出
咦?怎么输出了一堆奇怪的数组
有python经验的你看出来了吗?我们需要手动提取这里的结果
但是别慌,后面还有重头戏,这个暂且放一放
结果展示
为了方便用户,我们还是用tkinter把它显示出来
还是先封装一个功能模块 ShowResult.py
import tkinter as tkdef show(text): # 给到每一行的文字列表,一行一行的显示到文本框root = tk.Tk()root.title('GWord')root.attributes("-topmost", 1) # 这里给到一个置顶,方便用户查看+txt_area = tk.Text(root,wrap="none") # 设置到文本框结尾不自动换行for i in range(len(text)):txt = text[i].strip("\n")txt_area.insert(tk.END,txt)if i != len(text) - 1:txt_area.insert(tk.END,"\n")txt_area.pack()root.mainloop()
保持原格式
这是这里头的最有技术含量,也是最值得研究的地方了。希望本文抛砖引玉,有想法的朋友可以评论与我讨论哦
注意到result
中除了'text'
属性,还有一个坐标数组表示这个文字的四角坐标,我们通过这个来保留原格式。
这里有个疑问请朋友们知道的个我留言哦:为什么两个左右相差很远的文字,他们的横坐标几乎是相同的呢?且有的时候相较于左右更近的文字,离的远的文字反而差值更小呢?
先忽略这个情况,我们默认左右顺序在返回的数组中已保持相对顺序(即在左边的原本的index也更靠前)
先让一个文字的x坐标为四个x坐标中的最小值(当然这个不影响),y坐标为四个坐标的平均值
然后我们对y坐标排序,先给定一个阈值,经测试 15 15 15是被较好的,我们用DES
保存这个数值,方便调整,然后排序,TextOCR.py
对刚才的代码进行了改善
from cnocr import CnOcr
import ScreenCut
import ShowResult
from functools import cmp_to_key
import osDES = 15def Data(res):px = 1e9py = 0for pos in res["position"]:px = min(px,pos[0])py += pos[1]py /= len(res["position"])return {"x":px,"y":py,"text":res["text"]}def cmp(a,b):global DESif abs(a["y"] - b["y"]) < DES:return 0return a["y"] - b["y"]def TextOCR():global DESScreenCut.GetPic()ocr = CnOcr()result = ocr.ocr('screenshot.png')text = []positionlist = []for i in range(len(result)):positionlist.append(Data(result[i]))positionlist.sort(key = cmp_to_key(cmp))if len(positionlist) != 0:text.append(positionlist[0]["text"])for i in range(1,len(positionlist)):if abs(positionlist[i]["y"] - positionlist[i - 1]["y"]) < DES: # 判断在同一行,追加到结尾text[-1] += " " + positionlist[i]["text"]else:text.append(positionlist[i]["text"])ShowResult.show(text)os.remove('screenshot.png') # 我们把使用完的照片删除掉,保护隐私
事件绑定
然后我们同过keyboard库来绑定鼠标事件(这里绑定ctrl + alt
貌似这是几个为数不多的没有被各大应用程序占领的快捷键,好不容易试出来的),还是在TextOCR.py
中
from cnocr import CnOcr
import ScreenCut
import ShowResult
import keyboard
from functools import cmp_to_key
import osDES = 15def Data(res):px = 1e9py = 0for pos in res["position"]:px = min(px,pos[0])py += pos[1]py /= len(res["position"])return {"x":px,"y":py,"text":res["text"]}def cmp(a,b):global DESif abs(a["y"] - b["y"]) < DES:return 0return a["y"] - b["y"]def TextOCR():global DESScreenCut.GetPic()ocr = CnOcr()result = ocr.ocr('screenshot.png')text = []positionlist = []for i in range(len(result)):positionlist.append(Data(result[i]))positionlist.sort(key = cmp_to_key(cmp))if len(positionlist) != 0:text.append(positionlist[0]["text"])for i in range(1,len(positionlist)):if abs(positionlist[i]["y"] - positionlist[i - 1]["y"]) < DES:text[-1] += " " + positionlist[i]["text"]else:text.append(positionlist[i]["text"])ShowResult.show(text)os.remove('screenshot.png')if __name__ == '__main__':keyboard.add_hotkey('alt+ctrl',TextOCR)keyboard.wait()
这里提出一个问题
有朋友知道cnocr怎么打包成exe,pyinstaller貌似不能把那个资源文件也打包进去,会出错
感谢评论区或私信回答
这里再补充一个问题(相当于一个提醒)
在复制窗口中的文字时一定要等到ctrl + c,然后到目标位置ctrl+v后再关闭窗口,不然其他程序会死机(死机后关闭这个程序,另外的死机窗口也好了)
有朋友知道问什么吗?
感谢评论区或私信回答
接下来给一张效果图
自制 Windows 小工具 ———— 文字识别助手相关推荐
- 自制 Windows 小工具 ———— 智能截屏工具
自制 Windows 小工具 ---- 智能截屏工具 背景 需求分析 环境准备 功能实现 获取截图区域 获取文件保存路径 图像算法 截屏 快捷启动 背景 上网课期间,很多同学(包括老师)都会选择(提倡 ...
- 自制python小工具(3)——Gadgets1.1
自制python小工具(3)--Gadgets 1.1 文章目录 自制python小工具(3)--Gadgets 1.1 1. 前言 2. 功能实现 2.1 主程序界面 2.1.1 标签与按钮 2.1 ...
- WinMount是一款国产免费且功能强大Windows小工具,具备压缩解压和虚拟光驱(CD/DVD)的双重功能...
http://cn.winmount.com/index.html WinMount是一款国产免费且功能强大Windows小工具,具备压缩解压和虚拟光驱(CD/DVD)的双重功能.最大特色在于压缩包虚 ...
- [分享] jQuery开发之windows边栏小工具开发(Gadget development)- windows小工具实现的公司内部分机查询工具...
作者:Terry li - GBin1.com 使用vista和win7的朋友可能都或多或少的使用过windows小工具,这些小工具可以被自由的添加到桌面上并且快速实现一定的功能,比如,天气预报,股票 ...
- 自制python小工具(2)——Gadgets 0.2
自制python小工具(2)--Gadgets 0.2 文章目录 自制python小工具(2)--Gadgets 0.2 1. 前言 1.1 上篇 2. Gadgets 0.2更新功能介绍 3. Ga ...
- 优秀公众号推荐 STM32与FPGA资料整理 windows小工具推荐
文章目录 学习公众号推荐(无广告,良心推荐) 1.工具类 1.网罗灯下黑 2.平凡而诗意(这个老哥应该是弄深度学习的,整理的资料挺不错的,下面也还会推荐一次~) 3.Topbook 2.硬件类 1.吴 ...
- Python——【自制搜索小工具】
哈喽,大家好丫,你们的小郭子又来啦 ~ 当自己电脑文件很多还有点乱,用电脑自带的搜索文件,效率有点低,憋担心,我们用Python自制一个搜索小工具就行了,嘻嘻嘻嘻 环境准备 解释器: Python 3 ...
- 推荐几个 Windows 小工具
新的一年,抽空管理一下 Windows 里的文件.发现有的小工具用了两年以上了,也顺便推荐一下,是不是有些"火星"我倒真不知道,但总会对有些朋友有帮助的吧? PathSync 目录 ...
- windows小工具大全
今天又给大家推荐一款windows的工具神器哦~~~~,快来尝鲜吧!!! 核心工具箱(PC端) 这是一款功能很强大,并且集合了多家神器于一身的软件,软件可以jihuo系统.GIF录屏.看各种电影.不限 ...
最新文章
- API网关是否真的起到了它该有的作用?
- R语言ggplot2绘制平滑曲线的折线图简单小例子
- C++中String类的实现
- SPH(光滑粒子流体动力学)流体模拟实现四:各向异性(Anisotropic)表面光滑(2)
- 1、图解Oracle Logminer配置使用
- 解决批处理命令执行完毕后自动关闭cmd窗口
- 内存溢出的危害_漏洞练习之网络编程与堆栈溢出技术
- oracle及mysql错误记录
- STM32 F7xx + LAN8720+LWIP1.4.1调试坑点记录
- TVS 瞬态抑制二极管如何选型?
- 用python开发手机游戏_python开发安卓app
- wpl计算方法_用于计算加权路径长度(WPL)的C ++二叉树算法
- hotmail邮箱登录服务器,hotmail邮箱登录页面在哪 hotmail邮箱账号登录设置教程
- 从程序员到技术总监:一个普通人13年的奋斗
- 小程序源码:装B神器P图修改微信流量主小程序源码下载趣味恶搞图制作
- java8 stream中Comparator.comparing排序
- LDA模型中文文本主题提取丨可视化工具pyLDAvis的使用
- 哪款文件比较软件适合程序员
- Zigzag小整数压缩算法
- Web安全攻防 信息收集篇(仅供交流学习使用,请勿用于非法用途)