【问题标题】:What is the fastest way to draw an image from discrete pixel values in Python?在 Python 中从离散像素值绘制图像的最快方法是什么?
【发布时间】:2010-09-30 21:06:21
【问题描述】:

我希望根据计算的像素值绘制图像,作为可视化某些数据的一种方式。本质上,我希望采用一个二维矩阵的颜色三元组并渲染它。

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

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

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

【问题讨论】:

    标签: python image python-imaging-library


    【解决方案1】:

    如果你有 numpyscipy 可用(如果你在 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 可以很好地处理不同的数据类型,因此浮点数的二维数组可以明智地转换为灰度等。

    您可以从here 下载numpyscipy。或者使用 pip:

    pip install numpy scipy
    

    【讨论】:

    • 谢谢。我已经在大量使用 numpy 了 :) 这个指针正是我所需要的。如果这成为瓶颈,我可能会比较速度,但现在这很适合我。
    • 如果您是在科学背景下执行此操作,您还可以使用 matplotlib.pyplot 的“imshow”。它以颜色图和插值方法作为参数,对我很有帮助。
    • 如果我有很多像素怎么办???? 5K左右,这种情况下我的python脚本是什么???
    • "module 'scipy.misc' has no attribute 'toimage'" 直接使用 Pillow 的 Image.fromarray。 (source)
    【解决方案2】:
    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() 会更快。

    【讨论】:

    • 2017年第一行是:from PIL import Image
    【解决方案3】:

    要求

    对于本示例,安装 NumpyPillow

    示例

    目标是首先将您要创建的图像表示为由 3 个 (RGB) 数字组成的数组数组 - 使用 Numpy 的 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 的答案,它太过时而无法使用,而且差异太大,无法在不完全重写的情况下简单地更新。

    【讨论】:

      【解决方案4】:

      另一种方法是使用Pyxel,它是the TIC-80 API 在 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 种颜色,但您可以更改哪些颜色,并且无需太多工作就可以让它支持更多颜色。

      【讨论】:

        【解决方案5】:

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

        您应该通过直接在内存中渲染图片来获得小的速度提升(您将节省将图像写入磁盘然后重新加载它的成本)。看看这个线程https://stackoverflow.com/questions/326300/python-best-library-for-drawing,了解如何使用各种 python 模块渲染该图像。

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

        • 速度
        • 您将能够创建带有参数按钮的交互式用户界面。
        • 您将能够轻松编程放大和缩小功能
        • 您将能够在计算时绘制图像,如果计算需要大量时间,这将非常有用

        【讨论】:

          【解决方案6】:

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

          • setwindowsize( x,y ) - 将窗口大小设置为 x*y
          • drawpixel( 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()
          

          【讨论】:

            猜你喜欢
            • 2012-11-18
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2023-03-10
            相关资源
            最近更新 更多