在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()
这实际上是一个棘手的问题,它处理底层系统原语,如fork
和mmap
问题是进程不共享内存。因此,每个进程都在处理自己的初始数组副本。这是通过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
对象有一个数组接口,所以它可以在任何地方使用,与使用常规数组的方式相同。