首页 > 解决方案 > 将大灰度 PIL 图像转换为黑色和透明

问题描述

我正在尝试使用大型二维数组来创建具有黑色和透明部分的图像蒙版。最初,输入二维数组是以灰度 ( ) 模式PIL.Image加载的。'L'所以它包含 0 到 255 之间的值。现在我想用[0,0,0,255](黑色保持黑色)替换所有的 0,并且所有 >0 的值都应该是[0,0,0,0](透明的)。我可以像这样简单地做到这一点:

import numpy as np

# generate some random test data - normally I just read the input image, which is fast
input_data = np.array([np.array([random.choice([0,10]) for x in range(22000)]) for y in range(9000)])

# create a new img containing black and transparent pixels (r,g,b,alpha) and this takes ages
overlay_img = [[[0, 0, 0, 255] if input_data[y][x] == 0 else [0, 0, 0, 0] for x in range(len(input_data[0]))] for y in range(len(input_data))]
overlay_img = np.array(overlay_img)

这需要相当长的时间,因为输入数据太大(~22000x9000)。我很好奇是否有可能更快地做到这一点。我也试过np.where,但我无法让它工作。也许甚至有一种方法可以直接更改 PIL 图像?

仅供参考:最后,我只想在我的 matplotlib 图上绘制这个图像imshow,这样只有相关区域是可见的(图像是透明的),其余区域是隐藏/黑色的。

这里只是我想做的一个非常快速和小例子: 在此处输入图像描述

标签: pythonnumpypython-imaging-library

解决方案


我想你想要这个,但你没有显示你的代码imshow()

#!/usr/bin/env python3

import random
import numpy as np

# Set up dimensions and random input image
h, w = 9000, 22000
im = np.random.randint(0, 11, (h,w), dtype=np.uint8)

# Create 4-channel mask image
mask = np.zeros((h,w,4), dtype=np.uint8)
mask[...,3] = (im==0) * 255

最后一行在我的 MacBook Pro 上需要 800 毫秒。


如果你需要更多的性能,你可以使用numexpr如下,所需的时间是 300 毫秒而不是 800 毫秒:

import random
import numexpr as ne
import numpy as np

# Set up dimensions and random input image
h, w = 9000, 22000
im = np.random.randint(0, 11, (h,w), dtype=np.uint8)

# Create 4-channel mask image
mask = np.zeros((h,w,4), dtype=np.uint8)

# Same but with "numexpr"
mask[...,3] = ne.evaluate("(im==0)*255")

推荐阅读