Передача фигуры Matplotlib в HTML (фляжка)
Я использую Matplotlib для визуализации фигуры в веб-приложении. Я использовал 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 превращают фигуру в реальное изображение? Я во всех этих документах, но ничего не могу найти. Спасибо!
КСТАТИ: не думаю, что было необходимо включать код Python, который делает рисунок, но я могу включить его, если вам, ребята, нужно его увидеть (просто не хотел загромождать вопрос)
6 ответов
Вы должны разделить HTML и изображение на два разных маршрута.
Ваш /images/<cropzonekey>
route будет обслуживать только страницу, а в 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>
Python 3
У меня было много проблем с такими ошибками, как -
Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'NSWindow drag regions should only be invalidated on the Main Thread!
Для всех, кто хочет использовать matplotlib с колбой и отображать график на html-странице в python 3, вот и все -
в __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>
Для 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 %}
Надеюсь, что это помогает кому-то....
Я работаю с 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')
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-страницу.
У меня это работает очень хорошо, вы также можете проверить этот URLблог среднего
from flask import Flask, render_template
from PIL import Image
import base64
import io
app = Flask(__name__)
@app.route('/')
def show_image():
# Your plt plots instructions here
# plt.save('generated_plot.png')
im = Image.open("generated_plot.png") #Open the generated image
data = io.BytesIO()
im.save(data, "png")
encoded_img_data = base64.b64encode(data.getvalue())
return render_template("show_image.html", img=encoded_img_data.decode('utf-8'))
if __name__ == '__main__':
app.run(debug=True)