将matplotlib图传递给HTML(烧瓶)

时间:2013-11-20 21:28:50

标签: python html image matplotlib flask

我正在使用matplotlib在Web应用程序中呈现一些图形。我之前在运行脚本时使用过fig.savefig()。但是,我需要一个函数来返回一个实际的“.png”图像,以便我可以用我的HTML调用它。

更多(可能不必要的)信息:我正在使用Python Flask。我想我可以使用fig.savefig()并将图形粘贴在我的静态文件夹中,然后从我的HTML中调用它,但我不想每次都这样做。如果我可以创建图形,从中创建图像,返回该图像,并从我的HTML中调用它,然后它就会消失,那将是最佳选择。

创建图形的代码有效。但是,它返回一个数字,我猜不会使用HTML。

这是我在路由中调用draw_polygon的地方,draw_polygon是返回数字的方法:

@app.route('/images/<cropzonekey>')
def images(cropzonekey):
    fig = draw_polygons(cropzonekey)
    return render_template("images.html", title=cropzonekey, figure = fig)

这是我试图生成图像的HTML。

<html>
  <head>
    <title>{{ title }} - image</title>
  </head>
  <body>
    <img src={{ figure }} alt="Image Placeholder" height="100">
  </body>
</html>

而且,正如您可能猜到的,当我加载页面时,我得到的只是Image Placeholder。所以,他们不喜欢我用这个数字输入的格式。

任何人都知道什么matplotlib方法/解决方案将图形变成实际图像?我到处都是这些文档,但我找不到任何东西。谢谢!

BTW:不认为有必要包含构成数字的python代码,但如果你们需要看到它,我可以包括它(只是不想让问题混乱)

5 个答案:

答案 0 :(得分:30)

您必须将HTML和图像分成两个不同的路径。

您的/images/<cropzonekey>路线将仅为该页面提供服务,并且该页面的HTML内容中将引用第二条路线,即提供图像的路线。

图像以您自己的路径从您使用savefig()生成的内存文件中提供。

我显然没有对此进行测试,但我相信以下示例将按原样运行,或者让您非常接近工作解决方案:

@app.route('/images/<cropzonekey>')
def images(cropzonekey):
    return render_template("images.html", title=cropzonekey)

@app.route('/fig/<cropzonekey>')
def fig(cropzonekey):
    fig = draw_polygons(cropzonekey)
    img = StringIO()
    fig.savefig(img)
    img.seek(0)
    return send_file(img, mimetype='image/png')

您的images.html模板变为:

<html>
  <head>
    <title>{{ title }} - image</title>
  </head>
  <body>
    <img src="{{ url_for('fig', cropzonekey = title) }}" alt="Image Placeholder" height="100">
  </body>
</html>

答案 1 :(得分:4)

对于Python3 ....

我有一个DataFrame,我想在Flask中显示此情节...。

因此,创建该图的Base64图像。

    df_week_min_az = pd.DataFrame.from_dict(week_max_az.to_dict(),
                                            orient='index', columns=['min_az'])



    sunalt = df_week_max_angle.plot().get_figure()
    buf = io.BytesIO()
    sunalt.savefig(buf, format='png')
    buf.seek(0)
    buffer = b''.join(buf)
    b2 = base64.b64encode(buffer)
    sunalt2=b2.decode('utf-8')

我现在使用这样的base64编码数据调用模板。...

return render_template('where.html', form=form, sunalt=sunalt2)

模板的相关部分(即图片位)如下所示。...

 {% if sunalt != None %}

      <h2>Sun Altitude during the year</h2>
    <img src="data:image/png;base64,{{ sunalt }}">
{% endif %}

希望可以帮助某人。...

答案 2 :(得分:4)

Python 3

我遇到了很多麻烦,出现了- Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'NSWindow drag regions should only be invalidated on the Main Thread!

对于所有想要在烧瓶中使用matplotlib并在python 3中的html页面上呈现图形的人来说,您可以-

__init__.py

import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
from flask import Flask, render_template
from io import BytesIO
import base64

    @app.route('/plot')
    def plot():
        img = BytesIO()
        y = [1,2,3,4,5]
        x = [0,2,1,3,4]

        plt.plot(x,y)

        plt.savefig(img, format='png')
        plt.close()
        img.seek(0)
        plot_url = base64.b64encode(img.getvalue()).decode('utf8')

        return render_template('plot.html', plot_url=plot_url)

flaskr/templates/plot.html

<!doctype html>
<title>heatmap - </title>
<section>
  <h2>Heatmap</h2>
  <img src="data:image/png;base64, {{ plot_url }}">
</section>

答案 3 :(得分:1)

我正在使用Python 3.x,我已经改变了一些代码行,它对我有用。我有以下错误消息:“.....对象没有属性'savefig'”

@app.route('/fig/<cropzonekey>')

def fig(cropzonekey):
    #fig = draw_polygons(cropzonekey)
    fig = plt.plot([1,2,3,4], [1,2,3,4])
    #img = StringIO()
    img = BytesIO()
    #fig.savefig(img)
    plt.savefig(img)
    img.seek(0)
    return send_file(img, mimetype='image/png')

答案 4 :(得分:1)

from flask import Flask, send_file
from io import StringIO
import matplotlib.pyplot as plt
from StringIO import StringIO
@app.route('/fig/')
def fig():
      plt.plot([1,2,3,4], [1,2,3,4])
      img = StringIO()
      plt.savefig(img)
      img.seek(0)
      return send_file(img, mimetype='image/png')

其他答案都是正确的,我只是想显示必须包含的头文件。 该程序创建一个简单的图形并将其发送到html页面。