在ipython笔记本中嵌入图像以便分发

时间:2014-09-26 21:06:06

标签: ipython ipython-notebook

我有一个ipython笔记本,带有我本地驱动器的嵌入式图像。我期待它与代码单元的输出一起嵌入JSON中,但是当我分发笔记本时,图像并没有出现在用户身上。在Notebook中嵌入图像的推荐方法是什么,如果用户重新运行代码单元,清除单元格输出等,它不会消失?

笔记本系统缓存![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>

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

PS 现有的(旧的)答案提供了一些非常有用的指针,但不是解决方案。

5 个答案:

答案 0 :(得分:9)

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

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

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

请注意,Image类还有一个url关键字,但除非您同时指定embed=True,否则只会将链接添加到图像中(请参阅{ {3}}了解详情)。因此,除非您在远程服务器上引用图像,否则使用filename关键字会更安全。

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

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

答案 1 :(得分:3)

之所以

<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAnAAAAFgCAYAAAA...
当你把它放在降价单元格中时,

标签没有做任何事情是因为IPython使用HTML清理程序(称为Google Caja)来筛选出这种类型的标记(以及许多其他标记)被渲染。

通过将以下行添加到custom.js文件(通常位于~/.ipython/profile_default/static/custom/custom.js),可以完全禁用IPython中的HTML清理程序:

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

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

后记
将base64编码的字符串渲染为图像的能力!=显而易见的安全问题,因此Caja人应该有办法最终允许这种事情通过(尽管the related feature request ticket在2012年首次开放,所以不要&# 39;屏住呼吸)。

答案 2 :(得分:1)

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

降价示例:

![smile](data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAABHNCSVQICAgIfAhkiAAAAD9JREFUGJW1jzEOADAIAqHx/1+mE4ltNXEpI3eJQknCIGsiHSLJB+aO/06PxOo/x2wBgKR2jCeEy0rOO6MDdzYQJRcVkl1NggAAAABJRU5ErkJggg==)

答案 3 :(得分: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指出的那样,这实际上并不能正确回答问题,这将不允许用户重新运行单元格并保留图像(此解决方案仅允许将图像嵌入到导出文件中。

答案 4 :(得分:0)

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

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

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