当我使用 pytesseract 和 CREATE_NO_WINDOW 运行 tesseract 时如何隐藏控制台窗口

Posted

技术标签:

【中文标题】当我使用 pytesseract 和 CREATE_NO_WINDOW 运行 tesseract 时如何隐藏控制台窗口【英文标题】:How to hide the console window when I run tesseract with pytesseract with CREATE_NO_WINDOW 【发布时间】:2017-11-27 16:14:41 【问题描述】:

我正在使用 tesseract 对屏幕抓图执行 OCR。我有一个使用 tkinter 窗口的应用程序,在我的类的初始化中利用 self.after 在 tkinter 窗口中执行恒定的图像抓取和更新标签等值。我已经搜索了多天,但找不到任何具体示例如何在使用 pytesseract 调用 tesseract 的 Windows 平台上将 CREATE_NO_WINDOW 与 Python3.6 结合使用。

这与这个问题有关:

How can I hide the console window when I run tesseract with pytesser

我只用了 2 周的 Python 编程,不明白什么/如何执行上述问题中的步骤。我打开了 pytesseract.py 文件并查看并找到了 proc = subprocess.Popen(command, stderr=subproces.PIPE) 行,但是当我尝试对其进行编辑时,我遇到了一堆我无法弄清楚的错误。

#!/usr/bin/env python

'''
Python-tesseract. For more information: https://github.com/madmaze/pytesseract

'''

try:
    import Image
except ImportError:
    from PIL import Image

import os
import sys
import subprocess
import tempfile
import shlex


# CHANGE THIS IF TESSERACT IS NOT IN YOUR PATH, OR IS NAMED DIFFERENTLY
tesseract_cmd = 'tesseract'

__all__ = ['image_to_string']


def run_tesseract(input_filename, output_filename_base, lang=None, boxes=False,
                  config=None):
    '''
    runs the command:
        `tesseract_cmd` `input_filename` `output_filename_base`

    returns the exit status of tesseract, as well as tesseract's stderr output

    '''
    command = [tesseract_cmd, input_filename, output_filename_base]

    if lang is not None:
        command += ['-l', lang]

    if boxes:
        command += ['batch.nochop', 'makebox']

    if config:
        command += shlex.split(config)

    proc = subprocess.Popen(command, stderr=subprocess.PIPE)
    status = proc.wait()
    error_string = proc.stderr.read()
    proc.stderr.close()
    return status, error_string


def cleanup(filename):
    ''' tries to remove the given filename. Ignores non-existent files '''
    try:
        os.remove(filename)
    except OSError:
        pass


def get_errors(error_string):
    '''
    returns all lines in the error_string that start with the string "error"

    '''

    error_string = error_string.decode('utf-8')
    lines = error_string.splitlines()
    error_lines = tuple(line for line in lines if line.find(u'Error') >= 0)
    if len(error_lines) > 0:
        return u'\n'.join(error_lines)
    else:
        return error_string.strip()


def tempnam():
    ''' returns a temporary file-name '''
    tmpfile = tempfile.NamedTemporaryFile(prefix="tess_")
    return tmpfile.name


class TesseractError(Exception):
    def __init__(self, status, message):
        self.status = status
        self.message = message
        self.args = (status, message)


def image_to_string(image, lang=None, boxes=False, config=None):
    '''
    Runs tesseract on the specified image. First, the image is written to disk,
    and then the tesseract command is run on the image. Tesseract's result is
    read, and the temporary files are erased.

    Also supports boxes and config:

    if boxes=True
        "batch.nochop makebox" gets added to the tesseract call

    if config is set, the config gets appended to the command.
        ex: config="-psm 6"
    '''

    if len(image.split()) == 4:
        # In case we have 4 channels, lets discard the Alpha.
        # Kind of a hack, should fix in the future some time.
        r, g, b, a = image.split()
        image = Image.merge("RGB", (r, g, b))

    input_file_name = '%s.bmp' % tempnam()
    output_file_name_base = tempnam()
    if not boxes:
        output_file_name = '%s.txt' % output_file_name_base
    else:
        output_file_name = '%s.box' % output_file_name_base
    try:
        image.save(input_file_name)
        status, error_string = run_tesseract(input_file_name,
                                             output_file_name_base,
                                             lang=lang,
                                             boxes=boxes,
                                             config=config)
        if status:
            errors = get_errors(error_string)
            raise TesseractError(status, errors)
        f = open(output_file_name, 'rb')
        try:
            return f.read().decode('utf-8').strip()
        finally:
            f.close()
    finally:
        cleanup(input_file_name)
        cleanup(output_file_name)


