0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Gradio ImageEditorチュートリアル

Posted at

このノートブックでは、GradioのパワフルなImageEditorコンポーネントを使用して、画像編集アプリケーションを作成する方法を学びます。

Gradioとは?

Gradioは、機械学習モデルや画像処理アプリケーションなどを簡単にWebインターフェースとして公開できるPythonライブラリです。特に、AIデモの作成やプロトタイピングに最適です。

環境のセットアップ

まずは必要なライブラリをインストールしましょう。

!pip install gradio pillow numpy

基本的なImageEditorアプリケーション

以下では、シンプルな画像編集アプリを構築します。このアプリでは、ユーザーは画像をアップロードして編集し、結果を保存することができます。

import gradio as gr
import time
import numpy as np
from PIL import Image
import os

def save_image(im, filename="saved_image.png"):
    """画像をファイルに保存する関数"""
    if im is not None and "composite" in im:
        # 合成画像(最終結果)を取得
        composite = im["composite"]

        # numpy配列の場合はPIL Imageに変換
        if isinstance(composite, np.ndarray):
            composite = Image.fromarray(composite)

        # 画像を保存
        composite.save(filename)
        return f"画像が正常に {filename} として保存されました"
    else:
        return "保存する画像がないか、無効な画像形式です"

# Gradio Blocksアプリケーションを作成(テーマをOceanに設定)
with gr.Blocks(theme=gr.themes.Ocean()) as demo:
    gr.Markdown("# Image Editor Demo")

    with gr.Row():
        with gr.Column():
            # 1:1の縦横比でImageEditorコンポーネントを作成
            im = gr.ImageEditor(
                type="numpy",  # 画像はnumpy配列として処理される
                crop_size="1:1",  # 正方形のトリミング比率を設定
                label="画像エディタ"
            )

        with gr.Column():
            # プレビュー表示用のImageコンポーネントを作成
            im_preview = gr.Image(label="プレビュー")

    # 各種イベントを追跡するカウンター
    with gr.Row():
        n_upload = gr.Number(0, label="アップロードイベント数", step=1)
        n_change = gr.Number(0, label="変更イベント数", step=1)
        n_input = gr.Number(0, label="入力イベント数", step=1)

    # ファイル名入力と保存ボタンを追加
    with gr.Row():
        filename_input = gr.Textbox(value="my_drawing.png", label="ファイル名")
        save_btn = gr.Button("画像を保存", variant="primary")

    # 保存操作のステータスメッセージ
    save_status = gr.Textbox(label="保存ステータス", interactive=False)

    # イベントハンドラーを定義:
    # 画像がアップロードされたらアップロードカウンターを増加
    im.upload(lambda x: x + 1, outputs=n_upload, inputs=n_upload)

    # 画像が変更されたら変更カウンターを増加(ユーザー入力または関数更新による)
    im.change(lambda x: x + 1, outputs=n_change, inputs=n_change)

    # ユーザーが画像を変更したら入力カウンターを増加
    im.input(lambda x: x + 1, outputs=n_input, inputs=n_input)

    # 画像が変更されたらプレビューエリアに合成画像を表示
    im.change(lambda im: im["composite"] if im and "composite" in im else None,
              outputs=im_preview,
              inputs=im,
              show_progress="hidden")

    # 保存ボタンクリックイベントを設定
    save_btn.click(
        fn=save_image,
        inputs=[im, filename_input],
        outputs=save_status
    )

# このスクリプトが直接実行されたときにデモを起動
if __name__ == "__main__":
    demo.launch()

コードの詳細解説

インポートと設定

import gradio as gr
import time
import numpy as np
from PIL import Image
import os

ここでは、必要なライブラリをインポートしています:

  • gradio: UIコンポーネントの作成に使用
  • time: デモンストレーション目的(必要に応じて)
  • numpy: 画像データを配列として処理
  • PIL.Image: 画像処理機能
  • os: ファイル操作

画像保存関数

def save_image(im, filename="saved_image.png"):
    """画像をファイルに保存する関数"""
    if im is not None and "composite" in im:
        # 合成画像(最終結果)を取得
        composite = im["composite"]

        # numpy配列の場合はPIL Imageに変換
        if isinstance(composite, np.ndarray):
            composite = Image.fromarray(composite)

        # 画像を保存
        composite.save(filename)
        return f"画像が正常に {filename} として保存されました"
    else:
        return "保存する画像がないか、無効な画像形式です"

この関数は以下のことを行います:

  • ImageEditorからの出力を取得し、それが有効かチェックします
  • compositeキーにアクセスして最終的な合成画像を取得します
  • 必要に応じてnumpy配列からPIL Imageに変換します
  • 指定されたファイル名で画像を保存します
  • 操作の結果に関するメッセージを返します

Gradio UIの作成

with gr.Blocks() as demo:
    with gr.Row():
        # 1:1の縦横比でImageEditorコンポーネントを作成
        im = gr.ImageEditor(
            type="numpy",  # 画像はnumpy配列として処理される
            crop_size="1:1",  # 正方形のトリミング比率を設定
            label="画像エディタ"
        )
        # プレビュー表示用のImageコンポーネントを作成
        im_preview = gr.Image(label="プレビュー")

