利用baidu的api和python的GUI实现通用文字识别功能

1. 准备工作

1.1. 注册和申请

我们不是自己要写一套智能识别文字的工具 (那工作量也太大了)
因此不得不借助百度的力量。
首先就是注册账号和申请api了。

百度AI开放平台有好多好多功能可以用,我贴了几个。

百度AI开放平台
百度文字识别服务
百度语音识别服务
百度人脸识别服务

点哪个无所谓,反正我们注册之后来到百度智能云的管理中心,鼠标放到产品服务上。

在这里插入图片描述

就选文字识别吧(当然了要做别的就选别的,都差不多啦!| ू•ૅω•́)ᵎᵎᵎ)

然后咱们创建个新应用
在这里插入图片描述
ok,一个无比简易的应用创建完成了。

在这里插入图片描述
费用嘛,每天有50000次至少够我挥霍了哈哈哈哈

在这里插入图片描述

费用说明

1.2. python 的库

众所周期遇事不决先装库,对于这个应用要安装的是baidu-api,可以在cmd输入

pip install baidu-aip

或者你用pycharm装之类的都可以了。

用简单的代码来验证一下它的功能吧

from aip import AipOcr ## 引用OCR识别的api

class TextRecognition:
    def __init__(self,app_id,api_key,secret_key):
        ## 用自己申请到的app id等内容初始化AipOcr
        self.aipOcr = AipOcr(app_id,api_key,secret_key)

        """ 读取图片 """
    def get_file_content(self,filePath):
        with open(filePath, 'rb') as fp:
            return fp.read()


    def imageToText(self,path):
        ## 将path对应的图片转换为文字
        image = self.get_file_content(path)
        
        ### 可选参数
        options = {}
        options["language_type"] = "CHN_ENG"
        options["detect_direction"] = "true"
        options["detect_language"] = "true"
        options["probability"] = "true"
        result = self.aipOcr.webImage(image, options)
        self.result = result
        return result

    def SplicingText(self):
        text = ""
        for res in self.result['words_result']:
            text += res['words']
        print (text)
        return text

### 都换成你自己的
App_id = "*******"
Api_key = "*****************"
Secret_key = "*******************"

T = TextRecognition(App_id,Api_key,Secret_key)
path = r"D:\GH\ToolsBasedOnBaidu\TextTest.png"
## 显示结果
print(T.imageToText(path))
## 显示拼接后的文本
T.SplicingText()

其中的可选参数等内容来自于官方文档

选用图片

在这里插入图片描述

来观察一下返回结果的内容吧

在这里插入图片描述

result内容包括log_id,direction,words_result_num以及wrods_result几个内容。
其中direction是图像的方向,而words_resulf则是最重要的输出结果,是一个list。

在这里插入图片描述
其中每个元素都是一个字典,包括words和probability两个keys,words是我们想要转化成的文字,而probability则是概率(包括方差、正确率、最小值)

把列表里每个字典的words的内容拼接起来可以得到完整的文本。

在这里插入图片描述

OK大功告成,接下来来做真正的工具吧!

2. 小工具的开发

每次都运行个.py岂不是太麻烦了,还是整成一个带快捷键的工具比较合适。

2.1. 截图功能

此段主要参考csdn的大佬虾米小飞
涉及到截图就又需要调包了(没有的库就麻烦pip install ****一下了)

import time
from PIL import ImageGrab
import tkinter as tk
import os
import win32clipboard
from PIL import Image
from io import BytesIO

首先要把整个屏幕截下来,然后再去细分截图

def screenShot():
    root.state('icon')
    time.sleep(0.1)
    im = ImageGrab.grab(None)
    im.save('temp.png')
    im.close()
    w=FreeScreenShot(root,'temp.png')
    button_screenShot.wait_window(w.top)
    root.state('normal')
    os.remove('temp.png')

接下来实现类似QQ微信截图的点击、拖拽、松开截图

