画像からの「人や物」「背景」「テキスト」の除去をPythonとClipdrop APIsで実装してみた

[Supership](https://supership.jp/)の名畑です。6月となり、[2023年春アニメ](https://www.animatetimes.com/tag/details.php?id=5228)が次々とクライマックスを迎える中、[2023年夏アニメ](https://www.animatetimes.com/tag/details.php?id=5806)の情報も盛り上がり、落ち着かない毎日です。

## はじめに

[Clipdrop](https://clipdrop.co/)というサービスがあります。[Stable Diffusion](https://ja.stability.ai/stable-diffusion)の提供元である[stability.ai](https://stability.ai/)による画像編集ツールです。

[Stability AI 日本公式](https://note.com/stabilityai)が公開している「[様々な生成AIが無料で使えるClipdropが凄い](https://note.com/stabilityai/n/n3fbbcd420b4a)」という記事に概要がまとまっています。一部の物体のみ取り除いたり、背景のみ取り除いたり、様々な画像加工が可能です。

ブラウザ上で利用できるのですが、今回は[ClipDrop APIs](https://clipdrop.co/apis)経由で使ってみましたので、その内容を記事にします。

APIとしては下記が提供されていますが、今回はこのうちの3つ**Inpainting**、**Remove Background**、**Remove Text**を試します。

- [Inpainting](https://clipdrop.co/apis/docs/inpainting)
- [Remove Background](https://clipdrop.co/apis/docs/remove-background)
- [Super resolution](https://clipdrop.co/apis/docs/super-resolution)
- [Remove Text(Beta)](https://clipdrop.co/apis/docs/remove-text)
- [Text to Image(Beta)](https://clipdrop.co/apis/docs/text-to-image)
- [Replace Background(Beta)](https://clipdrop.co/apis/docs/replace-background)
- [Portrait Depth Estimation](https://clipdrop.co/apis/docs/portrait-depth-estimation)
- [Portrait Surface Normals](https://clipdrop.co/apis/docs/portrait-surface-normals)


## アカウント作成

[Sing in](https://clipdrop.co/apis/signin)にてメールアドレスを入力すると、メールが届きます。そこに記載されているリンクを押すとSign up/Sign in完了です。

**My Account**のページの**Claim my 100 free credits**を押し、名前と電話番号を入力してSMSでの認証を行えば100クレジットを入手することができます。

## API KEY

API KEYはMy Accountのページの**Reveal API KEY**を押すと取得できます。

取得したAPI KEYはいつも通りに環境変数にセットしました。**CLIPDROP\_API\_KEY**という環境変数名としました。

```bash
export CLIPDROP_API_KEY=ここに取得したAPI KEYを書く
```

## 人や物の除去

まずは[Inpainting](https://clipdrop.co/apis/docs/inpainting)のAPIを使用して画像から特定オブジェクトの除去をしてみました。

コードは以下で全部です。非常にシンプルです。
「**元画像**」と「**取り除く対象を示したマスク画像**」をパラメータとして渡します。

```Python
import requests
import os
import time

## API呼び出し
r = requests.post('https://clipdrop-api.co/cleanup/v1',
                  files={
                      'image_file': ('image.jpg', open("./image.jpg", "rb"), 'image/jpeg'),
                      'mask_file': ('mask.png', open("./mask.png", "rb"), 'image/png')
                  },
                  headers={'x-api-key': os.getenv("CLIPDROP_API_KEY")}
                  )

## レスポンスから画像を生成
if r.ok:
    with open(f"./clipdrop_{int(time.time())}.png", "wb") as f:
        f.write(r.content)
else:
    r.raise_for_status()
```


### パターン1

元画像としては[前の記事](https://qiita.com/nabata/items/d1f09a76e0ec69e34517)にてStable Diffusionで生成した下記画像を用いました。

<img width="50%" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/869934/f71db539-a1bc-1840-8ed0-8392d8f27d05.png">

今回はこの画像から通行人を取り除いてみようと思います。

そのため、マスクとしては、通行人がいる箇所のみ**白**とした画像を用意します。

<img width="50%" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/869934/d6f4c477-cca1-cb71-1f9d-f43df8e7f9ab.png">

この結果として生成された画像は下記です。

<img width="50%" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/869934/d7462f3e-2aa9-25aa-ab32-99c871bd5760.png">

人の痕跡は残ってはいますが、かなり綺麗に取り除かれているように思えます。

二つ並べて比較してみましょう。

| 元画像 | 生成画像 |
| :---: | :---: |
| ![image_1_a.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/869934/f71db539-a1bc-1840-8ed0-8392d8f27d05.png) | ![image_1_c.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/869934/d7462f3e-2aa9-25aa-ab32-99c871bd5760.png) |

元々がAI生成で背景が明瞭ではないこともあってか、違和感少ないですね。

### パターン2

次は実際の写真を元にして試してみようと思います。

弊社オフィスは[虎ノ門ヒルズ ビジネスタワー](https://www.toranomonhills.com/about/business_tower.html)にあるのですが、こちらはよくランチで堪能させていただいております[福島屋食堂](https://tabelog.com/tokyo/A1308/A130802/13248363/)様の**館が森高原豚の生姜焼き定食**です。こういった使い方をする予定なかったので雑な写真ですみません。本当に美味しいし小鉢が嬉しい素晴らしい定食です。

<img width="50%" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/869934/dbc4cdde-d6cc-5346-3a99-6f8356cead24.jpeg">

今回はこの画像からお手拭きを取り除いてみましょう。

ということでマスク画像は下記。お手拭きのあたりのみ**白**にしています。

<img width="50%" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/869934/f224eef9-e90b-46a7-b31d-f0a177f18cc5.png">

そして出来上がった画像は下記です。

<img width="50%" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/869934/76844778-8fac-a997-67c1-0df2571cd0a4.png">

めちゃくちゃ自然ではないでしょうか？

今回も二つ並べて比較してみましょう。

| 元画像 | 生成画像 |
| :---: | :---: |
| ![image_2_a.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/869934/dbc4cdde-d6cc-5346-3a99-6f8356cead24.jpeg) | ![image_2_c.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/869934/76844778-8fac-a997-67c1-0df2571cd0a4.png)|

トレイの模様にせよ影にせよ、不自然さがないと言えば嘘ですが、鈍感な私はきっと、加工したものだと知らなければなにも思わない。

### パターン3

次は同じく**館が森高原豚の生姜焼き定食**の写真から、右側の汁物を取り除くことに挑戦してみます。

<img width="50%" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/869934/4164b9a0-535c-60fc-92df-25e812994210.jpeg">

マスク画像は下記。

<img width="50%" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/869934/787a4a2b-d88d-a713-07ee-cbfd2c4254e7.png">

元画像と結果を並べたものは以下です。

| 元画像 | 生成画像 |
| :---: | :---: |
| ![image_2_a.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/869934/dbc4cdde-d6cc-5346-3a99-6f8356cead24.jpeg) | ![image_3_c.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/869934/4f9094c7-25a9-92bb-0756-2aea574f8cc0.png)|

流石にちょっと厳しかったですね。

ただ、除去はきっちりされているので、用途によっては充分に目的達成かもしれません。


## 背景除去

次は[Remove Background](https://clipdrop.co/apis/docs/remove-background)のAPIを使って、背景を取り除いてみます。

コードの呼び出すエンドポイントを変えます。**mask_file**は不要です。

API呼び出し箇所のみ抜粋したコードは下記です。

```Python
r = requests.post('https://clipdrop-api.co/remove-background/v1',
                  files={
                      'image_file': ('image.png', open("./image.png", "rb"), 'image/png'),
                  },
                  headers={'x-api-key': os.getenv("CLIPDROP_API_KEY")}
                  )
```

元画像は先ほどと同じものとします。

<img width="50%" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/869934/5f47203f-5192-37df-1122-7a054939f1a9.png">

結果はこちら。

<img width="50%" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/869934/300e321c-e31e-d258-a045-9b23ad956cc1.png">

かなり綺麗に背景を取り除いてくれていますね。

### rembgで試す

[前回の記事]()で用いたライブラリ[rembg](https://github.com/danielgatis/rembg)だとどうでしょうか。

インストールして

```shell-session
$ pip install rembg
```

呼び出して

```shell-session
$ rembg i image.png output.png
```

結果はこちら。

<img width="50%" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/869934/30eb8c98-3ba2-879c-85f8-2a5d04a9c820.png">

髪の毛や輪郭の辺りがClipdropのAPIに比べて荒いですが、一画像をさくっとデフォルト環境で試しただけですので、まあ、参考ということで。

## テキスト除去

最後に[Remove Text](https://clipdrop.co/apis/docs/remove-text)のAPIを用いたテキスト除去です。こちらはまだ**Beta**となっています。

先ほどのコードのエンドポイントを変えるのみです。

API呼び出し部分のみ抜粋したコードは下記です。

```Python
r = requests.post('https://clipdrop-api.co/remove-text/v1',
                  files={
                      'image_file': ('image.png', open("./image.png", "rb"), 'image/png'),
                  },
                  headers={'x-api-key': os.getenv("CLIPDROP_API_KEY")}
                  )
```

### パターン1

まずは文字と絵が重なっていないもので試してみました。

| 元画像 | 生成画像 |
| :---: | :---: |
| ![image_5_a.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/869934/a08a277a-e571-104d-ab92-6ba7a1bc8163.png) |![image_5_b.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/869934/deb9ce6e-c374-14e6-6c44-762f0b50f858.png)|

綺麗に文字だけ取り除かれているように見えますが、よく見ると左手の先も取り除かれてしまっていますね。

左手の先も数字の3のような形をしていますものね。

### パターン2

次は**模様のある吹き出し内に文字がある画像**で同様のことをしてみました。

| 元画像 | 生成画像 |
| :---: | :---: |
| ![image_5_c.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/869934/d3d25b9c-68cf-6e31-c8ca-2755e75dbb68.png) | ![image_5_d.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/869934/c20c04fd-1f20-c799-b348-eb933f2a611c.png)|

文字は取り除かれていますが、それ以外の箇所にも明らかな影響が出ていますね。文字として扱われても仕方ないと思えはしますが。

## 価格

先述しましたようにフリークレジットがありますが、それを超えて使用する場合はクレジットの購入が必要です。
価格は[Pricing](https://clipdrop.co/apis/pricing)に記載されています。

| クレジット数 | 金額(円) | 1クレジットあたりの金額(円) |
| :---: | :---: | :---: |
| 500 | ¥4,064 | ¥8.128 |
| 5,000 | ¥20,000 | ¥4.000 |
| 25,000 | ¥80,000 | ¥3.200 |
| 50,000  | ¥140,000 | ¥2.800 |
| 100,000 | ¥259,924 | ¥2.599 |
| 500,000 | ¥990,000 | ¥1.980 |
| 1,000,000 | ¥1,563,000 | ¥1.563 |

以下が各機能毎のクレジット消費数です。

今回試してみた**Cleanup**、**Remove text and logo**、**Remove background**はすべて呼び出し一回あたり1クレジットです。

| 機能 | クレジット数 |
| :---: | :---: |
| Cleanup | 1 credit / call |
| Remove text and logo | 1 credit / call |
| Depth estimation | 1 credit / call |
| Normals estimation | 1 credit / call |
| Remove background | 1 credit / call |
| Replace background | 1.5 credit / call |
| Text to image | 0.5 credit / call |
| Upscaler | From 0.2 credit / output megapixel |

## 最後に

技術の進化というのは手間を含めたコストの改善を生むわけですが、それを強く実感します。
前から[Photoshop](https://www.adobe.com/jp/products/photoshop.html)を使うなりして似たようなことはできますが、そのハードルは確実に下がっているなと。

かなり近い未来では格段に良いアウトプットが出ているのでしょうね。

## 宣伝

[SupershipのQiita Organization](https://qiita.com/organizations/supership-inc)を合わせてご覧いただけますと嬉しいです。他のメンバーの記事も多数あります。

Supershipではプロダクト開発やサービス開発に関わる方を絶賛募集しております。
興味がある方は[Supership株式会社 採用サイト](https://supership.jp/recruit/)よりご確認ください。