javascript 字符截取-JS限制网页复制? OCR软件精度低?不如做个超级好用的OCR截图识别助手

2023-08-29 0 2,674 百度已收录

【飞桨开发者说】邵申辰,2018级计算机科学与技术专业,华北航天工业大学,PPDE,飞桨开发者技术专家,2020年国家大学生创新创业训练计划市级项目,研究方向为计算机视觉。

项目背景

Windows操作系统拥有数量庞大的用户。 凭借其优秀的人机操作、更好的软硬件支持以及前期抢占的市场,到2020年,其全球用户数将突破10亿。

为了实现高效办公,勤奋的开发者创造了很多软件来满足你的需求。比如个别网页的文字受JavaScript限制,无法复制,百度也解决不了好久(是的,我太擅长了)

)。 为什么不尝试一下暴力的方法,直接将笔记本上的文字识别为图片呢? 但很多软件都是要钱的,而且疗效一般都是免费的,或者每天晚上都会给你几次体验的机会。 最重要的一点是里面的软件可以识别本地图片。 就像共享单车解决了城市最后一公里一样,截图识别省去了保存图片上传识别的过程。

该项目的AIStudio地址:

说到识别模型,就不得不提PaddleOCR,它连续几天霸占了GitHub上的Trending榜单。 PaddleOCR是百度开源的超轻量级OCR模型库。 提供数十种文本检查识别模型,从而打造丰富、领先、实用的文本检查识别模型/工具库,促进用户更好的训练。 模型并将其应用到地面。 值得注意的是,PaddleHub 中添加了使用 DB 文本检查和 CRNN 文本识别的预训练模型 chinese_ocr_db_crnn_mobile,因此可以使用该 hub 轻松获取并在代码中使用该模型。

图1-免费OCR软件的部分界面

javascript 字符截取-JS限制网页复制?  OCR软件精度低?不如做个超级好用的OCR截图识别助手

整个想法

既然要做一个截图识别软件,那么首先需要截取截图,并将内容识别交给模型,最后将识别结果输出到文本框。 截图和结果输出很容易,主要问题是使用哪些模型来测量和识别文本?

基于分割的测量自然场景文本的方法似乎越来越受欢迎javascript 字符截取,因为分割网络的结果可以准确地描述扭曲文本等场景。 基于分割的方法的关键步骤是后处理部分,它将分割结果转换为文本框或文本区域。 DB文本检查算法也是基于分割的,提出了可微分二值化(DB)来简化分割后的处理步骤,并且可以设置自适应阈值来提高网络性能。

图2-DB网络架构

模型的网络结构如图2所示,对输入图像进行不同阶段的采样,得到不同的特征图,然后利用这个特征图构建特征金字塔,最终输出大小为1的特征图F /4,并用它同时预测概率图P和阈值图T,并根据P和T估计后得到近似二值图B。如上所述,DB可以对每个进行自适应二值化像素。 阈值是从网络中学习的,二值化的步骤完全加入到网络中一起训练。 二值化公式如下,k为放大倍数根据经验设置为50。

图3-二值化公式与sigmoid比较

损失函数由概率图损失、二值图损失和阈值图损失组成。 其中,α和β分别设置为1和10。 并使用二元交叉熵损失函数,并使用L1距离损失函数。

标签的生成基于PSENet形式,收缩比列r设置为0.4,文本框向外收缩和扩展D个像素,然后估计每个收缩框和扩展框的差异框和扩展框之间差异的像素。 原始图像边界的归一化距离。 下式中的S和C分别代表面积和边长。

说完了检查算法,接下来就该说一下识别算法了。 一种流行且简单的识别算法是CRNN(AnEnd-to-EndTrainableNeuralNetworkforImage-basedSequenceRecognitionandItsApplicationtoSceneTextRecognition),其网络结构如下:

javascript 字符截取-JS限制网页复制?  OCR软件精度低?不如做个超级好用的OCR截图识别助手

图4-CRNN网络架构

从下往上看,第一部分是频域层,利用VGG来提取输入图像的特征。 VGG是一种经典的频域神经网络。 它的规则非常简单:使用几个填充为1的3×3频域层和最大池化层的窗口形状。 频域层保持输入的高和宽不变,通道数加倍,池化层高和宽减半,最后用全连接和激活函数softmax连接实现分类。

图5-VGG模型

VGG 与之前网络的区别在于,它用连续的 3×3 频域核代替了较大​​的频域核(11×11、7×7、5×5),这样不仅减少了参数,还带来了同样的效果。疗效如同一般经验场。