ここでは:

  • gr.Blocks()でUIの作成を開始
  • gr.Row()で水平レイアウトを作成
  • gr.ImageEditorを設定:
    • type="numpy": 画像をnumpy配列として処理
    • crop_size="1:1": 画像を正方形にトリミングするオプション
    • label="画像エディタ": コンポーネントのラベル
  • gr.Imageでプレビュー表示用のコンポーネントを作成

イベントカウンター

# 各種イベントを追跡するカウンター
n_upload = gr.Number(0, label="アップロードイベント数", step=1)
n_change = gr.Number(0, label="変更イベント数", step=1)
n_input = gr.Number(0, label="入力イベント数", step=1)
  • 各種のユーザーイベントを追跡するための数値カウンターを作成します
  • この例では、3種類のイベントを追跡しています:
    • アップロードイベント:新しい画像がアップロードされたとき
    • 変更イベント:画像が何らかの方法で変更されたとき
    • 入力イベント:ユーザーが直接画像を編集したとき

保存機能

# ファイル名入力と保存ボタンを追加
with gr.Row():
    filename_input = gr.Textbox(value="my_drawing.png", label="ファイル名")
    save_btn = gr.Button("画像を保存")

# 保存操作のステータスメッセージ
save_status = gr.Textbox(label="保存ステータス", interactive=False)
  • 保存機能のためのUI要素を追加:
    • ファイル名を入力するためのテキストボックス(デフォルト値付き)
    • 保存アクションを開始するボタン
    • 保存操作の結果を表示するステータステキストボックス

イベントハンドラ

# イベントハンドラーを定義:
# 画像がアップロードされたらアップロードカウンターを増加
im.upload(lambda x: x + 1, outputs=n_upload, inputs=n_upload)

# 画像が変更されたら変更カウンターを増加(ユーザー入力または関数更新による)
im.change(lambda x: x + 1, outputs=n_change, inputs=n_change)

# ユーザーが画像を変更したら入力カウンターを増加
im.input(lambda x: x + 1, outputs=n_input, inputs=n_input)

# 画像が変更されたらプレビューエリアに合成画像を表示
im.change(lambda im: im["composite"] if im and "composite" in im else None,
          outputs=im_preview,
          inputs=im,
          show_progress="hidden")

# 保存ボタンクリックイベントを設定
save_btn.click(
    fn=save_image,
    inputs=[im, filename_input],
    outputs=save_status
)

この部分ではUIのインタラクティブな動作を定義しています:

  1. イベントカウンター更新:

    • .upload().change().input()メソッドを使って各種イベントを検出
    • それぞれのイベントが発生するとカウンターを1増加
  2. プレビュー更新:

    • 画像が変更されるたびに、im.change()イベントでプレビュー画像を更新
    • compositeキーにアクセスして最終的な合成画像を取得
  3. 保存機能:

    • 保存ボタンがクリックされたときにsave_image関数を呼び出す
    • 現在の画像とユーザーが指定したファイル名を関数に渡す
    • 保存操作の結果をステータステキストボックスに表示

アプリケーションの起動

# このスクリプトが直接実行されたときにデモを起動
if __name__ == "__main__":
    demo.launch()
  • if __name__ == "__main__":は、このスクリプトが直接実行されたときだけ以下のコードを実行するPythonのイディオム
  • demo.launch()でGradioアプリケーションを起動し、ローカルのWebサーバーを開始

ImageEditorの主な特徴

編集ツール

ImageEditorコンポーネントには、以下のような編集ツールが含まれています:

  • ブラシ: 自由に描画することができます
  • 消しゴム: 描画した内容を消去できます
  • トリミング: 画像の一部を切り抜くことができます
  • レイヤー: 複数のレイヤーで作業でき、それぞれを個別に編集できます

データ構造

ImageEditorからの出力はEditorValueと呼ばれる辞書形式のオブジェクトです:

{
    'background': [背景画像データ],
    'layers': [レイヤーのリスト],
    'composite': [最終的な合成画像]
}
  • background: 編集の背景となる画像
  • layers: 追加されたレイヤーのリスト
  • composite: すべてのレイヤーを合成した最終画像

まとめ

このチュートリアルでは、GradioのImageEditorコンポーネントを使用して、以下のことを学びました:

  1. 基本的な画像編集アプリケーションの作成方法
  2. イベントハンドラを使ったインタラクティブな機能の実装
  3. 編集した画像の保存とファイル管理
  4. ImageEditorコンポーネントの主な特徴と出力データ構造

Gradioを使うと、複雑な画像処理機能を持つウェブアプリケーションを、わずか数十行のPythonコードで実装できます。これは、実用的なツール開発だけでなく、AIモデルのデモンストレーションやプロトタイピングにも非常に便利です。

さらなる学習リソース

ノートブック

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?