Как сделать распознавание текста со скриншота и вывод этого текста в QTextEdit?

Я написал приложение и использую OCR для распознавания текста со скриншота.
Я выделяю область и у меня сохраняется скриншот, но после его сохранения программа завершает работу.

Код:

import sys
import keyboard
from PyQt5.QtWidgets import QApplication, QMainWindow, QWidget, QPushButton, QVBoxLayout, QLabel, QTextEdit, QDialog
from PyQt5.QtCore import Qt, QRect, QPoint
from PyQt5 import QtCore, QtGui, QtWidgets
import pytesseract
from PIL import Image

class SnippingWidget(QDialog):
    selection_finished = QtCore.pyqtSignal(QtCore.QRect)
    text_selected = QtCore.pyqtSignal(str)

    def __init__(self):
        super(SnippingWidget, self).__init__()
        self.setAttribute(QtCore.Qt.WA_NoSystemBackground, True)
        self.setAttribute(QtCore.Qt.WA_TranslucentBackground, True)
        self.setStyleSheet("background:transparent;")

        self.setWindowFlags(Qt.FramelessWindowHint)

        self.outsideSquareColor = "red"
        self.squareThickness = 2

        self.start_point = QtCore.QPoint()
        self.end_point = QtCore.QPoint()
        self.selected_area = None

        screen_geometry = QtWidgets.QApplication.desktop().screenGeometry()
        self.setGeometry(screen_geometry)

    def mousePressEvent(self, event):
        self.start_point = event.pos()
        self.end_point = event.pos()
        QtWidgets.QApplication.setOverrideCursor(QtCore.Qt.CrossCursor)
        self.update()

    def mouseMoveEvent(self, event):
        self.end_point = event.pos()
        self.update()

    def mouseReleaseEvent(self, QMouseEvent):
        try:
            r = QtCore.QRect(self.start_point, self.end_point).normalized()
            self.close()
            self.selected_area = r
            QtWidgets.QApplication.restoreOverrideCursor()
            self.selection_finished.emit(r)

            # Извлечение изображения из выделенной области
            screenshot = QtWidgets.QApplication.primaryScreen().grabWindow(0, r.x(), r.y(), r.width(), r.height())
            screenshot.save("screenshot.png", "png")

            # Распознавание текста с помощью Tesseract OCR
            text = pytesseract.image_to_string(Image.open("screenshot.png"), lang='eng')

            # Передача распознанного текста в главное окно
            self.text_selected.emit(text)

            self.start_point = QtCore.QPoint()
            self.end_point = QtCore.QPoint()
        except Exception as e:
            pass

    def paintEvent(self, event):
        trans = QtGui.QColor(22, 100, 233)
        r = QtCore.QRectF(self.start_point, self.end_point).normalized()
        qp = QtGui.QPainter(self)
        trans.setAlphaF(0.2)
        qp.setBrush(trans)
        outer = QtGui.QPainterPath()
        outer.addRect(QtCore.QRectF(self.rect()))
        inner = QtGui.QPainterPath()
        inner.addRect(r)
        r_path = outer - inner
        qp.drawPath(r_path)
        qp.setPen(
            QtGui.QPen(QtGui.QColor(self.outsideSquareColor), self.squareThickness)
        )
        trans.setAlphaF(0)
        qp.setBrush(trans)
        qp.drawRect(r)