def main():
    if len(sys.argv) == 2:
        filename = sys.argv[1]
        try:
            image = Image.open(filename)
            if len(image.split()) == 4:
                # In case we have 4 channels, lets discard the Alpha.
                # Kind of a hack, should fix in the future some time.
                r, g, b, a = image.split()
                image = Image.merge("RGB", (r, g, b))
        except IOError:
            sys.stderr.write('ERROR: Could not open file "%s"\n' % filename)
            exit(1)
        print(image_to_string(image))
    elif len(sys.argv) == 4 and sys.argv[1] == '-l':
        lang = sys.argv[2]
        filename = sys.argv[3]
        try:
            image = Image.open(filename)
        except IOError:
            sys.stderr.write('ERROR: Could not open file "%s"\n' % filename)
            exit(1)
        print(image_to_string(image, lang=lang))
    else:
        sys.stderr.write('Usage: python pytesseract.py [-l lang] input_file\n')
        exit(2)


if __name__ == '__main__':
    main()

我使用的代码类似于类似问题中的示例:

def get_string(img_path):
    # Read image with opencv
    img = cv2.imread(img_path)
    # Convert to gray
    img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    # Apply dilation and erosion to remove some noise
    kernel = np.ones((1, 1), np.uint8)
    img = cv2.dilate(img, kernel, iterations=1)
    img = cv2.erode(img, kernel, iterations=1)
    # Write image after removed noise
    cv2.imwrite(src_path + "removed_noise.png", img)
    #  Apply threshold to get image with only black and white
    # Write the image after apply opencv to do some ...
    cv2.imwrite(src_path + "thres.png", img)
    # Recognize text with tesseract for python

    result = pytesseract.image_to_string(Image.open(src_path + "thres.png"))

    return result

当它到达下一行时,黑色控制台窗口闪烁不到一秒钟,然后在运行命令时关闭。

result = pytesseract.image_to_string(Image.open(src_path + "thres.png"))

这是控制台窗口的图片:

Program Files (x86)_Tesseract

这是另一个问题的建议:

您目前在 IDLE 中工作,在这种情况下,我认为不会 如果弹出控制台窗口真的很重要。如果你打算 用这个库开发一个 GUI 应用程序,那么你需要修改 pytesser.py 中的 subprocess.Popen 调用以隐藏控制台。我会先 尝试 CREATE_NO_WINDOW 进程创建标志。 – 埃克森

对于如何使用 CREATE_NO_WINDOW 修改 pytesseract.py 库文件中的 subprocess.Popen 调用,我将不胜感激。我也不确定 pytesseract.py 和 pytesser.py 库文件之间的区别。我会就另一个问题发表评论以要求澄清,但直到我在此网站上获得更多声誉后才能这样做。

【问题讨论】:

【参考方案1】:

我做了更多的研究并决定进一步了解 subprocess.Popen:

Documentation for subprocess

我还参考了以下文章:

using python subprocess.popen..can't prevent exe stopped working prompt

我在pytesseract.py中更改了原代码行:

proc = subprocess.Popen(command, stderr=subprocess.PIPE)

到以下:

proc = subprocess.Popen(command, stderr=subprocess.PIPE, creationflags = CREATE_NO_WINDOW)

我运行代码并得到以下错误:

Tkinter 回调 Traceback 中的异常(最近一次调用最后一次): 文件 "C:\Users\Steve\AppData\Local\Programs\Python\Python36-32\lib\tkinter__init__.py", 第 1699 行,在 call 中 返回 self.func(*args) 文件“C:\Users\Steve\Documents\Stocks\QuickOrder\QuickOrderGUI.py”,行 403,在收集数据中 update_cash_button() 文件“C:\Users\Steve\Documents\Stocks\QuickOrder\QuickOrderGUI.py”,行 208,在 update_cash_button currentCash = get_string(src_path + "cash.png") 文件 "C:\Users\Steve\Documents\Stocks\QuickOrder\QuickOrderGUI.py",行 150,在 get_string 结果 = pytesseract.image_to_string(Image.open(src_path + "thres.png")) 文件 "C:\Users\Steve\AppData\Local\Programs\Python\Python36-32\lib\site-packages\pytesseract\pytesseract.py", 第 125 行,在 image_to_string 中 config=config) 文件 "C:\Users\Steve\AppData\Local\Programs\Python\Python36-32\lib\site-packages\pytesseract\pytesseract.py", 第 49 行,在 run_tesseract proc = subprocess.Popen(command, stderr=subprocess.PIPE, creationflags = CREATE_NO_WINDOW) NameError: name 'CREATE_NO_WINDOW' 没有定义

然后我定义了 CREATE_NO_WINDOW 变量:

#Assignment of the value of CREATE_NO_WINDOW
CREATE_NO_WINDOW = 0x08000000

我从上面链接的文章中得到了 0x08000000 的值。添加定义后,我运行了应用程序,但没有再弹出控制台窗口。

【讨论】:

以上是关于当我使用 pytesseract 和 CREATE_NO_WINDOW 运行 tesseract 时如何隐藏控制台窗口的主要内容,如果未能解决你的问题,请参考以下文章

TypeError:需要一个类似字节的对象,而不是 python 3.5.2 和 pytesseract 中的“str”

pytesseract,WindowsError: [错误2] 系统找不到指定的文件

Pytesseract 无法识别图像中的简单文本

Pytesseract 提高 OCR 准确性

Python pytesseract - 找不到 eng.traineddata - oem 2

pytesseract库的安装和使用