numpy Python中的GUI性能(速度)

hec6srdp  于 2022-12-23  发布在  Python
关注(0)|答案(1)|浏览(128)

我目前正在用Python开发一个GUI,重点关注一个函数,该函数应该显示图像A覆盖图像B的方形框架的擦除动画。
虽然我的代码片段中没有语法错误,但我遇到了一些性能问题。
首先,关于图像过渡的速度,如果我将“after”方法的第一个参数设置为最小整数值1,过渡仍然显得有点慢。

def wipe():
        ImageA_Width, ImageA_Height = img.size
        data_A_norm = asarray(img2)
        data_B_norm = asarray(img)

        def get_frame(frame_number):
            frame = np.ones((ImageA_Width, ImageA_Height, 3))
            for x in range(0, ImageA_Width):
                for y in range(0, ImageA_Height):
                    if x < frame_number: 
                        frame[y,x] = data_A_norm[y,x]
                    else:
                        frame[y,x] = data_B_norm[y,x]
            return frame
        
       def show_frame(frame_number):
           global shot, label3
           if frame_number < ImageA_Width+1:
              frame = get_frame(frame_number)
              image_opened = Image.fromarray(frame.astype(np.uint8))
              shot = ImageTk.PhotoImage(image_opened)
              label3 = Label(window, image=shot)
              label3.place(x=800, y=200)
              label3.after(1, show_frame, frame_number+1)
        
      show_frame(0)

我发现,如果在每次迭代中将图像存储在列表中,而不是存储在变量中,则可以减少动画所花费的时间。
这种方法真的会提高我的性能吗?如果是的话,在Python中如何实现呢?

pbgvytdp

pbgvytdp1#

试试这个:

import numpy as np
from PIL import Image, ImageTk

def wipe():
    # Load the images into numpy arrays
    data_A_norm = np.asarray(img2)
    data_B_norm = np.asarray(img)

    # Get the size of the images
    image_width, image_height = img.size

    def get_frame(frame_number):
        # Create an empty frame
        frame = np.ones((image_width, image_height, 3), dtype=np.uint8)

        # Use a mask to select which pixels should come from each image
        mask = np.arange(image_width) < frame_number
        frame[:,:,0] = data_A_norm[:,:,0] * mask + data_B_norm[:,:,0] * (1 - mask)
        frame[:,:,1] = data_A_norm[:,:,1] * mask + data_B_norm[:,:,1] * (1 - mask)
        frame[:,:,2] = data_A_norm[:,:,2] * mask + data_B_norm[:,:,2] * (1 - mask)

        return frame
        
    def show_frame(frame_number):
        global shot, label3
        if frame_number < image_width + 1:
            # Get the next frame and display it
            frame = get_frame(frame_number)
            image_opened = Image.fromarray(frame)
            shot = ImageTk.PhotoImage(image_opened)
            label3 = Label(window, image=shot)
            label3.place(x=800, y=200)

            # Call this function again after a delay
            label3.after(50, show_frame, frame_number + 1)
    
    # Start the animation
    show_frame(0)

此版本的代码有一些更改:
get_frame函数使用numpy的矢量化操作来选择每个图像中的像素,这比使用嵌套的for循环要快得多。
show_frame函数的调用速度较慢,使用50毫秒而不是1毫秒的延迟,这应该允许get_frame函数跟上帧速率。
fromarray函数用于将numpy数组转换回PIL图像,这应该比单独使用Image和ImageTk库要快。

相关问题