首页 > 解决方案 > 功能修改原图

问题描述

我正在将 OpenCV 与 Python 一起使用,并且正在尝试使用多进程来处理图像。图像是100x100,我已经启动了 4 个进程。整个图像一分为四。这是一个过程:

processes = []
_ = mp.Process(target=kill, args=[blue[0:40, 0:47],0, 2])
_.start()
processes.append(_)

在此之后,我只是加入所有流程。

这是我的功能:

def kill(sliced, idx, perc):
    for i in range (0, sliced.shape[0]):
        for j in range (0, sliced.shape[1]):
            if perc* sliced[i][j][0] - sliced[i][j][1] - sliced[i][j][2] < 0:
                for k in range(0, 3):
                    sliced[i][j][k] = 0  #I am expecting this to alter my "blue" image

所以我期待下一个,如果我cv2.imshow("blue", blue)要看到一个像素变黑的图像。问题是这似乎没有修改原始blue图像。

我正在向我的每个进程传递一个切片图像。完成这些过程后,我期待我的原始图像被修改,而不是它没有被改变。传递切片图像并对其进行修改不应修改我的原始图像?有没有复制/缓冲的东西?

标签: pythonopencvimage-processing

解决方案


多处理是 IMO 真的不适合这样的事情,它最好用于一次处理多个独立的图像。它产生单独的进程,这意味着没有共享内存,数据需要从一个进程“发送”到另一个进程,这会产生开销。因此最好将其用于完全独立的处理操作。此外,生成过程需要时间,您正在实施的非常简单的操作无法证明这一点。

您可以在没有循环的情况下实现您的操作,从而获得非常重要的导入速度提升(至少 2 个数量级)。希望这使得不必使用多个内核。

假设image是一个通过 OpenCV 读入的 NumPy 数组:

mask = perc * image[:,:,0] - image[:,:,1] - image[:,:,2] < 0
image[np.broadcast_to(mask[:,:,np.newaxis], image.shape)] = 0

第二行相当复杂,因为mask是 2D 矩阵,但是image是 3D 矩阵。因此,我们需要扩展为 3D,并且与沿新的三维复制它mask的大小相同。是 2D 矩阵的 3D 版本,添加大小为 1 的第三维。然后将大小为 1 的维度复制到请求的形状,. 此扩展掩码现在可用于索引. 通过使用掩码(布尔矩阵)进行索引,我们仅选择where is的那些矩阵元素。因此,分配只改变选定的像素。imagemask[:,:,np.newaxis]np.broadcast_to()image.shapeimageimagemaskTrue


另一个使用 NumPy 加速 Python 循环的重要工具是Numba。如果一个操作不能很容易地向量化,那就是尝试的方法。


推荐阅读