您当前的位置:首页 > 计算机 > 编程开发 > Python

一个python写的可视化本地处理的OCR

时间:01-11来源:作者:点击数:

可以单个处理图片,也可以选择文件夹批量处理,完全本地cpu处理

需要用到的python库

pip install PyQt5
pip install opencv-python
pip install paddleocr
pip install numpy
pip install pillow
pip install pyperclip

python版本 3.8或者3.9

python下载地址:https://www.python.org/downloads/windows/

python代码

import sys
import os
from PyQt5.QtWidgets import QApplication, QMainWindow, QPushButton, QVBoxLayout, QHBoxLayout, QWidget, QFileDialog, QTextEdit, QLabel, QMessageBox, QProgressBar
from PyQt5.QtGui import QPixmap, QImage
from PyQt5.QtCore import Qt, QThread, pyqtSignal
import cv2
from paddleocr import PaddleOCR
import numpy as np
from PIL import Image
import pyperclip
 
class OCRThread(QThread):
    progress_update = pyqtSignal(int)
    result_ready = pyqtSignal(list)
 
    def __init__(self, ocr, file_list):
        super().__init__()
        self.ocr = ocr
        self.file_list = file_list
 
    def run(self):
        results = []
        for i, file in enumerate(self.file_list):
            try:
                result = self.ocr.ocr(file, cls=True)
                results.append((os.path.basename(file), result))
            except Exception as e:
                results.append((os.path.basename(file), None))
                print(f"处理文件 {file} 时出错: {str(e)}")
            self.progress_update.emit(int((i + 1) / len(self.file_list) * 100))
        self.result_ready.emit(results)
 
class OCRApp(QMainWindow):
    def __init__(self):
        super().__init__()
        self.initUI()
        self.ocr = PaddleOCR(use_angle_cls=True, lang="ch")
        self.current_image = None
 
    def initUI(self):
        self.setWindowTitle('OCR应用')
         
        fixed_width = 400
        fixed_height = 500
        self.setFixedSize(fixed_width, fixed_height)
 
        central_widget = QWidget()
        self.setCentralWidget(central_widget)
        main_layout = QVBoxLayout()
        central_widget.setLayout(main_layout)
 
        self.image_label = QLabel(self)
        self.image_label.setAlignment(Qt.AlignCenter)
        self.image_label.setFixedSize(fixed_width - 20, 200)
        main_layout.addWidget(self.image_label)
 
        button_layout = QHBoxLayout()
        self.open_file_button = QPushButton('选择图片', self)
        self.open_file_button.clicked.connect(self.open_file)
        button_layout.addWidget(self.open_file_button)
 
        self.open_folder_button = QPushButton('选择文件夹', self)
        self.open_folder_button.clicked.connect(self.open_folder)
        button_layout.addWidget(self.open_folder_button)
 
        self.copy_button = QPushButton('复制内容', self)
        self.copy_button.clicked.connect(self.copy_content)
        button_layout.addWidget(self.copy_button)
 
        main_layout.addLayout(button_layout)
 
        self.progress_bar = QProgressBar(self)
        self.progress_bar.setVisible(False)
        main_layout.addWidget(self.progress_bar)
 
        self.result_text = QTextEdit(self)
        self.result_text.setReadOnly(True)
        main_layout.addWidget(self.result_text)
 
    def open_file(self):
        file_name, _ = QFileDialog.getOpenFileName(self, "选择图片", "", "图片文件 (*.png *.jpg *.bmp)")
        if file_name:
            self.process_image(file_name)
 
    def open_folder(self):
        directory = QFileDialog.getExistingDirectory(self, "选择文件夹")
        if directory:
            files = [os.path.join(directory, f) for f in os.listdir(directory) if f.lower().endswith(('.png', '.jpg', '.bmp'))]
            if files:
                self.process_multiple_images(files)
            else:
                QMessageBox.warning(self, "提示", "文件夹中没有符合条件的图片文件。")
 
    def process_image(self, file_name):
        self.current_image = cv2.imread(file_name)
        if self.current_image is None:
            QMessageBox.warning(self, "错误", "无法加载图片,文件可能已损坏或格式不支持。")
            return
         
        self.display_image(self.current_image)
        try:
            result = self.ocr.ocr(file_name, cls=True)
            self.display_result([(os.path.basename(file_name), result)])
        except Exception as e:
            QMessageBox.warning(self, "错误", f"OCR处理失败: {str(e)}")
 
    def process_multiple_images(self, files):
        self.progress_bar.setVisible(True)
        self.progress_bar.setValue(0)
         
        self.ocr_thread = OCRThread(self.ocr, files)
        self.ocr_thread.progress_update.connect(self.update_progress)
        self.ocr_thread.result_ready.connect(self.display_result)
        self.ocr_thread.start()
 
    def update_progress(self, value):
        self.progress_bar.setValue(value)
 
    def display_image(self, img):
        height, width, channel = img.shape
        bytes_per_line = 3 * width
        q_img = QImage(img.data, width, height, bytes_per_line, QImage.Format_RGB888).rgbSwapped()
        pixmap = QPixmap.fromImage(q_img)
         
        label_width = self.image_label.width()
        label_height = self.image_label.height()
        scale = min(label_width / width, label_height / height)
         
        new_width = int(width * scale)
        new_height = int(height * scale)
         
        scaled_pixmap = pixmap.scaled(new_width, new_height, Qt.KeepAspectRatio, Qt.SmoothTransformation)
        self.image_label.setPixmap(scaled_pixmap)
 
    def display_result(self, results):
        self.result_text.clear()
        for file_name, result in results:
            self.result_text.append(f"文件: {file_name}")
            if result and len(result) > 0 and result[0]:
                try:
                    sorted_result = sorted(result[0], key=lambda x: (x[0][0][1], x[0][0][0]))
                    for line in sorted_result:
                        text = line[1][0]
                        self.result_text.append(text)
                except Exception as e:
                    self.result_text.append(f"解析结果时出错: {str(e)}")
            else:
                self.result_text.append("未识别到文本")
            self.result_text.append("\n")
         
        self.progress_bar.setVisible(False)
        if len(results) > 1:
            QMessageBox.information(self, "完成", f"已完成 {len(results)} 个文件的识别")
 
    def copy_content(self):
        content = self.result_text.toPlainText()
        pyperclip.copy(content)
        QMessageBox.information(self, "提示", "内容已复制到剪贴板")
 
if __name__ == '__main__':
    app = QApplication(sys.argv)
    ex = OCRApp()
    ex.show()
    sys.exit(app.exec_())

 

方便获取更多学习、工作、生活信息请关注本站微信公众号城东书院 微信服务号城东书院 微信订阅号
推荐内容
相关内容
栏目更新
栏目热门
本栏推荐