第二部分利用LSTM进一步提取图像频域特征中的序列特征。 文本识别主要有两种方法,一种是基于字符/短语的识别,另一种是基于序列的识别。 基于字/词组识别,将文本段中的每个字/词组通过剪切的方式分别提取出来,然后进行识别,本质上是图像分类。 而剪切的质量直接影响识别结果,如果不能准确地剪切出字词,就无法得到识别结果。 基于序列的识别将文本识别视为序列识别,这样可以保证算法不会漏掉字符/短语,同时还可以结合上下文更好地处理序列信息。

图 6 - 基于字符/短语的识别

图 7 - 基于序列的识别

然而RNN的输出序列X与真实标签序列很难严格对齐,因此引入CTC来解决训练时字符不对齐的问题。 为了更好地理解CTC比对,这里举一个简单的反例。 假设我们使用CNN+RNN(GRU)来预测图5中的文本,输出结果不是我们期望的“飞桨”,有些部分重叠,有些部分因为文本之间有空格而空白。 事实上,CRNN是由不同的网络架构组成的,但是可以通过损失函数来联合训练。 该模型的更多细节可以在原始论文中找到:

我们利用PyQt的可视化功能,将屏幕截图读取和文本识别集成到pushButton控件中,并将输出结果放在textEdit控件中,制作一个简单的GUI。 源代码以及如何使用它可以在 中找到。

代码

项目的代码结构如下,requirements.txt是需要安装的模块。

图 8 - 代码结构

这里没有逐行敲出PyQt的用户界面代码,而是用QtDesigner生成.ui文件,然后在命令行用python-mpyuic5-ointerface.pyinterface.ui转换成.py文件。

from PyQt5 import QtCore, QtGui, QtWidgets  


class Ui_MainWindow(object):  
    def setupUi(self, MainWindow):  
        MainWindow.setObjectName("MainWindow")  
        MainWindow.resize(500500)  
        self.centralwidget = QtWidgets.QWidget(MainWindow)  
        self.centralwidget.setObjectName("centralwidget")  
        self.gridLayout = QtWidgets.QGridLayout(self.centralwidget)  
        self.gridLayout.setObjectName("gridLayout")  
        self.verticalLayout = QtWidgets.QVBoxLayout()  
        self.verticalLayout.setObjectName("verticalLayout")  
        self.pushButton = QtWidgets.QPushButton(self.centralwidget)  
        self.pushButton.setObjectName("pushButton")  
        self.verticalLayout.addWidget(self.pushButton)  
        self.textEdit = QtWidgets.QTextEdit(self.centralwidget)  
        self.textEdit.setObjectName("textEdit")  
        self.verticalLayout.addWidget(self.textEdit)  
        self.gridLayout.addLayout(self.verticalLayout, 0011)  
        MainWindow.setCentralWidget(self.centralwidget)  
        self.menubar = QtWidgets.QMenuBar(MainWindow)  
        self.menubar.setGeometry(QtCore.QRect(0027322))  
        self.menubar.setObjectName("menubar")  
        self.menufile = QtWidgets.QMenu(self.menubar)  
        self.menufile.setObjectName("menufile")  
        MainWindow.setMenuBar(self.menubar)  
        self.statusbar = QtWidgets.QStatusBar(MainWindow)  
        self.statusbar.setObjectName("statusbar")  
        MainWindow.setStatusBar(self.statusbar)  
        self.menubar.addAction(self.menufile.menuAction())  

        self.retranslateUi(MainWindow)  
        QtCore.QMetaObject.connectSlotsByName(MainWindow)  

    def retranslateUi(self, MainWindow):  
        _translate = QtCore.QCoreApplication.translate  
        MainWindow.setWindowTitle(_translate("MainWindow""OCR截屏文字识别助手"))  
        self.pushButton.setText(_translate("MainWindow""识别文字"))  
        self.menufile.setTitle(_translate("MainWindow""file"))  

截图识别过程分为三个步骤:

阅读截图;

使用PaddleOCR识别截图;

将识别结果复制到textEdit控件中。

Python自带的ImageGrab库提供了一种读取屏幕截图的方法,只需一行代码即可完成。 MAC系统中还有截图功能,且无法通过该功能读取,因此很难实现完整的识别功能。

为了减少代码量,这里直接使用PaddleHub提供的OCR模型。 需要说明的是,该模型依赖第三方库shapely和pyclipper,使用前请先安装这两个库。 该中心提供两种运行模型的方式 - 命令行和 API。 命令行操作很简单,只需一行代码:$hubrunchinese_ocr_db_crnn_mobile--input_path "/PATH/TO/IMAGE"。 然而,当我们在Python代码中使用hub时,我们仍然关注API方法:

