在Python中,从离散像素值绘制图像的最快方法是什么?

在Python中,从离散像素值绘制图像的最快方法是什么?,python,image,python-imaging-library,Python,Image,Python Imaging Library,我希望根据计算出的像素值绘制一幅图像,作为可视化某些数据的手段。本质上,我希望得到一个二维的三色矩阵并进行渲染 请注意,这不是图像处理,因为我没有变换现有图像,也没有进行任何类型的整体图像变换,它也不是矢量图形,因为我渲染的图像没有预先确定的结构-我可能会一次生成一个像素的无定形颜色斑点 我现在需要渲染大约1kx1k像素的图像,但是一些可伸缩的东西会很有用。最终目标格式为PNG或任何其他无损格式 目前我一直在通过ImageDraw的draw.point使用PIL,我想知道,鉴于我所需要的非常具体

我希望根据计算出的像素值绘制一幅图像,作为可视化某些数据的手段。本质上,我希望得到一个二维的三色矩阵并进行渲染

请注意,这不是图像处理,因为我没有变换现有图像,也没有进行任何类型的整体图像变换,它也不是矢量图形,因为我渲染的图像没有预先确定的结构-我可能会一次生成一个像素的无定形颜色斑点

我现在需要渲染大约1kx1k像素的图像,但是一些可伸缩的东西会很有用。最终目标格式为PNG或任何其他无损格式


目前我一直在通过ImageDraw的draw.point使用PIL,我想知道,鉴于我所需要的非常具体和相对基本的功能,是否有更快的库可用?

我认为您可以使用PIL在磁盘上生成图像文件,然后使用图像读取器软件加载它

通过在内存中直接渲染图片,您应该可以获得一点速度提升(这样可以节省将图像写入磁盘然后重新加载的成本)。看看这个线程,了解如何使用各种python模块呈现该图像

我个人会尝试wxpython和dc.DrawBitmap函数。如果您使用这样的模块而不是外部图像读取器,您将获得许多好处:

  • 速度
  • 您将能够创建带有参数按钮的交互式用户界面
  • 您将能够轻松编程Zoomin和Zoomout功能
  • 您将能够在计算图像时绘制图像,如果计算需要大量时间,这将非常有用
将红色、绿色和蓝色像素放置在图像的左上角


如果您喜欢处理字节值,
im.fromstring()
速度更快。

如果您有可用的
numpy
scipy
(如果您在Python中操作大型数组,我推荐它们),那么该函数非常方便。 一个简单的例子:

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数组可以被合理地转换为灰度等

您可以从下载
numpy
scipy
。或使用pip:

pip install numpy scipy
要求 对于本例,请安装并安装

例子 目标是首先将要创建的图像表示为一组3(RGB)数字的数组-为了性能和简单性,请使用Numpy:

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]
然后,使用枕头从阵列生成图像:

from PIL import Image

image = Image.fromarray(data)
现在,“显示”图像(在OS X上,这将在预览中将其作为临时文件打开):


这个答案的灵感来源于BADCODE的答案,它太过时了,无法使用,也太不同了,无法在不完全重写的情况下简单地进行更新。

另一种方法是使用Python3中的开源实现(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种颜色,但您可以更改哪些颜色,并且您可以让它支持更多颜色,而无需做太多工作。

如果不想安装外部模块,您可以使用
Turl
模块。我创建了一些有用的函数:

  • setWindowsSize(x,y)
    -将窗口大小设置为x*y
  • drawpixel(x,y,(r,g,b),pixelsize)
    -使用RGB颜色(元组)和pixelsize厚度将像素绘制到x:y坐标
  • showimage()
    -显示图像
导入海龟
def设置窗口大小(x=640,y=640):
海龟。设置(x,y)
海龟。设定世界坐标(0,0,x,y)
def drawpixel(x、y、颜色、pixelsize=1):
海龟追踪器(0,0)
海龟色模式(255)
乌龟
turtle.setpos(x*像素大小,y*像素大小)
海龟。颜色(颜色)
乌龟
乌龟,开始填充
对于范围(4)中的i:
海龟。前进(像素大小)
乌龟,对(90)
乌龟
def showimage():
乌龟
tutle.update()
示例:

200x200窗口,中间有一个红色像素

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()

谢谢。我已经在大量使用numpy:)这个指针正是我所需要的。如果这成为一个瓶颈,我可能会比较速度,但现在这很适合我。如果你是在科学背景下做这件事,你也可以使用matplotlib.pyplot的“imshow”。它以colormap和插值方法作为参数,对我很有用。toimage现在不推荐使用:如果我有很多像素怎么办????5K左右,在这种情况下,我的python脚本将是什么??“模块'scipy.misc'没有属性'toimage'”直接使用Pillow的Image.fromarray。()2017年,第一行是:来自PIL进口图像
setwindowsize(200, 200)
drawpixel(100, 100, (255,0,0) )
showimage()
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()