class FreeScreenShot():
    def __init__(self,root,img):
        
        """保存鼠标左键点击位置(一会要赋值的)"""
        self.X = tk.IntVar(value = 0)
        self.Y = tk.IntVar(value = 0)

        """获取屏幕尺寸"""
        screenWidth = root.winfo_screenwidth()
        screenHeight = root.winfo_screenheight()

        ### 顶级组件容器

        self.top = tk.Toplevel(root,width=screenWidth,height = screenHeight)

        ### 隐藏顶条
        self.top.overrideredirect(True)
        self.canvas = tk.Canvas(self.top,bg = 'white',width = screenWidth,height = screenHeight)

        ### 显示全屏截图,然后进行区域截图
        self.image = tk.PhotoImage(file = img)
        self.canvas.create_image(screenWidth//2,screenHeight//2,image = self.image)

        self.lastDraw = None

        """更新鼠标左键按下位置"""
        def onLeftButtonDown(event):
            self.X.set(event.x)
            self.Y.set(event.y)
            # 开始截图
            self.begin = True

        self.canvas.bind('<Button-1>',onLeftButtonDown)# 绑定按键和事件

        """鼠标移动选取区域"""
        def onLeftButtonMove(event):
            #鼠标左键移动,显示选取的区域
            if not self.begin:
                return
            try: #删除刚画完的图形,要不然鼠标移动的时候是黑乎乎的一片矩形
                self.canvas.delete(self.lastDraw)
            except Exception as e:
                pass
            self.lastDraw = self.canvas.create_rectangle(self.X.get(), self.Y.get(), event.x, event.y, outline='green')

        """鼠标左键抬起,完成截图"""
        def onLeftButtonUp(event):
            #获取鼠标左键抬起的位置,保存区域截图
            self.begin = False
            try:
                self.canvas.delete(self.lastDraw)
            except Exception as e:
                pass

            time.sleep(0.1)
            #考虑鼠标左键从右下方按下而从左上方抬起的截图
            left, right = sorted([self.X.get(), event.x])
            top, bottom = sorted([self.Y.get(), event.y])
            pic = ImageGrab.grab((left+1, top+1, right, bottom))
            self.pic = pic  ## 存下图片
            
            #self.paste_img(pic)
            #self.send_msg_to_clip(win32clipboard.CF_UNICODETEXT,"啊啊啊啊啊啊啊八八八八八八八啊啊")
            #关闭当前窗口
            self.top.destroy()
            
        self.canvas.bind('<B1-Motion>', onLeftButtonMove) # 按下左键
        self.canvas.bind('<ButtonRelease-1>', onLeftButtonUp) # 抬起左键
        #让canvas充满窗口,并随窗口自动适应大小
        self.canvas.pack(fill=tk.BOTH, expand=tk.YES)

2.2. 保存到剪贴板

此处参考另一位大佬
你可以选择把截下来的图片保存入剪贴板,也可以选择把转换后的文字保存到剪贴板

    """将图片保存入剪贴板"""
    def send_msg_to_clip(self,type_data, msg):
        """
        操作剪贴板分四步:
        1. 打开剪贴板:OpenClipboard()
        2. 清空剪贴板,新的数据才好写进去:EmptyClipboard()
        3. 往剪贴板写入数据:SetClipboardData()
        4. 关闭剪贴板:CloseClipboard()

        :param type_data: 数据的格式,
        unicode字符通常是传 win32con.CF_UNICODETEXT
        :param msg: 要写入剪贴板的数据
        """
        win32clipboard.OpenClipboard()
        win32clipboard.EmptyClipboard()
        win32clipboard.SetClipboardData(type_data, msg)
        win32clipboard.CloseClipboard()

    
    def paste_img(self,image):
        """
        图片转换成二进制字符串,然后以位图的格式写入剪贴板

        主要思路是用Image模块打开图片,
        用BytesIO存储图片转换之后的二进制字符串

        :param file_img: 图片的路径
        """

        # 声明output字节对象
        output = BytesIO()

        # 用BMP (Bitmap) 格式存储
        # 这里是位图,然后用output字节对象来存储
        image.save(output, 'BMP')

        # BMP图片有14字节的header,需要额外去除
        data = output.getvalue()[14:]

        # 关闭
        output.close()

        # DIB: 设备无关位图(device-independent bitmap),名如其意
        # BMP的图片有时也会以.DIB和.RLE作扩展名
        # 设置好剪贴板的数据格式,再传入对应格式的数据,才能正确向剪贴板写入数据
        self.send_msg_to_clip(win32clipboard.CF_DIB, data)

2.3. 连接到文本识别

对最开始的截图部分稍加修改,引入我们之前的文本识别

import TextRecognize

在鼠标抬起的函数里添加转换文字的功能

            self.pic = pic  ## 存下图片
            pic.save("temp2.png")
            I2T = TextRecognize.TextRecognition(app_id = "21139457",api_key = "PbyNrvXkrnwYtbqnODiOmvH8",\
                secret_key = "WcXA0he5d0PalmqBPrmzTrmGrW52gDNy")
            I2T.imageToText("temp2.png")
            self.Text = I2T.SplicingText()
            #self.paste_img(pic)
            self.send_msg_to_clip(win32clipboard.CF_UNICODETEXT,self.Text)

2.4. 简单的界面

emmm,我们就放一个截屏按钮以及一个显示文本的文本框

root = tk.Tk()
root.title("ScreenShot")
root.geometry('500x500')
root.resizable(True,True)

text = tk.Text(root)
text.pack()

def screenShot():
    root.state('icon')
    time.sleep(0.2)
    im = ImageGrab.grab(None)
    im.save('temp.png')
    im.close()
    w=FreeScreenShot(root,'temp.png')
    button_screenShot.wait_window(w.top)
    root.state('normal')
    os.remove('temp.png')
    text.insert("end",w.Text)


button_screenShot = tk.Button(root,text='Shot',command = screenShot)
button_screenShot.place(relx=0.5, rely=0.75, relwidth=0.2, relheight=0.2)




try:
    root.mainloop()
except:
    root.destroy()

2.5. 高分辨率屏幕修正

由于我用的是Surface Book 2,高分辨率屏幕下开了屏幕缩放200%,因此ImageGrab抓取的屏幕只有左上角。可以参考下面的方法把python注册成高DPI。

参考资料

I manage to overcome this issue by adding registry key at

HKEY_CURRENT_USER\Software\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Layers

add a key with the path to your python.exe and pythonw.exe and in value set HIGHDPIAWARE

like so:

"C:\Users\Greg\Anaconda3\python.exe"="HIGHDPIAWARE" "C:\Users\Greg\Anaconda3\pythonw.exe"="HIGHDPIAWARE"

then everythings should be ok :)