def recognize_text(images=[],  
                    paths=[],  
                    use_gpu=False,  
                    output_dir='ocr_result',  
                    visualization=False,  
                    box_thresh=0.5,  
                    text_thresh=0.5)
  

范围

paths为图像的路径,值为字符; images 为读取后图像的格式,值为ndarray。 因为我们的截图是ImageGrab.grabclipboard()函数直接读取的ndarray格式,所以我们需要使用images参数。 如果是本地图片,可以通过paths参数指定,不需要使用cv2.imread等方法读取图片然后使用。

预测结果以JSON格式保存:

我们只需要识别文本内容,因此将文本值记录在data中。

from interface import Ui_MainWindow  
from PIL import Image, ImageGrab  
import cv2  
import numpy as np  
from PyQt5.QtWidgets import QApplication, QMainWindow  
import paddlehub as hub  


class run(QMainWindow, Ui_MainWindow):  
    def __init__(self):  
        super().__init__()  
        self.setupUi(self)  

    # 读取截图,返回截图  
    def imread(self, ui):  
        img = ImageGrab.grabclipboard()  
        try:  
            img = cv2.cvtColor(np.array(img), cv2.COLOR_RGB2BGR)  
        except TypeError:  
            ui.textEdit.setText("请先截图再点击按钮!")  
            return  
        else:  
            return img  

    # 使用PPOCR识别截图,返回识别结果  
    def imrec(self, img):  
        ocr = hub.Module(name="chinese_ocr_db_crnn_mobile")  
        result = ocr.recognize_text(images=[img])  
        res = str()  
        for data in result[0]["data"]:  
            res += data["text"]  
        return res  

    # 将识别结果打印到文本框中  
    def print_res(self, ui, res):  
        ui.textEdit.setText(res)  

    def all(self, ui):  
        img = self.imread(ui)  
        if not isinstance(img, np.ndarray):  
            return  
        res = self.imrec(img)  
        self.print_res(ui, res)  

main.py作为整个PyQt5的入口javascript 字符截取,以信号和槽的形式连接识别算法。

import sys  
from PyQt5.QtWidgets import QApplication, QMainWindow  
import interface  
import screen_rec  


if __name__ == '__main__':  
    app = QApplication(sys.argv)  
    # 生成主框口  
    MainWindow = QMainWindow()  
    # 定义自己设计的ui  
    ui = interface.Ui_MainWindow()  
    ui.setupUi(MainWindow)  
    MainWindow.show()  
    # 向槽函数传递ui即可修改textEdit控件  
    ui.pushButton.clicked.connect(lambda: screen_rec.run().all(ui))  
    sys.exit(app.exec_()) 

javascript 字符截取-JS限制网页复制?  OCR软件精度低?不如做个超级好用的OCR截图识别助手

演示

请在Windows 10操作系统下运行该软件。 MAC的截图功能其实可以用Command+Shift+4来使用,但是获得的图片无法粘贴保存,因此无法通过该功能读取。

建议使用 Miniconda 来管理你的包和环境,以避免奇怪的版本兼容性问题。

Win+Shift+S 弹出截图标志;

成功截取图片后,点击软件的识别文字即可开始识别;

识别完成后,在下方文本框中输出可编辑的识别结果。

图 9 - 动画演示

总结与展望

经测试,在AMD Ryzen 2500U处理器中,识别200个字符需要9秒,识别1000个字符需要25秒,而AIStudio提供的Intel(R) Xeon(R) Gold6148处理器分别需要2秒和12秒。 由于其紧凑的型号规格。

有时候打字费时费力,截图识别可以将截图翻译成可编辑的文本,大大提高了生产率。 值得注意的是,该项目仍在迭代中,仍有一些可以优化的地方。 比如显存泄漏问题,识别完成后,显存并不会完全释放。 考虑到PyQt主界面没有关闭,加载的模型没有被删除,导致显存占用。 对于CPU性能较弱、识别时间较长的本地机器,可以考虑接入百度的OCR字符识别API,实现准确、快速的识别。

如果您在使用过程中遇到任何问题,可以加入飞桨官方QQ群进行交流:1108045677。

收藏 (0) 打赏

感谢您的支持,我会继续努力的!

打开微信/支付宝扫一扫,即可进行扫码打赏哦,分享从这里开始,精彩与您同在
点赞 (0)

悟空资源网 javascript javascript 字符截取-JS限制网页复制? OCR软件精度低?不如做个超级好用的OCR截图识别助手 https://www.wkzy.net/game/175495.html

常见问题

相关文章

官方客服团队

为您解决烦忧 - 24小时在线 专业服务