Rembgではアニメ系の背景切り抜きが甘いので、今回はRembgのモデルをAnime-Segmentation(isnet-anime)に切り替えて使う場合と本家のAnime-Segmentationをそのまま使った場合とFastSAMを使った場合の3つの比較結果を公開してみます。
サンプルに使ったのはhololiveの沙花叉クロヱさんです。ch登録よろしくちゃん。
実験環境
OS : Windows 11
conda仮想環境
- python 3.11
- rembg 2.0.56
Rembg
Install
先ずは公式ガイドの通りpipでインストールします。
今回はGPU版を使いたいので最初にONNEXをインストール。
コマンドはONNEXのstart guidから。
# see https://onnxruntime.ai/getting-started
pip install onnxruntime-gpu
pip install rembg[gpu,cli]
インストール確認は下記のコマンドで行いました。
rembg --help
watchdog,gradio,asyncerの順で足りないと言われたのでライブラリを追加でインストールしました。
pip install watchdog,gradio,asyncer
無事にインストールが成功するとhelpコマンドで下記のメッセージが出ます。
Usage: rembg.exe [OPTIONS] COMMAND [ARGS]...
Options:
--version Show the version and exit.
--help Show this message and exit.
Commands:
b for a byte stream as input
d download all models
i for a file as input
p for a folder as input
s for a http server
Rembgのモデル切替コード
new_sessionに名前を入れるだけです。(公式の参考コード)
モデルの使用が初めての場合は”C:\Users\自分.u2net”のフォルダにダウンロードされます。
今回使うisnet-animeは”https://github.com/danielgatis/rembg/releases/download/v0.0.0/isnet-anime.onnx”からダウンロードされます。
from rembg import remove, new_session
import cv2
input_path = 'test.jpg'
output_path = 'output.jpg'
print('read img')
input = cv2.imread(input_path)
print('load session')
my_session = new_session(model_name="isnet-anime")
print('remove process')
output = remove(input, session=my_session)
print('write img')
cv2.imwrite(output_path, output)
上記のコードは下記のコマンドと一緒です。
rembg i -m isnet-anime input.jpg output.jpg
セッション変数(my_session)をリセットしなければロード時間が短縮出来るので、沢山の画像を処理したい場合はmy_session変数生成後にfor文でremove関数を回してください。
公式のサンプル:How to iterate over files in a performatic way
結果
上から順番にu2net,u2net-human-seg,isnet-animeです。isnet-animeの性能がずば抜けている。。。
Rembgのコード版とコマンド版の違い(未解決)
上記のisnet-animeモデルを使ったコードとコマンドでそれぞれ実行すると結果が異なります。(結果画像3枚目と4枚目)
何故なのか未だ分かっていません。。。
Rembgでコードを切り替えて使うと結果が安定しないので、isnet-animeの本家のプロジェクトであるAnime-Segmentationでも実験してみました。
Anime-Segmentation
Install
公式のガイドの通りpytorchとrequirements.txtをインストールします。
pytorch関連のバージョンは私の場合、下記のようにしてあります。
torch : 2.2.1+cu118
torchvision : 0.17.1+cu118
pytorch-lightning : 2.0.7
モデルのダウンロード
既にRembgでonnx版のモデルはありますが、サンプルコードではckpt版を使うようになっているのでHuggingFaceからダウンロードしてきます。
git clone https://github.com/SkyTNT/anime-segmentation/tree/main?tab=readme-ov-file
cd anime-segmentation
mkdir saved_models
# saved_modelsフォルダにダウンロードしたisnetis.ckptをコピー
サンプルコードの実行
inference.pyを実行します。
- inputはファイル名ではなくフォルダ名を指定
- outもフォルダを指定
- モデルの保存場所がsaved_modelsではない場合やモデル名を変更した場合は–ckptオプションでモデルの保存場所を指定
mkdir input
# inputフォルダの中にテストしたい画像を入れる
python inference.py --net isnet_is --data input --out out --img-size 1024 --only-matted
予測閾値の変更
Rembgと違いAnime-Segmentationでは背景マスクの予測結果に触れるので、ここでちょっと2値化して結果を調整してみます。
inference.pyのdef get_maskメソッドで使われているpredという変数がそれです。
pred = cv2.resize(pred, (w0, h0))[:, :, np.newaxis]
# 38行目以下を下記に修正 | return pred
# 2値化処理
_, binary_mask = cv2.threshold(pred, 0.5, 1, cv2.THRESH_BINARY)
binary_mask = binary_mask[:, :, np.newaxis]
return binary_mask
predでは1-0で各ピクセルの背景確率を出しているので、上記のコードでざっくりと0.5以上を非背景、0.5未満を背景で分離させています。
最後にチャンネルを調整して呼び出し元にリターンしています。
結果
上からデフォルト版とマスクを弄った版の2枚です。
rembgのコマンドライン版と違って、本家では右肩の背景とリボンが精度低めな感じになっています。
マスクは色々試して閾値0.45辺りで綺麗に切り取れたかなという感じ。
FastSAM
背景というよりは広くセグメンテーション用のモデルですがおまけ的に実験してみます。
Rembgでsamを動かす場合
公式では下記のコマンドが紹介されています。
rembg i -m sam -x '{ "sam_prompt": [{"type": "point", "data": [724, 740], "label": 1}] }' examples/plants-1.jpg examples/plants-1.out.png
prormptのtypeをtextにしたものを探していたのですが、モデルを処理しているモジュール(sam.py)を見た限りでは見つからなかったので今回は本家のFastSAMをインストールして使ってみました。
Install
下記のページの通りインストールしました。
プロンプトは何も指示していない場合、アニメキャラの伝家の宝刀”a girl”プロンプトを入れた場合の2種類をFastSAM-x.ptモデルの方で実施しました。
結果
背景除去用ではないのですがプロンプト指示無し版(上)は服と椅子を分けた唯一のモデルでした。
プロンプト”a girl”では顔の下半分のみの検知でした。
流石に適当すぎたのか。。。