PySimpleGUI Graph 直接显示图像

PySimpleGUI Graph Displaying an image directly

我正在尝试使用 Pysimplegui 及其“图形”组件制作一个应用程序,以便用户可以使用该应用程序在图像上绘制多边形。这是我的代码的一部分:

layout = [[sg.Graph(
    canvas_size=(length, width),
    graph_bottom_left=(0, 0),
    graph_top_right=(length, width),
    key="-GRAPH-",
    change_submits=True,  # mouse click events
    background_color='lightblue',
    drag_submits=True), ],]
window = sg.Window("draw rect on image", layout, finalize=True)
graph = window["-GRAPH-"]

这里的长宽指的是我的图片的大小。我知道如何显示图像的唯一方法是通过 graph.draw_image(path, location=(0,width)),其中路径是 png 文件的位置。

我的问题是:有没有一种方法可以直接使用图像而不是路径在图形中显示图像。 (即,如果我有一个表示图像的 nd numpy 数组,我是否可以直接让它显示在 canvas 中,而不是先另存为 png 然后加载位置?)。是否有可能完全避免任何形式的储蓄?

直观上,方法graph.draw_image读取路径打开图片然后显示。应该有一种方法可以避免任何保存,让图表直接显示图像。

你可以在这里使用选项data,但是你需要先将图像从数组转换为数据。

def draw_image(self, filename=None, data=None, location=(None, None)):

Places an image onto your canvas.  It's a really important method for this element as it enables so much

:param filename: if image is in a file, path and filename for the image. (GIF and PNG only!)
:type filename:  (str)
:param data:     if image is in Base64 format or raw? format then use instead of filename
:type data:      str | bytes
:param location: the (x,y) location to place image's top left corner
:type location:  (int, int) | Tuple[float, float]
:return:         id returned from tkinter that you'll need if you want to manipulate the image
:rtype:          int | None

数组中的数据可能只是 RGBA 的值,没有图像格式,如 PNG。 所以我将它从数组转换为 PIL.Image,然后将其保存到数据使用 io.BytesIO

示例代码

from io import BytesIO
from PIL import Image
import numpy as np
import PySimpleGUI as sg

def array_to_data(array):
    im = Image.fromarray(array)
    with BytesIO() as output:
        im.save(output, format="PNG")
        data = output.getvalue()
    return data

font = ("Courier New", 11)
sg.theme("DarkBlue3")
sg.set_options(font=font)

im = Image.open("D:/Fandom.png")
array = np.array(im, dtype=np.uint8)
data = array_to_data(array)

width, height = 640, 480

layout = [[sg.Graph(
    canvas_size=(width, height),
    graph_bottom_left=(0, 0),
    graph_top_right=(width, height),
    key="-GRAPH-",
    change_submits=True,  # mouse click events
    background_color='lightblue',
    drag_submits=True), ],]
window = sg.Window("draw rect on image", layout, finalize=True)
graph = window["-GRAPH-"]
graph.draw_image(data=data, location=(0, height))

while True:

    event, values = window.read()
    if event in (sg.WINDOW_CLOSED, 'Exit'):
        break
    print(event, values)

window.close()