19

我有一个 ipython 笔记本,其中包含来自本地驱动器的嵌入式图像。我期待它与代码单元的输出一起嵌入到 JSON 中,但是当我分发笔记本时,用户看不到图像。将图像嵌入笔记本中的推荐方法是什么,以便在用户重新运行代码单元、清除单元输出等时它不会消失?

笔记本系统缓存包含在 中的图像![label](image.png),但它们仅持续到为笔记本提供服务的 python“内核”重新启动。如果我重命名磁盘上的图像文件,我可以关闭并重新打开笔记本,它仍然显示图像;但是当我重新启动内核时它消失了。

编辑:如果我生成一个图像作为代码单元输出,然后将笔记本导出为 html,则该图像作为编码数据嵌入到 html 中。当然必须有一种方法可以连接到此功能并将输出加载到降价(或更好的“原始 nbconvert”)单元中?

from IPython.display import Image 
Image(filename='imagename.png')

将被导出(使用ipython nbconvert)到包含以下内容的 html:

<div class="output_png output_subarea output_execute_result">
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAnAAAAFgCAYAAAA...
</div>

但是,即使我手动将此代码段嵌入到降价单元格中,我也无法显示图像。我究竟做错了什么?

更新 (2020)

显然,这个问题(终于!)在较新的笔记本/Jupyter 版本中得到了解决:截至2018 年(感谢@Wayne 的链接),html sanitizer 将接受嵌入的 html 图像,如<img src="data:image/png;base64,iV...>. Markdown 图像语法也接受图像作为嵌入数据,因此有两种方法可以做到这一点。这些有用的答案中的详细信息:

4

5 回答 5

11

您愿意使用额外的代码单元来显示图像吗?如果是这样,请使用:

from IPython.display import Image
Image(filename="example.png")

输出单元格将在.ipynb文件中嵌入原始图像数据,因此您可以共享它并且图像将被保留。

请注意,Image该类也有一个url关键字,但这只会链接到图像,除非您还指定embed=True(有关详细信息,请参阅文档)。因此,filename除非您指的是远程服务器上的图像,否则使用关键字更安全。

如果您需要将图像包含在 Markdown 单元格中,即没有单独的代码单元格来生成嵌入的图像数据,我不确定是否有简单的解决方案。您可以使用python markdown 扩展,它允许在 markdown 单元格中动态显示 Python 变量的内容。但是,扩展会动态生成降价单元格,因此为了在共享笔记本时保留输出,您需要使用“安装”部分中提到ipython nbconvert --to notebook original_notebook.ipynb --output preprocessed_notebook的预处理器运行。pymdpreprocessor.py生成的笔记本然后将数据作为表单的 HTML 标记嵌入到 markdown 单元中,<img src="data:image/png;base64,...">因此您可以从preprocessed_notebook.ipynb. 不幸的是,当我尝试这个时<img>标签实际上并未显示在浏览器中,因此不确定这是否是可行的解决方案。:-/

另一种选择是使用Image代码单元中的类来生成上述图像,然后使用nbconvert自定义模板从笔记本中删除代码输入单元。有关详细信息,请参阅此线程。但是,这将从转换后的笔记本中删除所有代码单元,因此它可能不是您想要的。

于 2015-05-04T17:02:00.673 回答
3

的原因

<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAnAAAAFgCAYAAAA...

当您将标签放入降价单元格时,标签不会做任何事情,因为 IPython 使用 HTML sanitizer(称为Google Caja的东西)在呈现之前屏蔽掉这种类型的标签(以及许多其他标签)。

custom.jsIPython 中的 HTML sanitizer 可以通过在您的文件(通常位于)中添加以下行来完全禁用~/.ipython/profile_default/static/custom/custom.js

iPython.security.sanitize_html = function (html) { return html; };  

虽然这不是一个很好的解决方案,因为它确实会产生安全风险,而且它对分发没有太大帮助。

后记
将base64编码的字符串呈现为图像的能力!=明显的安全问题,所以应该有一种方法让Caja人最终允许这种事情通过(尽管相关的功能请求票是在2012年首次打开的,所以不要屏住呼吸)。

于 2015-10-01T18:25:49.080 回答
1

我发现用![name](image)base64 URL 替换中的图像 URL,类似于上面找到的那些,可以将图像嵌入到 markdown 容器中。

降价示例:

![smile](data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAABHNCSVQICAgIfAhkiAAAAD9JREFUGJW1jzEOADAIAqHx/1+mE4ltNXEpI3eJQknCIGsiHSLJB+aO/06PxOo/x2wBgKR2jCeEy0rOO6MDdzYQJRcVkl1NggAAAABJRU5ErkJggg==)
于 2020-12-09T23:48:50.363 回答
0

如果使用 IPython函数输出原始 HTML,您可以使用以下方法在标签内HTML()嵌入链接图像:base64<img>

import base64
import requests
from IPython.core.display import HTML

def embedded_image(url):
    response = requests.get(url)
    uri = ("data:" + 
       response.headers['Content-Type'] + ";" +
       "base64," + str(base64.b64encode(response.content).decode('utf-8')))
    return uri

# Here is a small example. When you export the notebook as HTML,
# the image will be embedded in the HTML file 
html = f'<img src="{embedded_image("https://upload.wikimedia.org/wikipedia/commons/5/56/Kosaciec_szczecinkowaty_Iris_setosa.jpg")}" />'
HTML(html)

更新:正如@a​​lexis 所指出的,这实际上并没有正确回答问题,这将不允许用户重新运行单元格并使图像保持不变(此解决方案只允许将图像嵌入到导出中)。

于 2019-10-28T19:52:23.673 回答
0

从 Jupyter Notebook 5 开始,您可以将图像数据附加到单元格,并通过attachment:<image-file-name>. 查看菜单Edit > Insert Image,或使用拖放操作。

不幸的是,将带有附加(嵌入)图像的笔记本转换为 HTML 时,这些图像不会显示。

要将它们放入 HTML 代码中,您可以使用 (例如) nbtoolbelt. 它将用嵌入标签中的图像数据替换这些attachment:引用。data:img

于 2020-02-07T10:13:56.357 回答