Я возвращаюсь к разработке после многих лет бездействия, поэтому мои навыки довольно заржавели, и я заранее прошу прощения за любые неправильные проблемы с синтаксисом и форматированием.
В настоящее время я работаю над небольшим проектом веб-приложения, которое принимает текстовую подсказку и генерирует изображение с помощью Googles aivertex и Gemini.
Вот несколько фрагментов кода для ознакомления.
HTML-шаблон
<body>
<h1>Turn your words into art!</h1>
<p>Enter a description of the image you want to generate.</p>
<form target = "_blank" id = "text-form" action = "/my_prompt" onsubmit = "dontredict('myindex.html')" method = "post">
<label for = "text-input">Text Prompt:</label>
<textarea id = "text-input" name = "text" rows = "5" placeholder = "e.g. A cat riding a bicycle on Mars"></textarea>
<button type = "submit">Generate Image</button>
</form>
<div id = "image-container">
{% if img_data %}
<h1>Your generated image will appear here.</h1>
<img id = "picture" style = "height: 300px;" src = "{{url_for('static',filename='my-output.png')}}">
{% else %}
<h1>Image will be render here...</h1>
{% endif %}
</div>
<!--Jquery Cdn -->
<script src = "https://code.jquery.com/jquery-3.5.1.js" integrity = "sha256-QWo7LDvxbWT2tbbQ97B53yJnYU3WhH/C8ycbRAkjPDc = "
crossorigin = "anonymous"></script>
<script type = "text/javascript">
function dontredict(dynamicUrl){
$(document).on('submit', '#text-form', function (e) {
e.preventDefault();
console.info('button smashed');
$.ajax({
type: 'POST',
url: '/my_prompt',
data: {
text: $("#text-input").val()
},
success: function () {
alert('saved');
}
})
});
}
</script>
</body>
Преобразование текста в изображение Python.py
def disp_image():
if os.path.exists(output_file):
im = Image.open("static/my-output.png")
data = io.BytesIO()
im.save(data, "PNG")
encoded_img_data = base64.b64encode(data.getvalue())
img_data=encoded_img_data.decode('utf-8')
return render_template("myindex.html", img_data=img_data)
#if os.path.exists(output_file):
#return redirect(url_for('static/my-output.png'))
@app.route('/my_prompt', methods = ['POST'])
@cross_origin()
def imggen():
print("inside gen")
if request.method == 'POST':
prompt = request.form.get("text")
logger.info('%s This is the prompt: ', prompt)
print(prompt);
print("after prompt")
model = ImageGenerationModel.from_pretrained("imagegeneration@006")
images = model.generate_images(
prompt=prompt,
# Optional parameters
number_of_images=1,
language = "en",
# You can't use a seed value and watermark at the same time.
# add_watermark=False,
# seed=100,
aspect_ratio = "1:1",
safety_filter_level = "block_some",
person_generation = "allow_adult",
)
images[0].save(location=output_file, include_generation_parameters=False)
print(f"Created output image using {len(images[0]._image_bytes)} bytes")
print(disp_image())
return disp_image()
else:
print("error")
Проблемы, с которыми я сталкиваюсь, заключаются в том, что когда текст публикуется и возвращается со сгенерированным изображением, он правильно сохраняется в папке статического изображения (с использованием flask и python), но он не отображается и не отображается на html-странице. Я также осознаю, что часть кода может быть избыточной. Дайте мне знать, что я делаю неправильно с точки зрения отображения изображения на реальной html-странице. Спасибо.
🤔 А знаете ли вы, что...
Python поддерживает динамическую типизацию, что облегчает разработку.
Когда вы используете $.ajax
(или встроенный современный fetch()
или более старый XMLHttpRequest()
)
тогда браузер не обновляет HTML. Это твоя работа.
Таким образом, вы можете решить, что и когда обновлять на странице.
В success()
вам нужно получить ответ от flask
и добавить/заменить HTML
.
Но сначала: вам не обязательно отправлять всю страницу, а только часть - например <h1>
и <img>
.
И для этого вы можете использовать render_template_string()
.
def disp_image():
# ... code ...
return render_template_string('''
<h1>Your generated image will appear here.</h1>
<img id = "picture" style = "height: 300px;"
src = "{{url_for('static',filename='my-output.png')}}">
''')
А позже можно будет заменить только контент внутри <div id = "image-container">
$.ajax(
// ... code ...
success: function(response_data) {
$('#image-container').html(response_data);
alert('saved');
}
)
Поскольку браузер может не перезагрузить изображение, если оно всегда будет иметь одно и то же имя, поскольку он не будет знать, что вы сохранили новое изображение с тем же именем, поэтому вы можете отправить изображение как base64
в src = "..."
.
def disp_image():
# ... code ...
img_data = encoded_img_data.decode('utf-8')
return render_template_string('''
<h1>Your generated image will appear here.</h1>
<img id = "picture" style = "height: 300px;"
src = "data:image/png;base64, {{base64_image}}">
''', base64_image=img_data)
Кстати: после data:image/png;base64,
есть один пробел.
Конечно можно отправлять только base64_image
- т.е. как JSON
— и JavaScript может получить его и заменить только src = "..."
(если он уже существует на странице)
from flask import jsonify
def disp_image():
# ... code ...
img_data = encoded_img_data.decode('utf-8')
return jsonify({'base64_image': img_data})
success: function(response_data) {
var json = $.parseJSON(response_data);
var image = json.base64_image;
$('#picture').attr('src', 'data:image/png;base64, ' + image);
alert('saved');
}
Полный рабочий код — с двумя версиями:
h1
и img
img
в JavaScriptОба используют PIL.Image
для создания изображения с текстом.
import os
from flask import Flask, request, render_template_string
from PIL import Image, ImageDraw, ImageFont
import io
import base64
os.makedirs('static', exist_ok=True)
app = Flask(__name__)
@app.route('/')
def index():
return render_template_string('''<!DOCTYPE html>
<html>
<head>
<meta charset = "utf-8">
<script src = "https://code.jquery.com/jquery-3.5.1.js" integrity = "sha256-QWo7LDvxbWT2tbbQ97B53yJnYU3WhH/C8ycbRAkjPDc = "
crossorigin = "anonymous"></script>
</head>
<body>
<form target = "_blank" id = "text-form" action = "/my_prompt" method = "POST">
<textarea id = "text-input" name = "text" rows = "5" placeholder = "e.g. A cat riding a bicycle on Mars"></textarea></br>
<button type = "submit">Generate Image</button>
</form>
<form target = "_blank" id = "text-form-json" action = "/my_prompt_json" method = "POST">
<textarea id = "text-input-json" name = "text" rows = "5" placeholder = "e.g. A cat riding a bicycle on Mars"></textarea></br>
<button type = "submit">Generate Image</button>
</form>
<div id = "image-container">
<h1>No Image</h1>
</div>
<script type = "text/javascript">
$(document).on('submit', '#text-form', function (e) {
e.preventDefault();
console.info('button smashed');
$.ajax({
type: 'POST',
url: '/my_prompt',
data: {
text: $("#text-input").val()
},
success: function(response_data) {
$('#image-container').html(response_data);
}
})
});
$(document).on('submit', '#text-form-json', function (e) {
e.preventDefault();
console.info('button smashed JSON');
$.ajax({
type: 'POST',
url: '/my_prompt_json',
data: {
text: $("#text-input-json").val()
},
success: function(response_data) {
picture = $('#picture');
if (picture.length === 0) {
picture = $('<img id = "picture" style = "height: 300px;">');
}
picture.attr('src', 'data:image/png;base64, ' + response_data.base64_image);
$('#image-container').html(picture);
}
})
});
</script>
</body>
</html>''')
def disp_image():
img = Image.open("static/my-output.png")
data = io.BytesIO()
img.save(data, 'PNG')
encoded_img_data = base64.b64encode(data.getvalue())
img_data=encoded_img_data.decode('utf-8')
return render_template_string('''
<h1>Your generated image will appear here.</h1>
<img id = "picture" style = "height: 300px;"
src = "data:image/png;base64, {{base64_image}}">
''', base64_image=img_data)
from flask import jsonify
def disp_image_json():
img = Image.open("static/my-output.png")
data = io.BytesIO()
img.save(data, 'PNG')
encoded_img_data = base64.b64encode(data.getvalue())
img_data=encoded_img_data.decode('utf-8')
return jsonify({'base64_image': img_data})
@app.route('/my_prompt', methods=['POST'])
def image():
if request.method == "POST":
text = request.form.get('text', '???')
print('text:', text)
img = Image.new('RGB', (600, 300))
draw = ImageDraw.Draw(img)
font = ImageFont.truetype("arial.ttf", size=40)
draw.text((10, 10), text, font=font, fill=(255, 255, 255))
img.save('static/my-output.png')
return disp_image()
@app.route('/my_prompt_json', methods=['POST'])
def image_json():
if request.method == "POST":
text = request.form.get('text', '???')
print('text:', text)
img = Image.new('RGB', (600, 300))
draw = ImageDraw.Draw(img)
font = ImageFont.truetype("arial.ttf", size=40)
draw.text((10, 10), text, font=font, fill=(255, 255, 255))
img.save('static/my-output.png')
return disp_image_json()
if __name__ == '__main__':
app.debug = True
app.run()