3. 看看结果

框住一段文字看看

在这里插入图片描述

文本框中出现文本,剪贴板上也有了,可以直接复制。

在这里插入图片描述

4. 打包

打包成exe啊!!!
pyinstaller老把一堆没用的库一起打包进来,不如勇哥虚拟环境

pip install virtualenv

virtualenv Name

然后cd进入虚拟环境(name你自己起)里面的Scripts文件夹中,输入activate激活虚拟环境

然后安装必要模块,比如本篇用到的

baidu-aip
pillow
pywin32  (里面有win32clipboard)
pyinstaller

都安装好后把我们的文件放到这个虚拟环境的目录下,进入文件夹,输入

pyinstaller -F main.py

其常见参数列表有

参数效果
-F,-onefile产生单个的可执行文件
-D,–onedir产生一个目录(包含多个文件)作为可执行程序
-a,–ascii不包含 Unicode 字符集支持
-d,–debug产生 debug 版本的可执行文件
-w,–windowed,–noconsolc指定程序运行时不显示命令行窗口(仅对 Windows 有效)
-c,–nowindowed,–console指定使用命令行窗口运行程序(仅对 Windows 有效)
-o DIR,–out=DIR指定 spec 文件的生成目录。如果没有指定,则默认使用当前目录来生成 spec 文件
-p DIR,–path=DIR设置 Python 导入模块的路径(和设置 PYTHONPATH 环境变量的作用相似)。也可使用路径分隔符(Windows 使用分号,Linux 使用冒号)来分隔多个路径
-n NAME,–name=NAME指定项目(产生的 spec)名字。如果省略该选项,那么第一个脚本的主文件名将作为 spec 的名字

即可获得我们的exe可执行文件,齐活!!!

5. 完整代码

CSDN

Github

  • 1
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

豆沙粽子好吃嘛!

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值