为了账号安全,请及时绑定邮箱和手机立即绑定

Python 3.7:多处理具有共享变量的 for 循环

Python 3.7:多处理具有共享变量的 for 循环

RISEBY 2021-11-16 16:42:02
首先是一些上下文:我正在尝试写下一个 python 脚本,将灰度 (.tif) 中的图像转换为具有所谓“jet”颜色图的 .jpeg。我设法用 for 循环来做到这一点,但对于一张图像(处理数百万像素!)来说有点长,所以我想使用多处理。我的问题是,要将每个灰色像素转换为彩色像素,我必须使用两个变量(光强度的最小值“min_img”和向量“dx_cm”从初始灰度到 256比例,对应于 jet 颜色图)。因此,为了将“min_img”和“dx_cm”的信息传递给进程,我尝试使用 multiprocessing.Value() 但作为回报,我得到了错误:RuntimeError: Synchronized objects should only be shared between processes through inheritance我尝试了来自不同来源的许多不同的东西,无论我的代码版本如何,我都在为该错误而苦苦挣扎。因此,如果我的代码不干净,我很抱歉,如果有人可以帮助我,我将不胜感激。我的非工作代码:import multiprocessingfrom PIL import Imagefrom matplotlib import cmdef fun(gr_list,dx,minp):    dx_cmp = dx.value    min_imgp = minp.value    rgb_res=list()    for i in range(len(gr_list)):        rgb_res.extend(cm.jet(round(((gr_list[i]-min_imgp)/dx_cmp)-1))[0:-1])    return rgb_resif __name__ == '__main__':    RGB_list=list()    n = multiprocessing.cpu_count()    img = Image.open(r'some_path_to_a.tif')    Img_grey=list(img.getdata())    dx_cm = multiprocessing.Value('d',(max(Img_grey)-min(Img_grey))/256)    min_img = multiprocessing.Value('d',min(Img_grey))    with multiprocessing.Pool(n) as p:        RGB_list = list(p.map(fun, (Img_grey,dx_cm,min_img)))    res = Image.frombytes("RGB", (img.size[0], img.size[1]), bytes([int(0.5 + 255*i) for i in RGB_list]))        res.save('rgb_file.jpg')PS:这是我想要并行化的初始 for 循环的示例:from PIL import Imagefrom matplotlib import cmif __name__ == '__main__':    img = Image.open(r'some_path_to_a.tif')    Img_grey = list(img.getdata())    dx_cm = (max(Img_grey)-min(Img_grey))/256    min_img = min(Img_grey)    Img_rgb = list()    for i in range(len(Img_grey)):        Img_rgb.extend(cm.jet(round(((Img_grey[i]-min_img)/dx_cm)-1))[0:-1])    res = Image.frombytes("RGB", (img.size[0], img.size[1]), bytes([int(0.5 + 255*i) for i in Img_rgb]))        res.save('rgb_file.jpg')
查看完整描述

2 回答

?
梵蒂冈之花

TA贡献1900条经验 获得超5个赞

您的fun方法正在遍历某个列表,但在这种情况下,它将接收一个“部分”,即您列表中的一个项目,因此它应该只返回其处理结果。


我已将工作代码更改为与多处理一起运行。


由于该fun方法返回一个列表,因此p.map将返回一个列表列表(结果列表)并且需要展平,extends之前使用 list方法完成。


尝试使用进程池和线程池多处理,在我的场景中没有任何性能提升。


进程多处理:

from PIL import Image

from matplotlib import cm

import multiprocessing



def fun(d):

    part, dx_cm, min_img = d

    return cm.jet(round(((part-min_img)/dx_cm)-1))[0:-1]


if __name__ == '__main__':

    img = Image.open(r'a.tif')

    Img_grey = list(img.getdata())


    def Gen(img_data):

        dx_cm = (max(img_data)-min(img_data))/256

        min_img = min(img_data)

        for part in img_data:

            yield part, dx_cm, min_img


    n = multiprocessing.cpu_count()

    with multiprocessing.Pool(n) as p:

        Img_rgb = [item for sublist in p.map(fun, Gen(Img_grey)) for item in sublist]


    res = Image.frombytes("RGB", (img.size[0], img.size[1]), bytes([int(0.5 + 255*i) for i in Img_rgb]))    

    res.save('b.jpg')

线程多处理:

from PIL import Image

from matplotlib import cm

import multiprocessing

from multiprocessing.pool import ThreadPool


if __name__ == '__main__':

    img = Image.open(r'a.tif')

    Img_grey = list(img.getdata())

    dx_cm = (max(Img_grey)-min(Img_grey))/256

    min_img = min(Img_grey)


    def fun(part):

        return cm.jet(round(((part-min_img)/dx_cm)-1))[0:-1]


    n = multiprocessing.cpu_count()

    with ThreadPool(n) as p:

        Img_rgb = [item for sublist in p.map(fun, Img_grey) for item in sublist]


    res = Image.frombytes("RGB", (img.size[0], img.size[1]), bytes([int(0.5 + 255*i) for i in Img_rgb]))    

    res.save('b.jpg')


查看完整回答
反对 回复 2021-11-16
?
心有法竹

TA贡献1866条经验 获得超5个赞

因此,对于多处理而言,计算负担似乎还不够大。


尽管如此,对于那些对我的问题的图像处理部分感兴趣的主题的人,我发现了另一种更快的方法(比以前的方法快 15 到 20 倍)在没有 for 循环的情况下做同样的事情:


from matplotlib import cm

import matplotlib.pyplot as plt

from mpl_toolkits.axes_grid1 import make_axes_locatable

import numpy as np

from PIL import Image


cm_jet = cm.get_cmap('jet')

img_src = Image.open(r'path to your grey image')

img_src.mode='I'


Img_grey = list(img_src.getdata())

max_img = max(Img_grey)

min_img = min(Img_grey)


rgb_array=np.uint8(cm_jet(((np.array(img_src)-min_img)/(max_img-min_img)))*255)


ax = plt.subplot(111)

im = ax.imshow(rgb_array, cmap='jet')


divider = make_axes_locatable(ax)

cax_plot = divider.append_axes("right", size="5%", pad=0.05)


cbar=plt.colorbar(im, cax=cax_plot, ticks=[0,63.75,127.5,191.25,255])

dx_plot=(max_img-min_img)/255

cbar.ax.set_yticklabels([str(min_img),str(round(min_img+63.75*dx_plot)),str(round(min_img+127.5*dx_plot)),str(round(min_img+191.25*dx_plot)), str(max_img)])


ax.axes.get_xaxis().set_visible(False)

ax.axes.get_yaxis().set_visible(False)


plt.savefig('test_jet.jpg', quality=95, dpi=1000)


查看完整回答
反对 回复 2021-11-16
  • 2 回答
  • 0 关注
  • 151 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信