このノートブックでは、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のインタラクティブな動作を定義しています:
-
イベントカウンター更新:
.upload()
、.change()
、.input()
メソッドを使って各種イベントを検出- それぞれのイベントが発生するとカウンターを1増加
-
プレビュー更新:
- 画像が変更されるたびに、
im.change()
イベントでプレビュー画像を更新 composite
キーにアクセスして最終的な合成画像を取得
- 画像が変更されるたびに、
-
保存機能:
- 保存ボタンがクリックされたときに
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
コンポーネントを使用して、以下のことを学びました:
- 基本的な画像編集アプリケーションの作成方法
- イベントハンドラを使ったインタラクティブな機能の実装
- 編集した画像の保存とファイル管理
ImageEditor
コンポーネントの主な特徴と出力データ構造
Gradioを使うと、複雑な画像処理機能を持つウェブアプリケーションを、わずか数十行のPythonコードで実装できます。これは、実用的なツール開発だけでなく、AIモデルのデモンストレーションやプロトタイピングにも非常に便利です。
さらなる学習リソース
ノートブック

Google Colab
デモアプリ

Image Editor Demo - a Hugging Face Space by MakiAi
Discover amazing ML apps made by the community
コメント