LaMa で物体を"無かったことにする" (画像内の物体をAIで自然に消す)

## はじめに

写真を撮ったら、余計なモノまで写っていた、なんてことありますよね？

![sofa.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1485835/1dc4185b-f674-2d47-cae2-cda31bd3e097.png)

- 「机の上のお菓子を消さなきゃ！」
- 「足元のコードが汚いなぁ」

そんなときに役立つのが、この LaMa です

https://github.com/saic-mdal/lama

何はともあれ動かしてみましょう

今回は Docker で動かします

## 実行環境

- macOS Monterey 12.6.1
- Rancher Desktop 1.6.2
- Python 3.10.6

CUDA 対応の GPU がないので CPU で実行しています

## 準備

公式リポジトリーをクローンしてきます

```bash
git clone https://github.com/saic-mdal/lama.git
```

ディレクトリーを移動します

```bash
cd lama
```

## コンテナのビルド

Docker ディレクトリーでコンテナをビルドします

```bash
cd docker
./build.sh
cd ..
```

## モデルのダウンロード

ファイルをダウンロードするために必要なライブラリをインストールします

```bash
pip install wldhx.yadisk-direct
```

最良のモデルファイルをダウンロードし、展開します

```bash
curl -L $(yadisk-direct https://disk.yandex.ru/d/ouP6l8VJ0HpMZg) -o big-lama.zip
unzip big-lama.zip
```

## テスト用データの準備

まずはテスト用データで動作を確認してみましょう

テスト用データをダウンロードし、展開します

```bash
curl -L $(yadisk-direct https://disk.yandex.ru/d/xKQJZeVRk5vLlQ) -o LaMa_test_images.zip
unzip LaMa_test_images.zip
```

展開すると、下画像のように xxx.png と xxx_mask.png がペアになったファイルが入っています

![スクリーンショット 2022-11-14 15.06.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1485835/5a00e9c4-a471-54d4-774e-3e3cef11d95f.png)

xxx.png　が元画像で、 xxx_mask.png が元画像から消したいところを示すマスク画像です

xxx_mask.png の黒い部分が残すところ、白い部分が消すところになります

### テスト画像の例

000068.png

![000068.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1485835/850095c2-e9f8-8b27-67c7-061fdb6a2f97.png)

000068_mask.png

![000068_mask.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1485835/8910052b-7564-f5d6-f788-e1e0313f97b5.png)

マスク画像を透過して元画像に重ねてみたのが下の画像になります

看板内の似顔絵や観覧車のいくつかの柱、パラソルや何人かの人間が削除対象として選択されています

![000068_masked.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1485835/32d81722-a8de-1b34-00e6-23aac141f9de.png)

## テスト画像での削除処理実行

私の macOS で実行したとき、 `Permission Denied` エラーが発生したので、以下のファイルを編集しました

docker/2_predict.sh

```diff_shell
 docker run \
     -v "$SRCDIR":/home/user/project \
     -v "$MODEL_LOCAL_DIR":/data/checkpoint \
     -v "$INPUT_LOCAL_DIR":/data/input \
     -v "$OUTPUT_LOCAL_DIR":/data/output \
-    -u $(id -u):$(id -g) \ # ここを削除
     --name="lama-predict" \
     --rm \
     windj007/lama \
     /home/user/project/bin/predict.py \
         model.path=/data/checkpoint \
         indir=/data/input \
         outdir=/data/output \
         dataset.img_suffix=.png \
         $@
```

この状態で以下のコマンドを実行します

```bash
bash docker/2_predict.sh $(pwd)/big-lama $(pwd)/LaMa_test_images $(pwd)/output device=cpu
```

output ディレクトリーに各画像の処理結果が出力されます

output/000068_mask.png

![000068_mask.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1485835/cbb0eedf-b030-ae2d-a2b9-86127cef2fb9.png)

見事に対象物が消えました！

画像を交互に切り替えてみると、このようになります

![000068.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1485835/68eaba13-8d5f-ffbf-52bd-f1caa84d93c7.gif)

元あったものが消えて、違和感ないように背景が補完されているのが分かりますね

## 目的の画像を処理する

それでは、自分の用意した画像を処理してみましょう

まずマスク画像を作らないといけないので、元画像を画像編集ソフト（レイヤーが使えるもの）で開きます

※以降の画像は FireAlpaca　で編集した例です

https://firealpaca.com/ja/

![スクリーンショット 2022-11-14 15.29.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1485835/f580e372-7d2e-1463-f117-39281420bc46.png)

レイヤーを追加して、不透明度を50%などの透ける数値にしておきます

![スクリーンショット 2022-11-14 14.47.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1485835/da9b7109-4e04-4209-9548-b69c175dc1d5.png)

追加した方のレイヤーで画像全体を黒に塗りつぶした後、消したい部分だけを白に塗ります

![スクリーンショット 2022-11-14 14.50.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1485835/c4b46433-b922-3dad-9b20-f6bf90517e52.png)

いい感じに塗れたら追加したレイヤーの不透明度を100%にして、 xxx_mask.png として出力します

![スクリーンショット 2022-11-14 14.51.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1485835/ba52a919-ff3e-3a95-21ab-1ccc2c9987a5.png)

元画像 xxx.png と xxx_mask.png を targets などの適当なフォルダに配置します

以下のコマンドを実行します

```bash
bash docker/2_predict.sh $(pwd)/big-lama $(pwd)/targets $(pwd)/output device=cpu 
```

output ディレクトリーに処理結果が出力されました

![sofa_mask.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1485835/121874cb-3cc9-750c-af13-046a62e70caf.png)

お菓子とコードが完全に消えて、あたかも最初から存在していなかったかのようです

画像を交互に切り替えてみると、いかに自然かが分かりますね

![sofa.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1485835/ad3146d5-536f-ac07-6745-113a12033f68.gif)

## まとめ

GPU があれば refine=True を指定してもっと高精度にできるようなので、 Google Colab で試してみよう