3
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?

Streamlit + Rembg + Pillow で画像切り抜き&合成アプリを作成

3
Posted at

はじめに

機械学習を活用した画像の背景切り抜きに特化したライブラリとしてRembgというものがあるようです。
今回はStreamlit+Rembg+Pillowの構成を取ることで、フロント・バックエンド一体型の画像編集アプリを作成しました!

rembgとは

rembgはPythonで書かれたオープンソースの画像処理ライブラリであり、画像から背景を削除するための機能を提供しています。

rembgではU-2-Netという機械学習のモデルが使用されています。画像から前景(注目している対象)を背景から分離する処理が可能なモデルです。

↓こちらの記事の画像がイメージしやすいです

rembgを使うことで、簡単なコードの記述だけでU-2-Netの技術を使用することができます。

環境構築

実際に手元で行った構築作業です。(windows環境)
rembgを利用するためには、onnxruntime のインストールも必要になります。
対応バージョンの関係でPython 3.12を指定して実行しました。

# Python 3.12で新しい仮想環境を作成
py -3.12 -m venv venv

# 仮想環境を有効化
venv\Scripts\activate

# 必要パッケージをインストール
pip install streamlit rembg pillow 
pip install onnxruntime

作ってみた:画像切り抜き&合成アプリ

今回は以下が実行できるアプリを作成してみました
人物と背景を合成して簡単な年賀状やポストカードを作るイメージです。

  • 背景を切り抜きたい画像(A)をアップロード
  • 背景にしたい画像(B)をアップロード
  • AとBをサイズ調整して合成

コード

app.py
import streamlit as st
from rembg import remove
from PIL import Image
import io

st.title("背景切り抜き&合成アプリ")

# 2つのカラムでファイルアップローダーを配置
col1, col2 = st.columns(2)

with col1:
    st.subheader("切り抜き対象の画像")
    uploaded_file = st.file_uploader(
        "切り抜きたい画像をアップロード",
        type=["png", "jpg", "jpeg"],
        key="main"
    )

with col2:
    st.subheader("背景画像")
    background_file = st.file_uploader(
        "背景画像をアップロード(オプション)",
        type=["png", "jpg", "jpeg"],
        key="background"
    )

# 画像プレビュー表示
if uploaded_file or background_file:
    col_preview1, col_preview2 = st.columns(2)
    
    with col_preview1:
        if uploaded_file:
            st.subheader("元画像")
            input_image = Image.open(uploaded_file)
            st.image(input_image, use_container_width=True)
    
    with col_preview2:
        if background_file:
            st.subheader("背景画像")
            background_preview = Image.open(background_file)
            st.image(background_preview, use_container_width=True)

if uploaded_file:
    input_image = Image.open(uploaded_file)

    if st.button("背景を切り抜く"):
        with st.spinner("処理中..."):
            # 背景を削除
            output_image = remove(input_image)

        col_result1, col_result2 = st.columns(2)
        
        with col_result1:
            st.subheader("切り抜き結果")
            st.image(output_image, use_container_width=True)

            # 切り抜き結果のダウンロード
            buf1 = io.BytesIO()
            output_image.save(buf1, format="PNG")
            st.download_button(
                "切り抜き画像をダウンロード",
                data=buf1.getvalue(),
                file_name="removed_bg.png",
                mime="image/png"
            )

        # 背景画像がアップロードされている場合は合成
        if background_file:
            with col_result2:
                st.subheader("背景と合成結果")
                
                background_image = Image.open(background_file).convert("RGB")
                
                # 切り抜き画像のサイズを背景画像に合わせる
                output_resized = output_image.resize(background_image.size, Image.Resampling.LANCZOS)
                
                # 背景画像に切り抜き画像を合成
                background_image.paste(output_resized, (0, 0), output_resized)
                
                st.image(background_image, use_container_width=True)
                
                # 合成画像のダウンロード
                buf2 = io.BytesIO()
                background_image.save(buf2, format="PNG")
                st.download_button(
                    "合成画像をダウンロード",
                    data=buf2.getvalue(),
                    file_name="composite.png",
                    mime="image/png"
                )
        

実行

# 実行コマンド
streamlit run app.py

実行すると、http://localhost:8501 に作成した画面が表示されます。

ポイント

切り抜き処理のポイントは以下の処理です。
rembgのremove関数で背景を削除できます。
元画像の切り抜きに関する記述はこれだけです。

# 背景を削除
output_image = remove(input_image)

切り抜き画像を背景と合成する処理はPillow (PIL) ライブラリを使用しています。
基本的な画像操作はこのライブラリで完結するようです。

# 切り抜き画像のサイズを背景画像に合わせる:resize 関数
 output_resized = output_image.resize(background_image.size, Image.Resampling.LANCZOS)
                
# 背景画像に切り抜き画像を合成:paste 関数
background_image.paste(output_resized, (0, 0), output_resized)

画面イメージ

1. 初期画面

最初の状態。画面の左右それぞれで画像をアップロードできます。

image.png


2. 画像アップロード後

アップロードするとプレビューされます。
今回は犬の画像にフレームを合成してみます。
※フリー画像を使用しています

image.png


3. 切り抜き結果

「背景を切り抜く」ボタンを押すことで結果が出力されます。

  • 左側:背景を切り抜いた状態
  • 右側:背景との合成結果

image.png

かなり正確に切り抜きができているので驚きました…!
特別な調整はしていないのですが、自然な形で合成もできていますね。


4. 画面全体

以上を一枚の画面で実現しています。
image.png

まとめ

Rembgを使用することで、複雑な機械学習モデルの知識がなくても、remove()関数ひとつで高精度な背景切り抜き処理を実装できることが分かりました。

今回の実装では、以下のように各ライブラリの役割を明確に分けることができ、バックエンドとフロントエンドを分離することなく、Pythonのみで完結する画像編集アプリを手早く作成することができました。

  • Rembg: 背景切り抜きのコア処理
  • Pillow: 画像のリサイズや合成などの基本的な画像操作
  • Streamlit: UIの構築とファイルアップロード機能

今回の構成を応用することで、「撮影した写真から自己紹介カードを作る」「風景写真の中に人物を合成する」といった実用的なアプリケーションへの展開も実現できそうです。

また、U-2-Netそのものの仕組みについても興味が湧いてきたので、画像処理プロセスの詳細についても調べてみようと思います。

作成したコード

画像ソース

参考

3
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
3
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?