PIL-对每个像素执行相同的操作 [英] PIL - apply the same operation to every pixel

查看:107
本文介绍了PIL-对每个像素执行相同的操作的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我创建图像并填充像素:

I create an image and fill the pixels:

img = Image.new( 'RGB', (2000,2000), "black") # create a new black image
pixels = img.load() # create the pixel map

for i in range(img.size[0]):    # for every pixel:
    for j in range(img.size[1]):
      #do some stuff that requires i and j as parameter

这可以做得更优雅(并且可能更快,因为从理论上讲循环是可并行的)?

Can this be done more elegant (and may be faster, since theoretically the loops are parallelizable)?

推荐答案

注意:我将首先回答这个问题,然后提出我认为更好的替代方法

在不知道您打算应用哪些更改以及将图像作为PIL图像加载是问题的一部分还是给定的基础上给出建议是很困难的.

It is hard to give advice without knowing what changes you intend to apply and whether the loading of the image as a PIL image is part of the question or a given.

  • 用Python讲得更优雅通常意味着使用列表理解
  • 对于并行化,您可以使用类似 multiprocessing 模块或 joblib
  • More elegant in Python-speak typically means using list comprehensions
  • For parallelization, you would look at something like the multiprocessing module or joblib

取决于您创建/加载图像的方法,您可能会对list_of_pixels = list(img.getdata())img.putdata(new_list_of_pixels)功能感兴趣.

Depending on your method of creating / loading in images, the list_of_pixels = list(img.getdata()) and img.putdata(new_list_of_pixels) functions may be of interest to you.

示例如下:

from PIL import Image
from multiprocessing import Pool

img = Image.new( 'RGB', (2000,2000), "black")

# a function that fixes the green component of a pixel to the value 50
def update_pixel(p):
    return (p[0], 50, p[2])

list_of_pixels = list(img.getdata())
pool = Pool(4)
new_list_of_pixels = pool.map(update_pixel, list_of_pixels)
pool.close()
pool.join()
img.putdata(new_list_of_pixels)

但是,我认为这不是一个好主意...当您看到Python中成千上万个元素的循环(和列表理解)并且您对性能有所了解时,可以确定有一个库可以可以使速度更快.

However, I don't think that is a good idea... When you see loops (and list comprehensions) over thousands of elements in Python and you have performance on your mind, you can be sure there is a library that will make this faster.

首先,它是指向渠道运营"模块, 由于您没有指定要执行的像素操作类型,并且您已经清楚地了解了PIL库,因此我假设您已经了解了PIL库,并且它没有执行您想要的操作.

First, a quick pointer to the Channel Operations module, Since you don't specify the kind of pixel operation you intend to do and you clearly already know about the PIL library, I'll assume you're aware of it and it doesn't do what you want.

然后,使用 Pandas Numpy Scipy ...

Then, any moderately complex matrix manipulation in Python will benefit from pulling in Pandas, Numpy or Scipy...

纯数字示例:

import numpy as np
import matplotlib.pyplot as plt
#black image
img = np.zeros([100,100,3],dtype=np.uint8)
#show
plt.imshow(img)
#make it green
img[:,:, 1] = 50
#show
plt.imshow(img)

由于您只使用标准的numpy.ndarray,因此可以使用任何可用的功能,例如np.vectorize,apply,map等.要使用update_pixel函数显示与上述类似的解决方案:

Since you are just working with a standard numpy.ndarray, you can use any of the available functionalities, such as np.vectorize, apply, map etc. To show a similar solution as above with the update_pixel function:

import numpy as np
import matplotlib.pyplot as plt
#black image
img = np.zeros([100,100,3],dtype=np.uint8)
#show
plt.imshow(img)
#make it green
def update_pixel(p):
    return (p[0], 50, p[2])
green_img = np.apply_along_axis(update_pixel, 2, img)
#show
plt.imshow(green_img)

另一个示例,这次直接从索引而不是从现有图像像素内容中计算图像内容(无需先创建空白图像):

One more example, this time calculating the image content directly from the indexes, instead of from existing image pixel content (no need to create an empty image first):

import numpy as np
import matplotlib.pyplot as plt

def calc_pixel(x,y):
    return np.array([100-x, x+y, 100-y])

img = np.frompyfunc(calc_pixel, 2, 1).outer(np.arange(100), np.arange(100))    
plt.imshow(np.array(img.tolist()))
#note: I don't know any other way to convert a 2D array of arrays to a 3D array...

而且,很低级,scipy具有读取和写入图像的方法,在这两者之间,您可以使用numpy将它们作为经典"多维数组进行操作. (顺便说一下,scipy.misc.imread取决于PIL)

And, low and behold, scipy has methods to read and write images and inbetween, you can just use numpy to manipulate them as "classic" mult-dimensional arrays. (scipy.misc.imread depends on PIL, by the way)

更多示例代码.

这篇关于PIL-对每个像素执行相同的操作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