简体   繁体   English

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

[英]What is the fastest way to draw an image from discrete pixel values in Python?

I wish to draw an image based on computed pixel values, as a means to visualize some data.我希望根据计算出的像素值绘制图像,作为可视化某些数据的一种方式。 Essentially, I wish to take a 2-dimensional matrix of color triplets and render it.本质上,我希望采用彩色三元组的二维矩阵并渲染它。

Do note that this is not image processing, since I'm not transforming an existing image nor doing any sort of whole-image transformations, and it's also not vector graphics as there is no pre-determined structure to the image I'm rendering- I'm probably going to be producing amorphous blobs of color one pixel at a time.请注意,这不是图像处理,因为我没有转换现有图像,也没有进行任何类型的整体图像转换,而且它也不是矢量图形,因为我正在渲染的图像没有预先确定的结构-我可能会一次生成一个像素的无定形颜色斑点。

I need to render images about 1kx1k pixels for now, but something scalable would be useful.我现在需要渲染大约 1kx1k 像素的图像,但是可扩展的东西会很有用。 Final target format is PNG or any other lossless format.最终目标格式是 PNG 或任何其他无损格式。

I've been using PIL at the moment via ImageDraw's draw.point , and I was wondering, given the very specific and relatively basic features I require, is there any faster library available?目前我一直在通过 ImageDraw 的 draw.point 使用 PIL,我想知道,鉴于我需要非常具体和相对基本的功能,是否有任何更快的库可用?

If you have numpy and scipy available (and if you are manipulating large arrays in Python, I would recommend them), then the scipy.misc.pilutil.toimage function is very handy.如果您有可用的numpyscipy (并且如果您在 Python 中操作大型数组,我会推荐它们),那么scipy.misc.pilutil.toimage函数非常方便。 A simple example:一个简单的例子:

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

The nice thing is toimage copes with different data types very well, so a 2D array of floating-point numbers gets sensibly converted to grayscale etc. toimagetoimage可以很好地处理不同的数据类型,因此浮点数的二维数组被明智地转换为灰度等。

You can download numpy and scipy from here .你可以从这里下载numpyscipy Or using pip:或者使用 pip:

pip install numpy scipy
import Image
im= Image.new('RGB', (1024, 1024))
im.putdata([(255,0,0), (0,255,0), (0,0,255)])
im.save('test.png')

Puts a red, green and blue pixel in the top-left of the image.在图像的左上角放置一个红色、绿色和蓝色像素。

im.fromstring() is faster still if you prefer to deal with byte values.如果您更喜欢处理字节值, im.fromstring()仍然更快。

Requirements要求

For this example, install Numpy and Pillow .对于此示例,安装NumpyPillow

Example例子

The goal is to first represent the image you want to create as an array arrays of sets of 3 (RGB) numbers - use Numpy's array() , for performance and simplicity:目标是首先将要创建的图像表示为一组 3 (RGB) 数字集的数组数组 - 使用 Numpy 的array() ,以提高性能和简单性:

import numpy

data = numpy.zeros((1024, 1024, 3), dtype=numpy.uint8)

Now, set the middle 3 pixels' RGB values to red, green, and blue:现在,将中间 3 个像素的 RGB 值设置为红色、绿色和蓝色:

data[512, 511] = [255, 0, 0]
data[512, 512] = [0, 255, 0]
data[512, 513] = [0, 0, 255]

Then, use Pillow's Image.fromarray() to generate an Image from the array:然后,使用 Pillow 的Image.fromarray()从数组生成图像:

from PIL import Image

image = Image.fromarray(data)

Now, "show" the image (on OS X, this will open it as a temp-file in Preview):现在,“显示”图像(在 OS X 上,这将在预览中将其作为临时文件打开):

image.show()

Note笔记

This answer was inspired by BADCODE's answer, which was too out of date to use and too different to simply update without completely rewriting.这个答案的灵感来自 BADCODE 的答案,这个答案已经过时了,无法使用,也太不同了,不能简单地更新而不完全重写。

