LambdaとBedrockでAI描き初めコンテスト開催してみた【Amazon Nova Canvas】

Nova

はじめに

2025年の新春を迎えるにあたり、書き初めならぬAI描き初めとして社内でAmazon Nova Canvasを使った画像作成コンテストを実施しました。

Amazon Nova Canvas

Amazon Nova Canvasは、Amazonが提供する最先端の画像生成AIモデルです。従来のTitan画像生成モデルの機能を大きく拡張し、写真のような写実的な表現から芸術的な表現まで、幅広い画像生成能力を実現しています。最大1024トークンまでの入力に対応し、多様なユースケースに活用できます。

Amazon Nova Canvas 機能紹介

  • テキストからの画像生成:自然言語のプロンプトを入力するだけで、高品質な画像を生成できます。直感的な操作で、イメージ通りの画像を作成することが可能です。
  • 高度な画像編集:マスク指定なしでテキスト指示のみによる画像編集が可能です。これにより、編集作業の効率が大幅に向上します。
  • 部分編集と拡張機能:オブジェクトの削除や置換、画像境界の拡張など、細かな編集作業にも対応しています。
  • バリエーション生成:最大5枚の入力画像をベースに、多様なバリエーションを生成できます。クリエイティブな展開を支援します。
  • 画像制御システム:ControlNetを活用した輪郭線検出やセグメンテーション、ブランドカラーのカラーパレット適用など、細かな制御が可能です。

ほかにも、生成された画像への自動透かし機能や、デフォルトでのコンテンツ認証用メタデータ追加など、様々な機能があります。 現時点では英語のみの対応となっていますが、他言語を英語に翻訳することで、間接的に他言語からの利用が可能です。

実際に開発をしてみた

アーキテクチャは以下の通りです。

サーバーはAWS App Runnerで構築し、認証はAuth0、データベースはTiDB Cloud Serverlessを使用しました。これらの技術的な部分については、このブログでは割愛します。
Amazon Bedrock、AWS Lambda、Amazon S3、Amazon API Gatewayを使用した実装については、以下のサイトを参考にしました。
Amazon Bedrock を利用して、画像生成アプリケーションを開発してみた!

基本的には参考サイトの手順に従えばよいのですが、今回はStable DiffusionではなくAmazon Nova Canvasを使用するため、Lambdaのコードを以下のように変更しています。
(API Gatewayとの受け渡し部分も一部変更しています)


# 必要なライブラリを読み込み
import json
import boto3
import base64
from botocore.config import Config

bedrock_runtime = boto3.client('bedrock-runtime')
# 署名プロセスには、署名バージョン4(SigV4)を指定
my_config = Config(region_name="us-east-1", signature_version="s3v4")
s3 = boto3.client("s3", config=my_config)
bucket_name = 'image-generator-demo'

def lambda_handler(event, context):    
    # イベントデータのbodyからJSONを取得
    body = json.loads(event['body'])
    
    # JSONから入力を受け取る
    input_text = body['input_text']
    image_uuid = body['image_uuid']
    input_seed = int(body['input_seed'])

    # Bedrock APIリクエストの設定
    request_body = {
        "taskType": "TEXT_IMAGE",
        "textToImageParams": {
            "text": input_text
        },
        "imageGenerationConfig": {
            "numberOfImages": 1,
            "width": 1024,
            "height": 1024,
            "cfgScale": 6.5,
            "seed": input_seed,
            "quality": "standard"
        }
    }

    # Amazon Bedrockで用意した基盤モデルへAPIリクエストし、画像を生成する
    response = bedrock_runtime.invoke_model(
        body=json.dumps(request_body),
        contentType='application/json',
        accept='application/json',
        modelId='amazon.nova-canvas-v1:0'
    )

    response_body = json.loads(response['body'].read())
    image_data = base64.b64decode(response_body['images'][0])

    # 生成された画像をS3にアップロード    
    s3_key = f"{image_uuid}.png"
    s3.put_object(
                Bucket=bucket_name, 
                Key=s3_key, 
                Body=image_data,
                ContentType='image/png'
            )

    # 署名付きURLを取得
    presigned_url = s3.generate_presigned_url('get_object',Params={'Bucket': bucket_name,'Key': s3_key},ExpiresIn=3600) 
    
    # 署名付きURLを返す
    return {
        'statusCode': 200,
        'body': json.dumps({'presigned_url': presigned_url,})
    }

これにより、API Gatewayにファイル名となるUUIDとプロンプト、生成AIのランダム性をコントロールするためのSeed値の3つをJSONで渡すことで画像が生成され、それをS3に格納して署名付きURLを返すというシステムを構築することができました。

実際のWebアプリがこちら

まず、Auth0を使用して社内メンバーのみがログインできる認証を実装しました。(左)
ログイン後は、登録済みの画像一覧を閲覧できます。新規の画像作成は、画面上部の「画像作成はこちら」ボタンから行えます。(中)
画像作成画面では、プロンプトとSeed値を入力することができます。

このアプリを使って画像を作ってみようと思います。
年始といえば、毎日放送が中継している東大阪市花園ラグビー場で行われる全国高校ラグビー大会も風物詩の一つです。これにちなんで、以下の要素を画像に取り入れることにしました。

  • 初夢に見ると縁起のよいものとされる一富士二鷹三茄子
  • ラグビーをしている選手たちとそれを撮影するスタッフたち

背景には、朝もやがかかった空に雄大な富士山がそびえ立ち、夜明けの優しいピンク色が、真っ白な雪をいただく山頂をそっと染めていきます。
手前では、10人の選手たちが、みずみずしい緑の葉をつけた3つの大きな紫色の茄子のある野原でラグビーをしています。2羽の鋭い目をした鷹が上空を飛んでいます。
4人のカメラマンたちが、2025年の到来とともにその瞬間を撮影しています。

In the background, majestic Mount Fuji rises against a misty dawn sky, its snow-capped peak bathed in the soft pink hues of sunrise.
In the foreground, ten players are playing rugby among three large, deep purple eggplants with lush green leaves in a field. Two sharp-eyed hawks fly overhead.
Four videographers are filming the action, capturing the moment as 2025 arrives.

するとこちらのような画像が出力されました。

一富士二鷹三茄子ならぬ一富士二鷹"大量"茄子になってしまいました。そしてビデオカメラマンたちがラグビーのユニフォームを着て撮影をしているという、少し意図と異なる結果となりました。
しかし、全体的には想像していた雰囲気の画像が生成され、個人的には満足のいく結果となりました。この画像は登録後、他のユーザーも閲覧できるようになっています。

さらに、画像一覧では各画像に使用されたプロンプトとSeed値も表示されるように実装しました。これにより、私のようにまだプロンプトの作成に慣れていないユーザーも、他の方のプロンプトを参考にしながら学ぶことができます。

さいごに

英語でのプロンプト入力が必要とはなりますが、プロンプトを入力するだけで画像生成ができるWebアプリを作成することができました。

季節のイベントということもあり、多くのメンバーに参加していただきました。参加者の中には、実際にプロンプトを作成してみて「少しの入力で反応があることに感心する一方で、AIの判断プロセスが不透明なことへの戸惑いがあった」であったり「プロンプトを試行錯誤して理想の出力に近づけていく作業は初めての経験で、思い描いた画像と実際の生成結果に違いがあることを実感した」など、プロンプト作成の難しさを改めて実感された方も多かったようです。この取り組みを通じて、生成AIをより身近に感じてもらえる機会を提供できたことを、作った身として嬉しく思いました。

Previous Post