从多重处理函数返回值

时间:2018-12-12 08:21:48

标签: python process multiprocessing python-multiprocessing

在python中使用多处理模块时遇到问题。我的目标是创建m * n个过程(其中m * n是图像的尺寸)并更改像素的所有值(在下面的代码中,将值从0更改为255)。 在函数内部,借助打印功能,我可以看到像素的值发生了变化。但是,当我最后显示输出图像时,图像内容没有变化。有人可以让我知道问题出在哪里吗?

import cv2
import numpy
import multiprocessing

def func(i,j,img_op):
    #print("For pixel",i,j)
    img_op[i][j]=255
    print("For pixel", i, j,"\t",img_op[i][j])
    return img_op[i][j]

img=cv2.imread('pokemon.png',0)
height = numpy.size(img, 0)
width = numpy.size(img, 1)
img_op=numpy.zeros((height,width,1),numpy.uint8)

print(height,width)

processes=[]
for i in range(0,height-2):
    for j in range(0,width-2):
        p=multiprocessing.Process(target=func,args=(i,j,img_op,))
        processes.append(p)
        p.start()

for p in processes:
    p.join()

cv2.imshow('Original image',img)
cv2.imshow('White IMage',img_op)
cv2.waitKey(0)
cv2.destroyAllWindows()

1 个答案:

答案 0 :(得分:0)

这实际上是一个棘手的问题,它处理低级系统原语,例如forkmmap

问题是进程不共享内存。 结果,每个进程都在其自己的初始数组副本上工作。 这是通过fork系统调用创建进程的方式的结果:当前进程,代码和内存被复制为新进程,并且它们都继续各自执行。

有很多解决方法,但是最直接的方法是使用内存映射。 内存映射是由mmap系统调用创建的对象,该对象将磁盘的一部分映射到RAM中并且可以作为文件描述符进行访问。 由于文件描述符实际上并未复制到fork上,因此实际上它们将在进程之间共享。

幸运的是,numpy定义了具有数组接口mmap的传统np.memmap对象的抽象。 就像我说的那样,内存映射由磁盘上的文件支持,因此您需要为其提供路径和访问模式。

您可以如下定义全局映像:

img_op = np.memmap(
    "/tmp/shared_image", dtype=np.uint8, mode='w+', shape=(height, width, 1)
)

由于np.memmap对象具有数组接口,因此可以在任何地方使用它,并且可以使用常规数组的方式。