在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()
答案 0 :(得分:0)
这实际上是一个棘手的问题,它处理低级系统原语,例如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
对象具有数组接口,因此可以在任何地方使用它,并且可以使用常规数组的方式。