问题
我正在尝试使用OpenCV捕获我的桌面,并让Tesseract OCR查找文本并将其设置为变量,例如,如果我要玩游戏并且捕获帧超过资源量,我希望它打印并使用它。一个完美的例子是minimumInterItemSpacing 只要他在游戏中失去健康,就会显示该健康并将其发送到启用蓝牙的气枪射击他。到目前为止,我有这个:
# imports
from PIL import ImageGrab
from PIL import Image
import numpy as np
import pytesseract
import argparse
import cv2
import os
fourcc = cv2.VideoWriter_fourcc(*'XVID')
out = cv2.VideoWriter("output.avi", fourcc, 5.0, (1366, 768))
while(True):
x = 760
y = 968
ox = 50
oy = 22
# screen capture
img = ImageGrab.grab(bbox=(x, y, x + ox, y + oy))
img_np = np.array(img)
frame = cv2.cvtColor(img_np, cv2.COLOR_BGR2RGB)
cv2.imshow("Screen", frame)
out.write(frame)
if cv2.waitKey(1) == 0:
break
out.release()
cv2.destroyAllWindows()
它可以实时捕获并显示在窗口中,但是我不知道如何使它每帧识别文本并输出。
有什么帮助吗?
答案 0 :(得分:3)
抓取屏幕并将其传递到tesseract
进行OCR相当简单。
PIL(枕头)库可以在MacOS和Windows上轻松捕获帧。但是,此功能仅在Linux上才被添加,因此下面的代码可解决该问题(不存在)。 (我使用的是Ubuntu 19.10,但我的Pillow不支持它。)
基本上,用户使用屏幕区域矩形坐标启动程序。主循环不断抓住屏幕的该区域,并将其馈送到Tesseract。如果Tesseract在该图像中找到任何非空白文本,则将其写入 stdout 。
请注意,这不是正确的实时系统。不能保证及时性,每个帧所花费的时间都一样长。您的计算机可能会获得60 FPS或可能达到6 FPS。这也将极大地受到您要求监视的矩形的大小的影响。
#! /usr/bin/env python3
import sys
import pytesseract
from PIL import Image
# Import ImageGrab if possible, might fail on Linux
try:
from PIL import ImageGrab
use_grab = True
except Exception as ex:
# Some older versions of pillow don't support ImageGrab on Linux
# In which case we will use XLib
if ( sys.platform == 'linux' ):
from Xlib import display, X
use_grab = False
else:
raise ex
def screenGrab( rect ):
""" Given a rectangle, return a PIL Image of that part of the screen.
Handles a Linux installation with and older Pillow by falling-back
to using XLib """
global use_grab
x, y, width, height = rect
if ( use_grab ):
image = PIL.ImageGrab.grab( bbox=[ x, y, x+width, y+height ] )
else:
# ImageGrab can be missing under Linux
dsp = display.Display()
root = dsp.screen().root
raw_image = root.get_image( x, y, width, height, X.ZPixmap, 0xffffffff )
image = Image.frombuffer( "RGB", ( width, height ), raw_image.data, "raw", "BGRX", 0, 1 )
# DEBUG image.save( '/tmp/screen_grab.png', 'PNG' )
return image
### Do some rudimentary command line argument handling
### So the user can speicify the area of the screen to watch
if ( __name__ == "__main__" ):
EXE = sys.argv[0]
del( sys.argv[0] )
# EDIT: catch zero-args
if ( len( sys.argv ) != 4 or sys.argv[0] in ( '--help', '-h', '-?', '/?' ) ): # some minor help
sys.stderr.write( EXE + ": monitors section of screen for text\n" )
sys.stderr.write( EXE + ": Give x, y, width, height as arguments\n" )
sys.exit( 1 )
# TODO - add error checking
x = int( sys.argv[0] )
y = int( sys.argv[1] )
width = int( sys.argv[2] )
height = int( sys.argv[3] )
# Area of screen to monitor
screen_rect = [ x, y, width, height ]
print( EXE + ": watching " + str( screen_rect ) )
### Loop forever, monitoring the user-specified rectangle of the screen
while ( True ):
image = screenGrab( screen_rect ) # Grab the area of the screen
text = pytesseract.image_to_string( image ) # OCR the image
# IF the OCR found anything, write it to stdout.
text = text.strip()
if ( len( text ) > 0 ):
print( text )
这个答案与SO上的其他答案完全拼凑在一起。
如果您经常将此答案用于任何用途,则值得添加一个速率限制器以节省一些CPU。每个循环大概睡半秒钟。
答案 1 :(得分:1)
Tesseract是使用文件输入和输出的一次性命令行应用程序,这意味着每个OCR调用都会创建一个新进程并初始化一个新的Tesseract引擎,其中包括从磁盘读取数兆字节的数据文件。它是否适合用作实时OCR引擎将取决于确切的用例(更多的像素需要更多的时间),以及提供的parameters用于调整OCR引擎。最终可能需要进行一些实验,以将引擎调整为准确的场景,但也期望对帧进行OCR所需的时间可能会超过帧时间,并且可能需要减少OCR执行的频率,即以10-游戏可能以20 FPS而不是60 FPS以上的速度运行。
根据我的经验,在老化的CPU上使用4核(默认)的英语快速模型,在2200x1700px图像中相当复杂的文档可能需要0.5s到2s的任何时间,但是此“复杂文档”代表了最差的-案例方案,并且不对所识别文本的结构做任何假设。在许多情况下,例如从游戏屏幕中提取数据,可以进行一些假设以实现一些优化并加快OCR:
-l
选项指定不同的模型,并使用--testdata-dir
选项指定包含模型文件的目录。您可以下载多个模型,然后将文件重命名为“ eng_fast.traineddata”,“ eng_best.traineddata”等。--psm
参数来防止您的方案不需要页面分割。 --psm 7
可能是处理单条信息的最佳选择,但要尝试不同的值并找出最合适的信息。-c tessedit_char_whitelist='1234567890'
来限制允许的字符集。pytesseract是开始实施Tesseract的最佳方法,该库可以直接处理图像输入(尽管它在将图像传递给Tesseract之前将其保存到文件中),并使用{{ 1}}。
image_to_string(...)
答案 2 :(得分:0)
我知道他使用的程序是OCR的开放式OpenCV存储库,而屏幕上限则是Imagegrab。 OCR和Cappig的2个过程是在一段时间内完成的,真正的循环是非常快的。
Michael在这里也有该项目的git:https://github.com/michaelreeves08/footnot-health-detection,但它表明他忘了上传它...
我在这里是因为我正在寻找相同的东西,如果您在这方面取得了进展,请告诉我。我是从视频截图中阅读Michael的代码获得此信息的。
答案 3 :(得分:0)
好的,我遇到了与您相同的问题,因此我对此进行了一些研究,并且确定可以找到解决方案!首先,您将需要以下库:
安装:
要安装cv2,只需在命令行/命令提示符中使用此命令: pip install opencv-python
安装 pytesseract 有点困难,因为您还需要预安装 Tesseract ,它实际上是进行ocr读取的程序。首先,按照本教程上的说明安装Tesseract。然后,在命令行/命令提示符中使用以下命令: pip install pytesseract 如果您没有安装此权限,则使用ocr会收到错误消息
要安装枕头,请在命令行/命令提示符中使用以下命令: python -m pip install --upgrade枕头或 python3 -m pip install --upgrade枕头。使用python的人对我有用
要安装NumPy,请在命令行/命令提示符中使用以下命令: pip install numpy 。以为它通常已经安装在大多数python库中。
代码: 这段代码是由我编写的,到目前为止,它可以按我想要的方式工作,并且类似于Michal的效果。它会显示在屏幕的左上方,并记录其图像,并显示当前使用OCR读取的图像的窗口显示。然后在控制台中,打印出在屏幕上读取的文本。
# OCR Screen Scanner
# By Dornu Inene
# Libraries that you show have all installed
import cv2
import numpy as np
import pytesseract
# We only need the ImageGrab class from PIL
from PIL import ImageGrab
# Run forever unless you press Esc
while True:
# This instance will generate an image from
# the point of (115, 143) and (569, 283) in format of (x, y)
cap = ImageGrab.grab(bbox=(115, 143, 569, 283))
# For us to use cv2.imshow we need to convert the image into a numpy array
cap_arr = np.array(cap)
# This isn't really needed for getting the text from a window but
# It will show the image that it is reading it from
# cv2.imshow() shows a window display and it is using the image that we got
# use array as input to image
cv2.imshow("", cap_arr)
# Read the image that was grabbed from ImageGrab.grab using pytesseract.image_to_string
# This is the main thing that will collect the text information from that specific area of the window
text = pytesseract.image_to_string(cap)
# This just removes spaces from the beginning and ends of text
# and makes the the it reads more clean
text = text.strip()
# If any text was translated from the image, print it
if len(text) > 0:
print(text)
# This line will break the while loop when you press Esc
if cv2.waitKey(1) == 27:
break
# This will make sure all windows created from cv2 is destroyed
cv2.destroyAllWindows()
我希望这对您所需要的有所帮助,确实对我有帮助!