A different approach is to use Pyxel , an open source implementation of the TIC-80 API in Python3 (TIC-80 is the open source PICO-8).一种不同的方法是使用Pyxel ,它是Python3 中TIC-80 API 的开源实现(TIC-80 是开源 PICO-8)。

Here's a complete app that just draws one yellow pixel on a black background:这是一个完整的应用程序,它只在黑色背景上绘制一个黄色像素:

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)

Note : The library only allows for up to sixteen colors, but you can change which colors, and you could probably get it to support more without too much work.注意:该库最多只允许 16 种颜色,但是您可以更改哪些颜色,并且您可能无需太多工作就可以让它支持更多颜色。

I think you use PIL to generate an image file on the disk, and you later load it with an image reader software.我想你使用PIL在磁盘上生成一个图像文件,然后你用一个图像阅读器软件加载它。

You should get a small speed improvement by rendering directly the picture in memory (you will save the cost of writing the image on the disk and then re-loading it).您应该通过直接在内存中渲染图片来获得小的速度提升(您将节省将图像写入磁盘然后重新加载的成本)。 Have a look at this thread https://stackoverflow.com/questions/326300/python-best-library-for-drawing for how to render that image with various python modules.查看此线程https://stackoverflow.com/questions/326300/python-best-library-for-drawing了解如何使用各种 python 模块渲染该图像。

I would personally try wxpython and the dc.DrawBitmap function.我会亲自尝试 wxpython 和dc.DrawBitmap函数。 If you use such a module rather than an external image reader you will have many benefits:如果您使用这样的模块而不是外部图像阅读器,您将获得许多好处:

  • speed速度
  • you will be able to create an interactive user interface with buttons for parameters.您将能够创建带有参数按钮的交互式用户界面。
  • you will be able to easily program a Zoomin and Zoomout function您将能够轻松编程 Zoomin 和 Zoomout 功能
  • you will be able to plot the image as you compute it, which can be quite useful if the computation takes a lot of time您将能够在计算时绘制图像,如果计算需要大量时间,这将非常有用

You can use the turtle module if you don't want to install external modules.如果不想安装外部模块,可以使用turtle模块。 I created some useful functions:我创建了一些有用的函数:

  • setwindowsize( x,y ) - sets the window size to x*y setwindowsize( x,y ) - 将窗口大小设置为 x*y
  • drawpixel( x, y, (r,g,b), pixelsize) - draws a pixel to x:y coordinates with an RGB color (tuple), with pixelsize thickness drawpixel( x, y, (r,g,b), pixelsize) - 使用 RGB 颜色(元组)将像素绘制到 x:y 坐标,像素大小的厚度
  • showimage() - displays image 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()

Examples:例子:

200x200 window, 1 red pixel in the center 200x200 窗口,中心有 1 个红色像素

setwindowsize(200, 200)
drawpixel(100, 100, (255,0,0) )
showimage()

在此处输入图片说明

30x30 random colors. 30x30 随机颜色。 Pixel size: 10像素大小: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()

在此处输入图片说明

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 在 Python 中重新映射 OpenCV 中的像素值的最快方法是什么? - What's the fastest way to remap pixel values in OpenCV in Python? 在 tkinter 上绘制像素的最快方法 - Fastest way to draw a pixel on tkinter 在Gtk +中绘制图像的最快方法是什么? - What is the fastest way to draw an image in Gtk+? 在Python中为图像中的每个像素选择7 * 7个相邻像素的最快方法 - fastest way to select 7*7 neighbor pixels for every pixel in an image in Python 在 Python 中查找图像像素和调色板颜色之间差异的最快方法 - Fastest way to find difference between image pixel and palette colour in Python 在Python中生成图像缩略图的最快方法是什么? - What is the fastest way to generate image thumbnails in Python? 在python中旋转图像的最快方法是什么? - What is the fastest way to rotate image in python? 在Python中扩展和显示图像的最快方法是什么? - What is the fastest way to scale and display an image in Python? 用python绘制多边形的最快方法 - The fastest way to draw polygons with python 最有效的方法是在 Python 中使用海龟绘制像素? - What would the most efficient way be to draw a pixel using turtle in Python?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM