python - 带有本地 PIL 图像的 Altair 工具提示

标签 python jupyter-notebook python-imaging-library altair

按照 docs 的官方示例我可以成功创建一个 Altair 散点图,每个点都有一个工具提示:

import altair as alt
import pandas as pd

source = pd.DataFrame.from_records(
    [{'a': 1, 'b': 1, 'image': 'https://altair-viz.github.io/_static/altair-logo-light.png'},
     {'a': 2, 'b': 2, 'image': 'https://avatars.githubusercontent.com/u/11796929?s=200&v=4'}]
)
alt.Chart(source).mark_circle(size=200).encode(
    x='a',
    y='b',
    tooltip=['image']  # Must be a list for the image to render
)

结果如下所示

before code change

但是我想使用通过 PIL 加载的本地镜像。如果我只是将工具提示中的 URL 字符串替换为 PIL 对象,则会收到错误:TypeError:“Image”类型的对象不可序列化

然后我尝试按照此 SO answer 将图像转换为 JSON

我的代码现在如下所示:

from io import BytesIO
import base64
def image_formatter2(im):
    with BytesIO() as buffer:
        im.save(buffer, 'png')
        data = base64.encodebytes(buffer.getvalue()).decode('utf-8')
    
    return json.dumps(data)
    


temp = some_local_PIL_image.thumbnail((90,90))

source = pd.DataFrame.from_records(
    [{'a': 1, 'b': 1, 'image': image_formatter2(temp)},
     {'a': 2, 'b': 2, 'image': 'https://avatars.githubusercontent.com/u/11796929?s=200&v=4'}]
)
alt.Chart(source).mark_circle(size=200).encode(
    x='a',
    y='b',
    tooltip=['image']  # Must be a list for the image to render
)

我的工具提示现在是空的!如何在工具提示中显示本地镜像?

after code change


版本信息

IPython          : 7.16.1
jupyter_client   : 7.0.6
jupyter_core     : 4.8.1
altair           : 4.1.0

最佳答案

好吧,我大概明白了。必须向数据添加前缀 data:image/png;base64,。现在代码如下:

import PIL.Image
from io import BytesIO
import base64

def image_formatter2(im):
    with BytesIO() as buffer:
        im.save(buffer, 'png')
        data = base64.encodebytes(buffer.getvalue()).decode('utf-8')
    
    return f"data:image/png;base64,{data}" # <--------- this prefix is crucial
    


temp = some_local_PIL_image.thumbnail((90,90))

source = pd.DataFrame.from_records(
    [{'a': 1, 'b': 1, 'image': image_formatter2(temp)},
     {'a': 2, 'b': 2, 'image': 'https://avatars.githubusercontent.com/u/11796929?s=200&v=4'}]
)
alt.Chart(source).mark_circle(size=200).encode(
    x='a',
    y='b',
    tooltip=['image']  # Must be a list for the image to render
)

结果

final result


因为我不知道术语/语法,这也可能对其他人有帮助: 必须寻找的术语是数据 URL。这是一个很好的介绍:https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URIs

关于python - 带有本地 PIL 图像的 Altair 工具提示,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70751037/

相关文章:

python - 如何在 Jupyter notebook 中找到缩进级别?

Python:创建带有可移动图钉的 map

python - 有没有办法用 PIL 来回退丢失的字形?

python - 如何使用 scipy leastsq 设置最小化

python - 基于正则表达式拆分字符串而不消耗字符

python - 如何清除这两个小部件以及它们被其他小部件清除

amazon-web-services - 如何将 boto3 安装到 EMR 集群上以与 Jupyter Notebook 一起使用

python - 如何根据 python 中的 rgb 值合并图像中的像素?

python - 自定义 Django 表单未显示 - 使用 Wagtail

python - 在 OR 工具中使用 IntVar