😎

rembgで画像の輪郭抽出

2022/10/10に公開

きっかけ

下記 tweet を見かけたので試してみる。

スクリプト

rembg_test.py を下記内容で作成する。

from rembg import remove
from PIL import Image
input_path = 'input.jpg'
output_path = 'output.png'
input = Image.open(input_path)
output = remove(input)
output.save(output_path)

環境構築

>pip install rembg

(略)

Successfully installed aiohttp-3.8.1 aiosignal-1.2.0 anyio-3.6.1 async-timeout-4.0.2 asyncer-0.0.1 asynctest-0.13.0 attrs-22.1.0 click-8.1.3 coloredlogs-15.0.1 fastapi-0.80.0 filetype-1.1.0 flatbuffers-22.9.24 frozenlist-1.3.1 h11-0.14.0 humanfriendly-10.0 imagehash-4.2.1 llvmlite-0.39.1 mpmath-1.2.1 multidict-6.0.2 numba-0.56.2 numpy-1.21.6 onnxruntime-1.12.1 opencv-python-headless-4.6.0.66 pydantic-1.10.2 pymatting-1.1.8 pyreadline-2.1 python-multipart-0.0.5 rembg-2.0.25 setuptools-59.8.0 sniffio-1.3.0 starlette-0.19.1 sympy-1.10.1 uvicorn-0.18.3 watchdog-2.1.9 yarl-1.8.1

AttributeError: module 'cv2' has no attribute 'gapi_wip_gst_GStreamerPipeline'

スクリプトを実行してみる。

>python rembg_test.py
Traceback (most recent call last):
  File "rembg_test.py", line 1, in <module>
    from rembg import remove
  File "C:\usr\Python37\lib\site-packages\rembg\__init__.py", line 5, in <module>
    from .bg import remove
  File "C:\usr\Python37\lib\site-packages\rembg\bg.py", line 6, in <module>
    from cv2 import (
  File "C:\usr\Python37\lib\site-packages\cv2\__init__.py", line 181, in <module>
    bootstrap()
  File "C:\usr\Python37\lib\site-packages\cv2\__init__.py", line 175, in bootstrap
    if __load_extra_py_code_for_module("cv2", submodule, DEBUG):
  File "C:\usr\Python37\lib\site-packages\cv2\__init__.py", line 28, in __load_extra_py_code_for_module
    py_module = importlib.import_module(module_name)
  File "C:\usr\Python37\lib\importlib\__init__.py", line 127, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
  File "C:\usr\Python37\lib\site-packages\cv2\gapi\__init__.py", line 290, in <module>
    cv.gapi.wip.GStreamerPipeline = cv.gapi_wip_gst_GStreamerPipeline
AttributeError: module 'cv2' has no attribute 'gapi_wip_gst_GStreamerPipeline'

エラーの内容をググってみて見つかった参考ページの通り、下記バージョン指定で opencv-python をインストールする。

pip install opencv-python==4.5.5.64

u2net.onnx

再度スクリプトを実行してみる。

>python rembg_test.py
Access denied with the following error:

        Too many users have viewed or downloaded this file recently. Please
        try accessing the file again later. If the file you are trying to
        access is particularly large or is shared with many people, it may
        take up to 24 hours to be able to view or download the file. If you
        still can't access a file after 24 hours, contact your domain
        administrator.

You may still be able to access the file from the browser:

         https://drive.google.com/uc?id=1tCU5MM1LhRgGou5OpmpjBQbSrYIUoYab

Traceback (most recent call last):
  File "rembg_test.py", line 6, in <module>
    output = remove(input)
  File "C:\usr\Python37\lib\site-packages\rembg\bg.py", line 133, in remove
    session = new_session("u2net")
  File "C:\usr\Python37\lib\site-packages\rembg\session_factory.py", line 61, in new_session
    str(path), providers=ort.get_available_providers(), sess_options=sess_opts
  File "C:\usr\Python37\lib\site-packages\onnxruntime\capi\onnxruntime_inference_collection.py", line 347, in __init__
    self._create_inference_session(providers, provider_options, disabled_optimizers)
  File "C:\usr\Python37\lib\site-packages\onnxruntime\capi\onnxruntime_inference_collection.py", line 384, in _create_inference_session
    sess = C.InferenceSession(session_options, self._model_path, True, self._read_config_from_model)
onnxruntime.capi.onnxruntime_pybind11_state.NoSuchFile: [ONNXRuntimeError] : 3 : NO_SUCHFILE : Load model from D:\home\wurly\.u2net\u2net.onnx failed:Load model D:\home\wurly\.u2net\u2net.onnx failed. File doesn't exist

u2net.onnx が必要らしいので、上記からダウンロードし、~/.u2net/" に保存する。

実行例

Photographic color portrait of software engineer, out of focus shot

上記 Prompt にて Stable Diffusion で生成した画像を、CodeFormerでピンボケ画像を補正する で補正したものを使います。

確かに、髪の毛の細かい部分も含めて、上手く輪郭抽出できています。

どこが背景であるとか、どこが対象物であるとか指定せずとも、remove() 一発でできるというのがすごいですね。

変換前

変換後

参考

Discussion