1

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

这与这个问题有关:

使用 pytesser 运行 tesseract 时如何隐藏控制台窗口

我只用了 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"))

这是控制台窗口的图片:

程序文件 (x86)_Tesseract

这是另一个问题的建议:

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

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

4

1 回答 1

3

我做了更多的研究并决定了解更多关于 subprocess.Popen 的信息:

子流程的文档

我还参考了以下文章:

使用 python subprocess.popen.. 无法阻止 exe 停止工作提示

我更改了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 行,调用中 return self.func(*args) 文件“C:\Users\Steve\Documents\Stocks\QuickOrder\QuickOrderGUI.py”,第 403 行,gather_data 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' is not defined

然后我定义了 CREATE_NO_WINDOW 变量:

#Assignment of the value of CREATE_NO_WINDOW
CREATE_NO_WINDOW = 0x08000000

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

于 2017-06-24T03:51:35.717 回答