在阅读了一些 SO 帖子后,我想出了一种在 Python3 中使用 OpenCV 和 multiprocessing 的方法。我建议在 linux 上执行此操作,因为根据this post,只要内容未更改,生成的进程就会与其父进程共享内存。这是一个最小的例子:
import cv2
import multiprocessing as mp
import numpy as np
import psutil
img = cv2.imread('test.tiff', cv2.IMREAD_ANYDEPTH) # here I'm using a indexed 16-bit tiff as an example.
num_processes = 4
kernel_size = 11
tile_size = img.shape[0]/num_processes # Assuming img.shape[0] is divisible by 4 in this case
output = mp.Queue()
def mp_filter(x, output):
print(psutil.virtual_memory()) # monitor memory usage
output.put(x, cv2.GaussianBlur(img[img.shape[0]/num_processes*x:img.shape[0]/num_processes*(x+1), :],
(kernel_size, kernel_size), kernel_size/5))
# note that you actually have to process a slightly larger block and leave out the border.
if __name__ == 'main':
processes = [mp.Process(target=mp_filter, args=(x, output)) for x in range(num_processes)]
for p in processes:
p.start()
result = []
for ii in range(num_processes):
result.append(output.get(True))
for p in processes:
p.join()
不使用Queue,另一种收集进程结果的方法是通过multiprocessing 模块创建一个共享数组。 (必须导入ctypes)
result = mp.Array(ctypes.c_uint16, img.shape[0]*img.shape[1], lock = False)
然后假设没有重叠,每个进程可以写入数组的不同部分。然而,创建一个大的mp.Array 非常慢。这实际上违背了加快操作的目的。因此,仅当与总计算时间相比增加的时间不多时才使用它。这个数组可以通过以下方式变成一个numpy数组:
result_np = np.frombuffer(result, dtypye=ctypes.c_uint16)