class MainWindow(QMainWindow):
    def __init__(self):
        super(MainWindow, self).__init__()

        self.setWindowFlags(QtCore.Qt.WindowStaysOnTopHint | QtCore.Qt.FramelessWindowHint)

        pytesseract.pytesseract.tesseract_cmd = r'C:\Program Files\Tesseract-OCR\tesseract.exe'
        
        self.draggable = False
        self.offset = None

        # set the title 
        self.setWindowTitle("") 

        # Удаление иконки окна
        self.setWindowIconText("")

        #Размеры окна
        self.setGeometry(300, 300, 500, 300)

        # Установка фона и темы
        self.setStyleSheet("themes/rose.json")

        # Окно работы
        self.osnovnoe_frame = QWidget(self)
        self.osnovnoe_frame.setGeometry(QRect(300, 0, 700, 600))

        # Боковой фрейм для меню
        self.lev_frame = QWidget(self)
        self.lev_frame.setGeometry(QRect(0, 0, 300, 600))

        self.text_edit = QTextEdit(self)
        self.text_edit.setGeometry(QRect(200, 50, 290, 200))

        # Текст логотип
        self.label = QLabel("TransScreen", self.lev_frame)
        self.label.setGeometry(QRect(20, 30, 260, 50))
        self.label.setStyleSheet("font: bold 25px;")

        # Старт
        self.button_start = QPushButton("Выделение области", self.lev_frame)
        self.button_start.setGeometry(QRect(20, 100, 170, 40))
        self.button_start.clicked.connect(self.start_app)

        # Настройки
        self.button_settings = QPushButton("Настройки", self.lev_frame)
        self.button_settings.setGeometry(QRect(20, 150, 170, 40))

        # Выход
        self.button_exit = QPushButton("Выход", self.lev_frame)
        self.button_exit.setGeometry(QRect(20, 200, 170, 40))
        self.button_exit.clicked.connect(self.exit_app)

        self.snipper = None

        # Бинды
        keyboard.on_press_key('ctrl', self.toggle_window)

    # функции
    def start_app(self):
        self.is_selecting = True
        self.hide()
        self.snipper = SnippingWidget()
        self.snipper.selection_finished.connect(self.handle_text_selected)
        self.snipper.text_selected.connect(self.handle_text_display)  # Connect the text_selected signal
        self.snipper.exec_()  

    def handle_text_selected(self, selected_area):
        # Вывод распознанного текста в QTextEdit виджет
        screenshot = QtWidgets.QApplication.primaryScreen().grabWindow(0, selected_area.x(), selected_area.y(), selected_area.width(), selected_area.height())
        screenshot.save("screenshot.png", "png")
        text = pytesseract.image_to_string(Image.open("screenshot.png"), lang='eng')
        self.text_edit.setText(text)
        # Другие действия с текстом...

    def handle_text_display(self, text):
        self.text_edit.setText(text)  # Отображение распознанного текста в QTextEdit

    def exit_app(self):
        self.close()

    def toggle_window(self, e):
        if self.isVisible():
            self.hide()
        else:
            self.show()

    def mousePressEvent(self, event):
        if event.button() == Qt.LeftButton:
            self.draggable = True
            self.offset = event.pos()

    def mouseMoveEvent(self, event):
        if self.draggable:
            self.move(event.globalPos() - self.offset)

    def mouseReleaseEvent(self, event):
        if event.button() == Qt.LeftButton:
            self.draggable = False


if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = MainWindow()
    window.show()
    sys.exit(app.exec_())

Он должен распознавать текст с сохранённого скрина и выводить его в QTextEdit.
Ошибок никаких не вылезает, просто завершение работы происходит.


Ответы (1 шт):

Автор решения: S. Nick

Некоторые косметические исправления смотрите по тексту кода:

import sys
import keyboard
from PyQt5.QtWidgets import QApplication, QMainWindow, \
     QWidget, QPushButton, QVBoxLayout, QLabel, \
     QTextEdit, QDialog
from PyQt5.QtCore import Qt, QRect, QPoint
from PyQt5 import QtCore, QtGui, QtWidgets
import pytesseract
from PIL import Image


class SnippingWidget(QDialog):
    selection_finished = QtCore.pyqtSignal(QtCore.QRect)
    text_selected = QtCore.pyqtSignal(str)

    def __init__(self):
        super(SnippingWidget, self).__init__()

# +++
        self.setWindowFlags(Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint)
        self.setAttribute(Qt.WA_TranslucentBackground)

        '''        
        self.setAttribute(QtCore.Qt.WA_NoSystemBackground, True)
        self.setAttribute(QtCore.Qt.WA_TranslucentBackground, True)
        self.setStyleSheet("background: transparent;")
        self.setWindowFlags(Qt.FramelessWindowHint)
        '''

        self.outsideSquareColor = "red"
        self.squareThickness = 2

        self.start_point = QtCore.QPoint()
        self.end_point = QtCore.QPoint()
        self.selected_area = None

        screen_geometry = QtWidgets.QApplication.desktop().screenGeometry()
        self.setGeometry(screen_geometry)

    def mousePressEvent(self, event):
        self.start_point = event.pos()
        self.end_point = event.pos()
        QtWidgets.QApplication.setOverrideCursor(QtCore.Qt.CrossCursor)
        self.update()

    def mouseMoveEvent(self, event):
        self.end_point = event.pos()
        self.update()

    def mouseReleaseEvent(self, QMouseEvent):
        try:
            r = QtCore.QRect(self.start_point, self.end_point).normalized()
            self.close()
            self.selected_area = r
            QtWidgets.QApplication.restoreOverrideCursor()
            self.selection_finished.emit(r)

            # Извлечение изображения из выделенной области
            screenshot = QtWidgets.QApplication.primaryScreen().grabWindow(0, r.x(), r.y(), r.width(), r.height())
            screenshot.save("screenshot.png", "png")

            # Распознавание текста с помощью Tesseract OCR
            text = pytesseract.image_to_string(Image.open("screenshot.png"), lang='eng')

            # Передача распознанного текста в главное окно
            self.text_selected.emit(text)

            self.start_point = QtCore.QPoint()
            self.end_point = QtCore.QPoint()
        except Exception as e:
            print(f'Exception as e: {e} ???????????????')   # +

    def paintEvent(self, event):
