如何减慢枕头中的图像显示速度

How to slow down image display in Pillow

可能是一个不寻常的问题,但我目前正在寻找一种解决方案,以较慢地显示 PIL 图像文件。 理想情况下,您可以从左到右逐个像素地查看图像是如何构建的。

有没有人知道如何实现这样的东西? 是纯光学的东西,不是必须的。

举个例子:

from PIL import Image

im = Image.open("sample-image.png")

im.show()

有没有办法“慢下来”im.show()

AFAIK,您不能直接使用 PIL 的 Image.show() 执行此操作,因为它实际上会将您的图像作为文件保存到 /var/tmp/XXX,然后将该文件传递给您的 OS 的标准图像查看器显示在屏幕上,之后没有与查看器进程的进一步交互。因此,如果您绘制另一个像素,查看器将不会意识到,如果您再次调用 Image.show(),它将保存图像的新副本并调用另一个查看器,这将为您提供第二个 window而不是更新第一个!

有几种方法可以绕过它:

  • 使用 OpenCV 的 cv2.imshow() 允许更新
  • 使用tkinter显示变化的图像
  • 创建一个动画 GIF 并启动一个新进程来显示它

我选择了第一个,使用 OpenCV,作为阻力最小的路径:

#!/usr/bin/env python3

import cv2
import numpy as np
from PIL import Image

# Open image
im = Image.open('paddington.png')

# Make BGR Numpy version for OpenCV
BGR = np.array(im)[:,:,::-1]
h, w = BGR.shape[:2]

# Make empty image to fill in slowly and display
d = np.zeros_like(BGR)

# Use "x" to avoid drawing and waiting for every single pixel
x=0
for y in range(h):
   for x in range(w):
       d[y,x] = BGR[y,x]
       if x%400==0:
          cv2.imshow("SlowLoader",d)
          cv2.waitKey(1)
       x += 1

# Wait for one final keypress to exit
cv2.waitKey(0)

增加接近末尾的 400 以使其更快并在更多像素后更新屏幕,或减少它以使其在更少像素后更新屏幕,这意味着您会看到它们出现得更慢。

由于我无法在 Whosebug 上分享电影,我制作了一个动画 GIF 来展示它的外观:


我决定也尝试用 tkinter 来做。我不是 tkinter 方面的专家,但下面的代码与上面的代码一样。如果有谁知道tkinter更好,欢迎大家指出我的不足之处~我乐于学习!谢谢。

#!/usr/bin/env python3

import numpy as np
from tkinter import *
from PIL import Image, ImageTk

# Create Tkinter Window and Label
root = Tk()
video = Label(root)
video.pack()

# Open image
im = Image.open('paddington.png')

# Make Numpy version for simpler pixel access
RGB = np.array(im)
h, w = RGB.shape[:2]

# Make empty image to fill in slowly and display
d = np.zeros_like(RGB)

# Use "x" to avoid drawing and waiting for every single pixel
x=0
for y in range(h):
   for x in range(w):
       d[y,x] = RGB[y,x]
       if x%400==0:
          # Convert the video for Tkinter
          img = Image.fromarray(d)
          imgtk = ImageTk.PhotoImage(image=img)
          # Set the image on the label
          video.config(image=imgtk)
          # Update the window
          root.update() 

       x += 1