设为首页收藏本站

 找回密码
 立即注册
搜索
查看: 102|回复: 19

基于PaddleOCR的【一键截图+笔墨辨认】工具【支持win7】【2026.1.30更新】

[复制链接]
累计签到:13 天
连续签到:5 天
灌水成绩
9
14
2272
主题
帖子
积分

等级头衔

ID : 629

初级技术员

积分成就 测量币 : 2272
在线时间 : 0 小时
注册时间 : 2026-3-23
最后登录 : 2026-5-14

勋章
UID勋章测量学徒测量员
联系方式
发表于 2026-3-20 22:14:30 | 显示全部楼层 |阅读模式 IP:香港
●这是一个基于PaddleOCR的【一键截图文字辨认】工具(已于2026.1.30更新本地离线摆设版本)
由于是模子OCR,因此可以辨认:普通文本、手写中英文、数学公式等复杂文本。
--------------------------------------------------------------【API版】-------------------------------------------------------------------------------
调用PaddleOCR-VL官方API接口进行文字辨认,需前去PaddleOCR官网(https://aistudio.Baidu.com/paddleocr)免费申请API_TOKEN,并在工具”设置“菜单中填入。
已发布适配win7的版本,与正常版本无区别~win7朋侪也能用啦,嘿嘿嘿



【API版】使用提示:

1.如工具无法打开,可能是运行库缺失题目,我已将必备运行库上传至工具下载地址。

2.需前去PaddleOCR官网(https://aistudio.baidu.com/paddleocr)免费申请API_TOKEN,并在工具”设置“菜单中填入,方可使用本工具。

3.截图过程中按右键或ESC可取消截图,截图地区过小自动取消截图。

4.图片解析后的文字自动存入剪贴板,也可直接在文本框里划选并复制(copy)。

5.点击热键如果没有反应,请尝试以管理员身份运行本工具。

6.工具使用过程中需全程联网,网络环境不佳时,解析时间可能较长,请耐心等待或重新辨认。

7.如遇文字解析失败环境,请尝试重新辨认。
--------------------------------------------------------------【本地离线版】--------------------------------------------------------------------------
CPU要求要有AVX指令集,故不支持  【Intel:凌动Atom,安腾Itanium,赛扬Celeron,奔腾Pentium系列 】【AMD:K10架构及之前的系列】 CPU。
推荐运行内存:6GB+
2026.1.30已发布v1.42版本
------------------------------------------------------------【本地离线Lite版】-------------------------------------------------------------------------
超轻量级,适合低设置机器
支持全部CPU
预计2月初发布,敬请期待


【本地版】使用提示:

1.如工具无法打开,可能是运行库缺失题目,我已将必备运行库上传至工具下载地址。

2.需确保压缩包内全部文件完备解压,目次内点击exe文件方可启动使用本工具

3.截图过程中按右键或ESC可取消截图,截图地区过小自动取消截图。

4.图片解析后的文字自动存入剪贴板,也可直接在文本框里划选并复制(copy)。

5.点击热键如果没有反应,请尝试以管理员身份运行本工具。

6.如遇文字解析失败环境,请尝试重新辨认。

7.本地版采用轻量级模子,针对公式辨认有更高要求的朋侪建议移步API版。
---------------------------------------------------------------------------------------------------------------------------------------------------------

工具下载地址: 下载地址.txt (11 KB, 下载次数: 0)


更新日志:
v1.41:①新增热键功能,热键可在“设置”中绑定,点击热键即可开始截图;②新增公式预览功能,点击按钮可对辨认出的LaTex数学公式进行可读化预览;③新增排版优化功能,点击按钮可对辨认出的文字段落进行排版优化;④工具更名为抠抠截图文字辨认工具
v1.42:①修复辨认文字后出现“##”的题目;




本工具将连续更新,接待各位大佬反馈题目与BUG。

源代码:
[Python] 纯文本查看 复制代码import sys, re, io, time, base64, requests, threading, keyboardfrom PyQt6.QtWidgets import (QApplication, QMainWindow, QPushButton, QVBoxLayout,                              QWidget, QTextEdit, QLabel, QLineEdit, QStackedWidget, QHBoxLayout)from PyQt6.QtCore import Qt, QRect, pyqtSignal, QObject, QTimer, QSettingsfrom PyQt6.QtGui import QPainter, QPen, QColorfrom PIL import ImageGrab, ImageEnhance, ImageFilterimport pyperclipclass WorkerSignals(QObject):    finished = pyqtSignal(str, str)#截图层class CaptureWindow(QWidget):    def __init__(self, callback, cancel_callback):        super().__init__()        self.callback = callback        self.cancel_callback = cancel_callback        self.setWindowFlags(Qt.WindowType.FramelessWindowHint | Qt.WindowType.WindowStaysOnTopHint | Qt.WindowType.Tool)        self.setWindowState(Qt.WindowState.WindowFullScreen)        self.setWindowOpacity(0.3)        self.setCursor(Qt.CursorShape.CrossCursor)        self.start_pos = self.end_pos = None        self.is_drawing = False    def paintEvent(self, event):        if self.is_drawing and self.start_pos and self.end_pos:            painter = QPainter(self)            painter.setPen(QPen(QColor(255, 0, 0), 2, Qt.PenStyle.SolidLine))             painter.drawRect(QRect(self.start_pos, self.end_pos))    def mousePressEvent(self, event):        if event.button() == Qt.MouseButton.RightButton:            self.cancel_callback(); self.close()        elif event.button() == Qt.MouseButton.LeftButton:            self.start_pos = event.pos(); self.is_drawing = True    def mouseMoveEvent(self, event):        if self.is_drawing: self.end_pos = event.pos(); self.update()    def mouseReleaseEvent(self, event):        if event.button() == Qt.MouseButton.LeftButton:            self.is_drawing = False            self.hide()            QApplication.processEvents()            time.sleep(0.15)            x1, y1 = min(self.start_pos.x(), event.pos().x()), min(self.start_pos.y(), event.pos().y())            x2, y2 = max(self.start_pos.x(), event.pos().x()), max(self.start_pos.y(), event.pos().y())            if x2 - x1 < 10 or y2 - y1 < 10:                self.cancel_callback(); self.close(); return            ratio = self.screen().devicePixelRatio()            bbox = (x1 * ratio, y1 * ratio, x2 * ratio, y2 * ratio)            img = ImageGrab.grab(bbox)            self.callback(img); self.close()#主窗口class MainWindow(QMainWindow):    def __init__(self):        super().__init__()        self.setWindowTitle(&quot;截图文字辨认工具v1.30&quot;)        self.resize(450, 600)                #设置保存        self.settings = QSettings(&quot;MyOCRTool&quot;, &quot;Settings&quot;)                        self.stack = QStackedWidget()        self.setCentralWidget(self.stack)                self.init_main_ui()            self.init_setting_ui()         self.init_about_ui()                self.signals = WorkerSignals()        self.signals.finished.connect(self.on_ocr_finished)                #初始热键绑定        #self.current_hotkey = self.settings.value(&quot;hotkey&quot;, &quot;alt+q&quot;)        #self.rebind_hotkey(self.current_hotkey)    def init_main_ui(self):        page = QWidget()        layout = QVBoxLayout(page)                header_layout = QHBoxLayout()                self.btn_to_setting = QPushButton(&quot;设置&quot;)        self.btn_to_setting.clicked.connect(lambda: self.stack.setCurrentIndex(1))        self.btn_to_about = QPushButton(&quot;关于&quot;)        self.btn_to_about.clicked.connect(lambda: self.stack.setCurrentIndex(2))               header_layout.addWidget(self.btn_to_setting)        header_layout.addWidget(self.btn_to_about)        header_layout.addStretch()        layout.addLayout(header_layout)        self.btn_capture = QPushButton(&quot;开始截图&quot;)        self.btn_capture.setMinimumHeight(60)        self.btn_capture.setStyleSheet(&quot;background-color: #4CAF50; color: white; font-weight: bold;&quot;)        self.btn_capture.clicked.connect(self.start_capture)        layout.addWidget(self.btn_capture)        self.label_status = QLabel(&quot;工具已停当&quot;)        layout.addWidget(self.label_status)        self.result_box = QTextEdit()        layout.addWidget(self.result_box)                self.stack.addWidget(page)    def init_setting_ui(self):        page = QWidget()        layout = QVBoxLayout(page)        layout.addWidget(QLabel(&quot;API_URL:&quot;))        self.edit_url = QLineEdit(self.settings.value(&quot;url&quot;, &quot;在此输入API_URL&quot;))        layout.addWidget(self.edit_url)        layout.addWidget(QLabel(&quot;API_TOKEN:&quot;))        self.edit_token = QLineEdit(self.settings.value(&quot;token&quot;, &quot;在此输入TOKEN&quot;))        layout.addWidget(self.edit_token)        # layout.addWidget(QLabel(&quot;快捷键 (如 alt+q, ctrl+shift+a):&quot;))        # self.edit_hotkey = QLineEdit(self.settings.value(&quot;hotkey&quot;, &quot;alt+q&quot;))        # layout.addWidget(self.edit_hotkey)        layout.addStretch()        btn_save = QPushButton(&quot;保存并返回&quot;)        btn_save.setMinimumHeight(40)        btn_save.setStyleSheet(&quot;background-color: #4CAF50; color: white; font-weight: bold;&quot;)        btn_save.clicked.connect(self.save_settings)        layout.addWidget(btn_save)        self.stack.addWidget(page)    def init_about_ui(self):        page = QWidget()        layout = QVBoxLayout(page)        layout.addWidget(QLabel(&quot;截图文字辨认工具v1.30

&quot;))        layout.addWidget(QLabel(&quot;本工具免费且已开源,仅供学习交换,严禁倒卖!&quot;))        layout.addWidget(QLabel(&quot;功能说明:截图地区文字辨认,鼠标右键或ESC可取消截图
&quot;))                layout.addStretch()                btn_back = QPushButton(&quot;返回&quot;)        btn_back.setMinimumHeight(40)        btn_back.setStyleSheet(&quot;background-color: #2196F3; color: white; font-weight: bold;&quot;)        btn_back.clicked.connect(lambda: self.stack.setCurrentIndex(0))        layout.addWidget(btn_back)                self.stack.addWidget(page)             def save_settings(self):        #保存到设置        self.settings.setValue(&quot;url&quot;, self.edit_url.text())        self.settings.setValue(&quot;token&quot;, self.edit_token.text())                #new_hotkey = self.edit_hotkey.text().lower()        #if new_hotkey != self.current_hotkey:            #self.rebind_hotkey(new_hotkey)            #self.current_hotkey = new_hotkey            #self.settings.setValue(&quot;hotkey&quot;, new_hotkey)                    self.stack.setCurrentIndex(0)        self.label_status.setText(&quot;设置已保存&quot;)    def rebind_hotkey(self, key_str):        try:            keyboard.unhook_all() #扫除旧的            keyboard.add_hotkey(key_str, self.start_capture)        except:            print(&quot;热键绑定失败&quot;)    def start_capture(self):        if self.isVisible():            self.hide()            QTimer.singleShot(250, self.show_capture_window)            def show_capture_window(self):        self.cap_win = CaptureWindow(self.request_ocr_thread, self.on_capture_cancel)        self.cap_win.show()    def on_capture_cancel(self):        self.show(); self.label_status.setText(&quot;截图已取消&quot;)    def request_ocr_thread(self, img_obj):        self.show()        self.label_status.setText(&quot;图片解析中&quot;)        self.btn_capture.setEnabled(False)        threading.Thread(target=self.ocr_worker, args=(img_obj,), daemon=True).start()            def ocr_worker(self, img):        try:            #图像预处理            img = img.convert('L')            img = ImageEnhance.Contrast(img).enhance(2.0)            img = img.filter(ImageFilter.SHARPEN)            img = img.convert('RGB')            #图像压缩            img_byte_arr = io.BytesIO()            img.save(img_byte_arr, format='JPEG', quality=95)            file_data = base64.b64encode(img_byte_arr.getvalue()).decode(&quot;ascii&quot;)            # 从界面获取实时设置            url = self.settings.value(&quot;url&quot;)            token = self.settings.value(&quot;token&quot;)            headers = {&quot;Authorization&quot;: f&quot;token {token}&quot;, &quot;Content-Type&quot;: &quot;application/json&quot;}            payload = {&quot;file&quot;: file_data, &quot;fileType&quot;: 1, &quot;useDocOrientationClassify&quot;: False, &quot;useChartRecognition&quot;: False}                        response = requests.post(url, json=payload, headers=headers, timeout=20)                        if response.status_code == 200:                result = response.json()[&quot;result&quot;]                text = &quot;&quot;.join([re.sub(r']+>', '', res[&quot;markdown&quot;][&quot;text&quot;]) + &quot;\n&quot; for res in result.get(&quot;layoutParsingResults&quot;, [])])                self.signals.finished.emit(text.strip() or &quot;解析失败,请尝试重新辨认&quot;, &quot;辨认完成&quot;)            else:                self.signals.finished.emit(&quot;&quot;, f&quot;API错误: {response.status_code}&quot;)        except Exception as e:            self.signals.finished.emit(&quot;&quot;, f&quot;异常: {str(e)}&quot;)    def on_ocr_finished(self, text, status):        self.btn_capture.setEnabled(True)        self.label_status.setText(status)        if text:            self.result_box.setText(text)            pyperclip.copy(text)if __name__ == &quot;__main__&quot;:    app = QApplication(sys.argv)    window = MainWindow()    window.show()    sys.exit(app.exec())













                                
                                
                                
                                
                                
                                
                                
                                
                                
                                
                                
                                
                                
                                
                                
                                
                                
                                
精密测量技术论坛免责声明
重要声明:以上内容仅代表该作者观点,不代表本站精密测量技术论坛立场。
如有涉及侵权请尽快告知,我们将会在第一时间处理。作者原创内容未经允许不得转载!
站长联系邮箱:1339305021@qq.com
站长联系微信:dddnnbbb
累计签到:8 天
连续签到:2 天
灌水成绩
2
133
1251
主题
帖子
积分

等级头衔

ID : 896

测量学徒

积分成就 测量币 : 1251
在线时间 : 0 小时
注册时间 : 2026-1-28
最后登录 : 2026-5-15

勋章
UID勋章测量学徒测量员
联系方式
发表于 2026-3-25 17:15:44 | 显示全部楼层 IP:香港
感谢大神,很好用,识别正确率比Umi-OCR高,希望能够考虑增加两个功能就更好了。1、识别表格;2、参考https://www.52pojie.cn/forum.php?mod=viewthread&tid=1913500&highlight=%CE%A2%D0%C5ocr,增加一个无界面版  打开后直接让用户截图   自动识别后复制到剪贴板  然后自动退出。
回复

使用道具 举报

累计签到:11 天
连续签到:5 天
灌水成绩
1
157
1348
主题
帖子
积分

等级头衔

ID : 846

测量学徒

积分成就 测量币 : 1348
在线时间 : 0 小时
注册时间 : 2025-10-13
最后登录 : 2026-5-14

勋章
UID勋章测量学徒测量员
联系方式
发表于 2026-3-22 16:58:15 | 显示全部楼层 IP:香港
自己测试一下,用的日漫测试
因为日漫排版问题从左至右而且是竖排,好些白嫖软件识别起来都比较苦手,特别是识别后的排版基本都是乱的
测试结果在线版的话几乎完美,就是识别的速度不行,经常会出现链接异常,需要反复识别
离线版的识别速度上几乎是秒识别,就是识别出来以后基本就是乱码了
回复

使用道具 举报

累计签到:10 天
连续签到:5 天
灌水成绩
1
151
1352
主题
帖子
积分

等级头衔

ID : 810

测量学徒

积分成就 测量币 : 1352
在线时间 : 0 小时
注册时间 : 2025-11-3
最后登录 : 2026-5-15

勋章
UID勋章测量学徒测量员
联系方式
发表于 2026-3-29 10:49:32 | 显示全部楼层 IP:香港
感觉还不错,收费吗
回复

使用道具 举报

累计签到:13 天
连续签到:5 天
灌水成绩
4
143
1272
主题
帖子
积分

等级头衔

ID : 868

测量学徒

积分成就 测量币 : 1272
在线时间 : 0 小时
注册时间 : 2026-2-5
最后登录 : 2026-5-15

勋章
UID勋章测量学徒测量员
联系方式
发表于 2026-3-27 04:58:26 | 显示全部楼层 IP:香港
这个工具不错,自己搞定Access Token就行了
回复

使用道具 举报

累计签到:16 天
连续签到:5 天
灌水成绩
1
180
1426
主题
帖子
积分

等级头衔

ID : 843

测量学徒

积分成就 测量币 : 1426
在线时间 : 0 小时
注册时间 : 2026-2-8
最后登录 : 2026-5-15

勋章
UID勋章测量学徒测量员
联系方式
发表于 2026-3-25 18:09:05 | 显示全部楼层 IP:香港
支持下。谢谢
回复

使用道具 举报

累计签到:10 天
连续签到:1 天
灌水成绩
2
158
976
主题
帖子
积分

等级头衔

ID : 893

测量学徒

积分成就 测量币 : 976
在线时间 : 0 小时
注册时间 : 2025-12-18
最后登录 : 2026-5-15

勋章
UID勋章测量学徒测量员
联系方式
发表于 2026-3-25 05:35:39 | 显示全部楼层 IP:香港
能常驻任务栏再加一个快捷键,并能对识别文字智能排版段落就更精准了。
回复

使用道具 举报

累计签到:14 天
连续签到:1 天
灌水成绩
1
142
1432
主题
帖子
积分

等级头衔

ID : 869

测量学徒

积分成就 测量币 : 1432
在线时间 : 0 小时
注册时间 : 2026-4-4
最后登录 : 2026-5-14

勋章
UID勋章测量学徒测量员
联系方式
发表于 2026-3-26 23:16:28 | 显示全部楼层 IP:香港
感谢楼主,试了一下,能很好的识别公式。如果增加识别后直接复制的选项。就更好了。目前在寻找哪一款公式识别准确而且方便的app。
回复

使用道具 举报

累计签到:10 天
连续签到:1 天
灌水成绩
1
141
1262
主题
帖子
积分

等级头衔

ID : 844

测量学徒

积分成就 测量币 : 1262
在线时间 : 0 小时
注册时间 : 2025-10-9
最后登录 : 2026-5-15

勋章
UID勋章测量学徒测量员
联系方式
发表于 2026-3-22 05:20:55 | 显示全部楼层 IP:香港
抱歉忘了设置提示了,识别完成后是直接存进剪贴板的。后面我改一下
回复

使用道具 举报

累计签到:8 天
连续签到:1 天
灌水成绩
1
145
847
主题
帖子
积分

等级头衔

ID : 832

测量学徒

积分成就 测量币 : 847
在线时间 : 0 小时
注册时间 : 2026-1-4
最后登录 : 2026-5-15

勋章
UID勋章测量学徒测量员
联系方式
发表于 2026-3-23 06:40:41 | 显示全部楼层 IP:香港
收到,后面我改一下
回复

使用道具 举报

快速回复换一批
好贴支持!
感谢楼主,好人一生平安
路过留名
好贴帮顶
强无敌
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|精密测量技术论坛 ( 桂ICP备2026007449号-1 )|网站地图

GMT+8, 2026-5-15 04:00 , Processed in 0.189308 second(s), 33 queries .

快速回复 返回顶部 返回列表