代码之家  ›  专栏  ›  技术社区  ›  Gordon13

在tkinter中显示numpy数组图像时,图像被破坏

  •  0
  • Gordon13  · 技术社区  · 2 年前

    我试图将代码按程序生成的图像显示到画布对象中。我不想使用canvas函数来生成这些图像,因为没有好的方法(截图和重影脚本方法不好)从canvas中获取像素数据。

    我四处寻找生成图像像素的方法,最终选择了scikit图像,然后你可以将数组作为数据加载到tkinter中的图像对象中。

    左侧是使用matplotlib显示的像素数据,右侧是tkinter画布,其显示的数据与PhotoImage相同。

    很明显有些不对劲。

    enter image description here

    这是我的代码:

    from skimage.draw import polygon
    from PIL import Image, ImageTk
    
    import matplotlib.pyplot as plt
    
    import tkinter as tk
    import numpy as np
    
    def generate():
        
        # clear canvas
        canvas.delete("all")
    
        # make clean array
        img = np.ones((width, height, 3), dtype=np.double) * 0.75
    
        # randomly generate positions
        x_generated = np.random.uniform(0, width, 5)
        y_generated = np.random.uniform(0, height, 5)
        
        for x, y in zip(x_generated, y_generated):
            base_height = 70
            base_width = 70
    
            # generate the corners
            x0 = x - base_width/2
            x1 = x + base_width/2
            y0 = y - base_height/2
            y1 = y + base_height/2
    
            # create rectangle
            poly = np.array((
                (x0, y0),
                (x1, y0),
                (x1, y1),
                (x0, y1),
            ))
    
            rr, cc = polygon(poly[:, 0], poly[:, 1], img.shape)
            img[rr, cc, :] = 0.5
    
            # # canvas method. I don't want to use this!
            # canvas.create_rectangle(x0, y0, x1, y1, fill="red", outline="")
        
        # display generated image in tkinter canvas
        scaled_to_8bit = img * 255
        imgarray = ImageTk.PhotoImage(image=Image.fromarray(scaled_to_8bit, 'RGB'))
    
        # create the canvas image object from the numpy array
        canvas.create_image(20, 20, anchor="nw", image=imgarray)
        
        # display pixel data for debugging
        plt.imshow(img)
        plt.show()
    
    
    
    if __name__ == "__main__":
        width = 1000
        height = 1000
    
        # Create a root window
        root = tk.Tk()
        root.configure(background="green")
    
        # Create a canvas widget
        canvas = tk.Canvas(root, width=width, height=height)
        canvas.pack()
    
        # Create a button widget
        button = tk.Button(root, text="Generate", command=generate)
        button.pack()
    
        # start main tk loop
        root.mainloop()
    
    1 回复  |  直到 2 年前
        1
  •  2
  •   Gordon13    2 年前

    空白图像数组的数据类型是double,但图像对象不支持该格式。在显示图像之前,我将其转换为8位数据类型,这解决了问题。

    注意:当matplotlib窗口关闭时,仍然存在图像消失的问题,但这是一个单独的问题

    from skimage.draw import polygon
    from PIL import Image, ImageTk
    
    import matplotlib.pyplot as plt
    
    import tkinter as tk
    import numpy as np
    
    def generate():
        
        # clear canvas
        canvas.delete("all")
    
        # make clean array
        img = np.ones((width, height, 3), dtype=np.float32) * 0.75
    
        # randomly generate positions
        x_generated = np.random.uniform(0, width, 5)
        y_generated = np.random.uniform(0, height, 5)
        
        for x, y in zip(x_generated, y_generated):
            base_height = 70
            base_width = 70
    
            # generate the corners
            x0 = x - base_width/2
            x1 = x + base_width/2
            y0 = y - base_height/2
            y1 = y + base_height/2
    
            # create rectangle
            poly = np.array((
                (x0, y0),
                (x1, y0),
                (x1, y1),
                (x0, y1),
            ))
    
            rr, cc = polygon(poly[:, 0], poly[:, 1], img.shape)
            img[rr, cc, :] = 0.5
    
            # # canvas method. I don't want to use this!
            # canvas.create_rectangle(x0, y0, x1, y1, fill="red", outline="")
        
        # display generated image in tkinter canvas
        scaled_to_8bit = img * 255
        newarr = scaled_to_8bit.astype(np.uint8)
        imgarray = ImageTk.PhotoImage(image=Image.fromarray(newarr, 'RGB'))
    
        # create the canvas image object from the numpy array
        canvas.create_image(20, 20, anchor="nw", image=imgarray)
        
        # display pixel data for debugging
        plt.imshow(img)
        plt.show()
    
    
    
    if __name__ == "__main__":
        width = 1000
        height = 1000
    
        # Create a root window
        root = tk.Tk()
        root.configure(background="green")
    
        # Create a canvas widget
        canvas = tk.Canvas(root, width=width, height=height)
        canvas.pack()
    
        # Create a button widget
        button = tk.Button(root, text="Generate", command=generate)
        button.pack()
    
        # start main tk loop
        root.mainloop()