我希望根据计算出的像素值绘制图像,作为可视化某些数据的方法。基本上,我希望采用二维矩阵颜色三元组并渲染它。
请注意,这不是图像处理,因为我没有变换现有图像,也没有进行任何形式的全图像变换,而且它也不是矢量图形,因为图像没有预先确定的结构。渲染 - 我可能会一次生成一个像素的无定形斑点。
我现在需要渲染大约1kx1k像素的图像,但可伸缩的东西会很有用。最终目标格式是PNG或任何其他无损格式。
我目前通过ImageDraw的draw.point一直在使用PIL,我想知道,鉴于我需要的非常具体和相对基本的功能,是否有更快的库可用?
答案 0 :(得分:33)
如果你有numpy
和scipy
可用(如果你在Python中操作大型数组,我会推荐它们),那么scipy.misc.pilutil.toimage
函数非常方便。
一个简单的例子:
import numpy as np
import scipy.misc as smp
# Create a 1024x1024x3 array of 8 bit unsigned integers
data = np.zeros( (1024,1024,3), dtype=np.uint8 )
data[512,512] = [254,0,0] # Makes the middle pixel red
data[512,513] = [0,0,255] # Makes the next pixel blue
img = smp.toimage( data ) # Create a PIL image
img.show() # View in default viewer
好处是toimage
能够很好地处理不同的数据类型,因此浮点数的2D数组可以合理地转换为灰度等。
您可以从here下载numpy
和scipy
。或者使用pip:
pip install numpy scipy
答案 1 :(得分:16)
import Image
im= Image.new('RGB', (1024, 1024))
im.putdata([(255,0,0), (0,255,0), (0,0,255)])
im.save('test.png')
在图像的左上角放置一个红色,绿色和蓝色像素。
如果您更喜欢处理字节值, im.fromstring()
会更快。
答案 2 :(得分:2)
目标是首先将您想要创建的图像表示为3(RGB)数字组的数组 - 使用Numpy' s array()
,以提高性能和简单性:
import numpy
data = numpy.zeros((1024, 1024, 3), dtype=numpy.uint8)
现在,设置中间的3个像素' RGB值为红色,绿色和蓝色:
data[512, 511] = [255, 0, 0]
data[512, 512] = [0, 255, 0]
data[512, 513] = [0, 0, 255]
然后,使用Pillow的Image.fromarray()
从数组生成一个Image:
from PIL import Image
image = Image.fromarray(data)
现在,"显示"图像(在OS X上,这将在预览中将其作为临时文件打开):
image.show()
这个答案的灵感来自于BADCODE的答案,这个答案太过时而无法使用,而且不完全改写而不完全重写。
答案 3 :(得分:2)
另一种方法是使用Pyxel,这是Python3中the TIC-80 API的开源实现(TIC-80是开源PICO-8)。
这是一个完整的应用程序,仅在黑色背景上绘制一个黄色像素:
import pyxel
def update():
"""This function just maps the Q key to `pyxel.quit`,
which works just like `sys.exit`."""
if pyxel.btnp(pyxel.KEY_Q): pyxel.quit()
def draw():
"""This function clears the screen and draws a single
pixel, whenever the buffer needs updating. Note that
colors are specified as palette indexes (0-15)."""
pyxel.cls(0) # clear screen (color)
pyxel.pix(10, 10, 10) # blit a pixel (x, y, color)
pyxel.init(160, 120) # initilize gui (width, height)
pyxel.run(update, draw) # run the game (*callbacks)
注意:该库最多只能提供16种颜色,但是您可以更改哪些颜色,并且可能不需要太多工作就可以支持它。
答案 4 :(得分:1)
我认为您使用PIL在磁盘上生成图像文件,稍后使用图像阅读器软件加载它。
通过直接在内存中渲染图片,您可以获得较小的速度提升(您将节省在磁盘上写入图像然后重新加载图像的成本)。看看这个线程https://stackoverflow.com/questions/326300/python-best-library-for-drawing,了解如何使用各种python模块渲染该图像。
我个人会尝试使用wxpython和 dc.DrawBitmap 函数。如果您使用这样的模块而不是外部图像阅读器,您将获得许多好处:
答案 5 :(得分:0)
如果您不想安装外部模块,可以使用 turtle
模块。我创建了一些有用的函数:
setwindowsize( x,y )
- 将窗口大小设置为 x*ydrawpixel( x, y, (r,g,b), pixelsize)
- 使用 RGB 颜色(元组)将像素绘制到 x:y 坐标,像素大小厚度showimage()
- 显示图像import turtle
def setwindowsize(x=640, y=640):
turtle.setup(x, y)
turtle.setworldcoordinates(0,0,x,y)
def drawpixel(x, y, color, pixelsize = 1 ):
turtle.tracer(0, 0)
turtle.colormode(255)
turtle.penup()
turtle.setpos(x*pixelsize,y*pixelsize)
turtle.color(color)
turtle.pendown()
turtle.begin_fill()
for i in range(4):
turtle.forward(pixelsize)
turtle.right(90)
turtle.end_fill()
def showimage():
turtle.hideturtle()
turtle.update()
示例:
200x200 窗口,中心有 1 个红色像素
setwindowsize(200, 200)
drawpixel(100, 100, (255,0,0) )
showimage()
30x30 随机颜色。像素大小:10
from random import *
setwindowsize(300,300)
for x in range(30):
for y in range(30):
color = (randint(0,255),randint(0,255),randint(0,255))
drawpixel(x,y,color,10)
showimage()