python-3.x - 在 PIL 图像的每个像素上应用函数的快速方法
问题描述
我需要对大 PIL
图像中的每个像素应用一个函数。我在这里发现了类似的问题,但不知何故,这些答案对我来说从来没有用过(主要是因为它们是特定于函数的)。
用两个 for 循环遍历每个像素是可行的,但速度非常慢。所以我想,可能有一种更快的方法,比如numpy.apply_along_axis
矢量化。但是,第一个也很慢,我无法让第二个工作。我很感激任何建议!
from PIL import Image
import numpy as np
# example functions to be applied on each pixel RGB value
# (lets just imagine for now, that l and r cannot be 0)
def blueness(rgb):
r, g, b = int(rgb[0]), int(rgb[1]), int(rgb[2])
l = (r+g+b)/3
return (b/r)*(1/l)*100
input_path = 'input.png'
img = Image.open(input_path)
img_np = np.asarray(orig_img)
h, w, z = img_np.shape
converted_img = np.zeros((h, w))
# apply blueness on img_np
for x in range(w):
for y in range(h):
converted_img[y, x] = blueness(img_np[y, x])
解决方案
一般来说,如果您考虑将图像转换为列表并for
在 Python 中使用循环,您可能已经出错了。你真的需要用 Numpy 或 Numba 或类似的东西进行矢量化numexpr
。
这是对您的功能执行此操作的一种方法:
#!/usr/bin/env python3
import numpy as np
def loopy(na):
# Create output image in greyscale
res = np.zeros_like(na[..., 0])
# apply blueness on na
for x in range(w):
for y in range(h):
res[y, x] = blueness(na[y, x])
return res
def blueness(rgb):
r, g, b = int(rgb[0]), int(rgb[1]), int(rgb[2])
l = (r+g+b)/3
return (b/r)*(1/l)*100
def me(na):
# Take mean of RGB values
l = np.mean(na, axis=2)
res = (na[..., 2] / na[..., 0]) * 100/l
return res.astype(np.uint8)
# Guess the height and width
h, w = 1080, 1920
# Create a random image in Numpy array
na = np.random.randint(1,256, (h,w,3), np.uint8)
# Double for loop method
res1 = loopy(na)
# Numpy method
res2 = me(na)
这是结果。Numpy 大约快 65 倍:
%timeit me(na)
37 ms ± 523 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
%timeit loopy(na)
2.36 s ± 11.9 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
推荐阅读
- javascript - JavaScript 将平面数组转换为嵌套/分组和排序数组
- azureservicebus - 为什么消息锁过期后Azure Servicebus触发函数立即调用?
- javascript - Mongodb错误码和对应的http状态码
- python - 从 yahoo Finance 检索 ESG 分数
- reactjs - useEffect 无限循环仅在测试时发生,否则不会发生 - 尽管使用了 useReducer
- git - 无法从远程存储库克隆项目
- discord.py-rewrite - Mongo db 不会连接我的代码或写入数据库
- jenkins - 我想在我公司的帐户上安装一个 Jenkins 插件,但不确定重启状态?
- c++ - 初学者 C++ 构造错误。我想不通
- python - 正则表达式仅在字符串之前查找有限的值