在本系列的上篇中,我们介绍了如何利用Amazon Nova Canvas进行创意图片内容生成,并使用Amazon Bedrock的InvokeModel API进行文本到图像(文生图)的生成。并且介绍了Nova Canvas提供的广泛的功能,包括图像修复、画布扩展、颜色引导等,使其成为强大的AI创意工具。接下来下篇中我们将继续介绍我们上篇中的方案,利用Nova生成一个完整的故事书插画。
调整Nova Canvas的生成结果
编辑提示词(Edit Prompt)
如果生成的图像没有达到预期,或者缺少某些特征,可以通过修改提示词(prompt)来调整结果。例如:
prompt = """
A rundown house with a light, the front door of the house is swung wide open
and a warm fire in a chimney can be seen.
"""
重新运行代码后,会生成符合新描述的图像。
修改随机种子(Change Seed)
如果当前提示词生成的图像不错,但想要探索一些变化,可以更改种子值(seed),以生成不同版本的图像:
seed: 23423423
这将创建一个具有相似风格但不同细节的新图像。
调整cfgScale参数
如果模型生成的图像未能严格按照提示词执行,大家可以调整 cfgScale
参数:
cfgScale: 8.5
- 值越高(最大10.0):模型会更加严格遵循提示词的描述。
- 值越低(最小1.1):生成的图像会带有更多随机性,可能出现创造性的变化。
负面提示词(Negative Text )
如果想要去除特定元素,可以使用 negativeText
属性。例如,要生成一张没有窗户的房屋:
negative_prompt = "window, window with light"
# ...
"textToImageParams": {
"text": prompt,
"negativeText": negative_prompt
},
这将告诉模型不要生成包含这些元素的图片,再次运行将生成以下图片。
大家现在已经掌握了调整Nova Canvas输出的各种方法,包括修改提示词、调整随机种子、配置cfgScale参数,以及使用负面提示词去除特定元素。
如需了解更多关于提示词优化(Prompt Optimization)和输出调整(Output Tweaking)的详细信息,请参考Nova官方文档。
生成最终输出 - 故事板(Storyboard)
现在,大家已经掌握了Nova Canvas的调整技巧,接下来可以继续生成多个图像,并把他们组合生成PDF故事图画集。
大家可以选择一个故事情节,设计图片分镜布局,然后使用Python代码自动生成一个故事图画集,并导出为单页PDF。
更新 requirements.txt
请确保 requirements.txt 文件包含以下依赖项:
boto3
fpdf2
在本地 IDE 或 SageMaker Jupyter Notebook 安装依赖
如果大家使用的是SageMaker Jupyter Notebook,可以在Notebook的第一个代码单元格中运行:
!pip install boto3
!pip install fpdf2
代码示例
该代码将会生成一个完整的故事图画集PDF,包含三幅由Nova Canvas生成的插图。
# Required imports
import base64
import io
import json
import boto3
from PIL import Image
from botocore.config import Config
import time
from fpdf import FPDF
# Create the client instance (5 minute timeout)
bedrock = boto3.client(
service_name='bedrock-runtime',
region_name="us-east-1",
config=Config(read_timeout=300)
)
# Define the default generated image width and height
DEFAULT_IMG_WIDTH = 480
DEFAULT_IMG_HEIGHT = 480
# Cells are used for page layout, this is the size of one cell
CELL_WIDTH = DEFAULT_IMG_WIDTH / 6
# Define a page layout of cells, 1 or 2 cell spans per row, 3 rows per page
page_layout = [[7,5], [12], [8,4]]
# Define the story for each cell
story = [
"""Two bears entering a dark, ominous wood, walking along a grassy path. Seen from behind.""",
"""Two bears in a dark, ominous wood, a small, rundown house with a light on is in front of them. Seen from behind.""",
"""A rundown house with a light, the door of the house is open and a warm fire and pot can be seen through the door.""",
"""A rundown house with a light, the door of the house is open and a warm fire and pot can be seen through the door. A shadowy figure is standing at the door""",
"""A rundown house with a light, the door of the house is open and a warm fire and pot can be seen through the door. A man is standing at the door with an axe. Two bears are running from the house towards the viewer."""
]
def image_from_text(text, width, height, file):
body = json.dumps({
"taskType": "TEXT_IMAGE",
"textToImageParams": {
"text": text
},
"imageGenerationConfig": {
"numberOfImages": 1,
"width": width,
"height": height,
"cfgScale": 8.0,
"seed": 0
}
})
response = bedrock.invoke_model(
body=body,
modelId="amazon.nova-canvas-v1:0",
accept="application/json",
contentType="application/json"
)
response_body = json.loads(response.get("body").read())
base64_image = response_body.get("images")[0]
base64_bytes = base64_image.encode('ascii')
image_bytes = base64.b64decode(base64_bytes)
image = Image.open(io.BytesIO(image_bytes))
image.save(file)
return file
def generate_story(story, page_layout):
outputs = []
cells = [cell for row in page_layout for cell in row]
for idx, text in enumerate(story):
if idx > 0:
time.sleep(20)
file = image_from_text(text, int(CELL_WIDTH * cells[idx]), DEFAULT_IMG_HEIGHT, f"story-{idx}.jpg")
outputs.append(file)
return outputs
def build_pdf(images, page_layout, file):
pdf = FPDF(orientation="portrait")
pdf.set_margin(0)
pdf.add_page()
row_height = pdf.eph / len(page_layout)
cell_width = pdf.epw / 12
print(f"{pdf.epw} {cell_width} {cell_width*7}")
# full page height, half page width pdf.epw/2
img_idx = 0
for r_idx, row in enumerate(page_layout):
cursor_y = r_idx * row_height
for c_idx, cell in enumerate(row):
cursor_x = 0 if c_idx == 0 else cell_width * row[c_idx - 1]
pdf.set_y(cursor_y)
pdf.image(images[img_idx], h=row_height, w=cell_width * cell, x=cursor_x)
img_idx += 1
pdf.output(file)
images = generate_story(story, page_layout)
build_pdf(images, page_layout, "storyboard.pdf")
Nova模型生成的完整故事图片故事集如下:
调整图片生成风格
假如客户对以上的生成结果很满意,但建议将风格修改为卡通风格。我们可以再次利用Nova Canvas,以内可以通过其调整提示词实现不同的图像风格。
我们修改如下代码中的修改提示词部分,再次运行生成图片。
# ...
# existing code from previous example
def generate_story_with_style(style, story, page_layout, prefix):
outputs = []
cells = [cell for row in page_layout for cell in row]
for idx, text in enumerate(story):
if idx > 0:
time.sleep(20)
file = image_from_text(style + text, int(CELL_WIDTH * cells[idx]), DEFAULT_IMG_HEIGHT, f"{prefix}-story-{idx}.jpg")
outputs.append(file)
return outputs
style = "A cartoon style image. "
prefix="cartoon"
styled_images = generate_story_with_style(style, story, page_layout, prefix)
build_pdf(styled_images, page_layout, f"{prefix}-storyboard.pdf")
然后重新运行脚本,便可以生成卡通化的故事图片集。
结论
- Nova Canvas提供了多种方法调整生成的图像,包括修改提示词、调整种子值、配置
cfgScale
以及负面提示词。 - 可以批量生成图像,并将其组合成PDF故事图片集,用于快速展示电影、产品、图像、文本等方面的创意概念。
- 可通过修改提示词风格(如"cartoon style")来快速匹配客户的不同图片生成需求。
通过Nova以上强大的功能,我们就可以仅需几秒就可以生成高质量的图片故事集,极大提高在商品海报、活动营销策划、产品概念展示等方面的工作效率。