# ---------------------------------------> vv <----------------------------
        trans = QtGui.QColor(22, 100, 233, 77)
        r = QtCore.QRectF(self.start_point, self.end_point).normalized()
        qp = QtGui.QPainter(self)
#        trans.setAlphaF(0.2)
        qp.setBrush(trans)
        outer = QtGui.QPainterPath()
        outer.addRect(QtCore.QRectF(self.rect()))
        inner = QtGui.QPainterPath()
        inner.addRect(r)
        r_path = outer - inner
        qp.drawPath(r_path)
        qp.setPen(
            QtGui.QPen(QtGui.QColor(self.outsideSquareColor), self.squareThickness)
        )
#        trans.setAlphaF(0)
        qp.setBrush(trans)
        qp.drawRect(r)

class MainWindow(QMainWindow):
    def __init__(self):
        super(MainWindow, self).__init__()

        self.setWindowFlags(QtCore.Qt.WindowStaysOnTopHint | QtCore.Qt.FramelessWindowHint)

        pytesseract.pytesseract.tesseract_cmd = r'C:\Program Files\Tesseract-OCR\tesseract.exe'
        
        self.draggable = False
        self.offset = None

        # set the title 
        self.setWindowTitle("WindowTitle") 

        # Удаление иконки окна
        self.setWindowIconText("Ok.png")

        #Размеры окна
        self.setGeometry(300, 300, 500, 300)

# Установка фона и темы
# ?     self.setStyleSheet("themes/rose.json")

# Окно работы # ??? это что self.osnovnoe_frame # ???
# вам надо почитать что такое setCentralWidget <--------------------
        self.osnovnoe_frame = QWidget(self)
        self.osnovnoe_frame.setGeometry(QRect(300, 0, 700, 600))

        # Боковой фрейм для меню
        self.lev_frame = QWidget(self)
        self.lev_frame.setGeometry(QRect(0, 0, 300, 600))

        self.text_edit = QTextEdit(self)
        self.text_edit.setGeometry(QRect(200, 50, 290, 200))

        # Текст логотип
        self.label = QLabel("TransScreen", self.lev_frame)
        self.label.setGeometry(QRect(20, 30, 260, 50))
        self.label.setStyleSheet("font: bold 25px;")

        # Старт
        self.button_start = QPushButton("Выделение области", self.lev_frame)
        self.button_start.setGeometry(QRect(20, 100, 170, 40))
        self.button_start.clicked.connect(self.start_app)

        # Настройки
        self.button_settings = QPushButton("Настройки", self.lev_frame)
        self.button_settings.setGeometry(QRect(20, 150, 170, 40))

        # Выход
        self.button_exit = QPushButton("Выход", self.lev_frame)
        self.button_exit.setGeometry(QRect(20, 200, 170, 40))
        self.button_exit.clicked.connect(self.exit_app)

        self.snipper = None

# Бинды # ???
        keyboard.on_press_key('ctrl', self.toggle_window)

    # функции
    def start_app(self):
        self.is_selecting = True
        
# Внимание вы скрыли главное окно 
# и забыли его показать чтобы увидеть вывод распознанного текста в QTextEdit
        self.hide()
        
        self.snipper = SnippingWidget()
        self.snipper.selection_finished.connect(self.handle_text_selected)
        self.snipper.text_selected.connect(self.handle_text_display)  # Connect the text_selected signal
        self.snipper.exec_()  

    def handle_text_selected(self, selected_area):
        # Вывод распознанного текста в QTextEdit виджет
        screenshot = QtWidgets.QApplication.primaryScreen().grabWindow(0, selected_area.x(), selected_area.y(), selected_area.width(), selected_area.height())
        screenshot.save("screenshot.png", "png")
        text = pytesseract.image_to_string(Image.open("screenshot.png"), lang='eng')

# !! ++ vvvvvvvvvvv <----------------------------------------------------
        self.show()
        
        self.text_edit.setText(text)
        # Другие действия с текстом...

    def handle_text_display(self, text):
        self.text_edit.setText(text)  # Отображение распознанного текста в QTextEdit

    def exit_app(self):
        self.close()

    def toggle_window(self, e):
        if self.isVisible():
            self.hide()
        else:
            self.show()

    def mousePressEvent(self, event):
        if event.button() == Qt.LeftButton:
            self.draggable = True
            self.offset = event.pos()

    def mouseMoveEvent(self, event):
        if self.draggable:
            self.move(event.globalPos() - self.offset)

    def mouseReleaseEvent(self, event):
        if event.button() == Qt.LeftButton:
            self.draggable = False


if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = MainWindow()
    window.show()
    sys.exit(app.exec_())

введите сюда описание изображения



введите сюда описание изображения


→ Ссылка