我正在使用pytesseract通过多处理方法进行一些ocr。
该方法如下:
tess_api = PyTessBaseAPI()
Parallel(n_jobs=4)(delayed(execute)(image) for image in images)
具有功能:
def execute(image):
tess_api.SetImage(image)
text = tess_api.GetUTF8Text()
这将导致并发问题,因为工作进程1执行执行gettext()之前,工作进程1可能会覆盖映像
现在的想法是让每个工人一个PyTessBaseAPI
实例。
主要的想法是做类似的事情:
tess_apis = [PyTessBaseAPI(), PyTessBaseAPI(), PyTessBaseAPI(), PyTessBaseAPI()]
,然后将tess_api[0]
移交给工作人员0,但我不知道如何在工作人员和实例之间建立连接。
有什么建议,或者什么是更好的方法?
因为我有成千上万张图像,所以我不想在execute函数中创建实例。
答案 0 :(得分:1)
在每个工作进程开始使用Pool(initializer=...)
初始化Tesseract对象之前,便开始读取其工作队列。
tess_api = None
def initialize_worker():
global tess_api
tess_api = PyTessBaseAPI() # initialize a copy for this instance
def execute(image):
tess_api.SetImage(image)
text = tess_api.GetUTF8Text()
def main():
with multiprocessing.Pool(initializer=initialize_worker) as p:
for result in p.imap_unordered(images, chunksize=10):
# ...
这仅在您使用实际流程时才有效;如果您使用的是线程(考虑到Tesseract是C并会发布GIL,这可能会起作用),则可以使用contextvars
/ threading.local
。
答案 1 :(得分:1)
Pool(initializer=...)
可以按照提及的方式工作。但是,如果您想做更复杂的事情,建议您使用Ray。
然后将其表示为
import ray
ray.init()
@ray.remote
class Worker(object):
def __init__(self):
self.tess_api = PyTessBaseAPI()
def execute(self, image):
self.tess_api.SetImage(image)
return self.tess_api.GetUTF8Text()
# Create several Worker actors.
workers = [Worker.remote() for _ in range(4)]
# Execute tasks on them in parallel.
result_ids = [worker.execute.remote(image) for worker in workers]
# Get the results
results = ray.get(result_ids)
您可以阅读有关Ray in the documentation的更多信息。请注意,我帮助开发Ray。