Layerdivider を 高速化してみる
はじめに
デスクトップ PC が壊れたため、ノートPCでも扱えるツールを探していたところ、AI を使わずに画像のレイヤー分解を行う layerdivider
を思い出しました。そこで、layerdivider
の高速化などを試みたので、その内容を共有します。
高速化を施したバージョンは以下のスペースから触れることができます:
なお、SAM を用いたレイヤー分解などの高度な機能には対応していないため、完全な機能を使いたい場合は 本家リポジトリ をローカルで実行してください。
layerdivider
AI を用いず、色空間に基づいたセグメンテーション手法は他にも存在しますが、layerdivider
は学習不要かつアルゴリズムがシンプルである点が大きな特徴です。今回の改修で NumPy による処理へと置き換えた結果、CPU のみでも数秒で変換できるようになりました。
この軽量さから、Rust 等で実装しなおして WebAssembly(WASM)にコンパイルすれば、ブラウザ上だけでも動作可能になるポテンシャルがあります。
基本的な動作原理としては、各ピクセルの色をクラスタリングした後に、同系色や空間的に近い色をマージして領域を分割し、その後、効果レイヤーを分割するという流れです。
詳しい仕組みについては、作者様による以下の記事が非常に参考になりますので、ぜひご覧ください:
高速化
一部の行列処理が pandas で実装されていたため、NumPy に置き換えました。その結果、従来は約5分かかっていた処理が、約5秒にまで短縮されました。
NumPy だけでは処理速度が不十分であれば、Numba や Cython によるさらなる高速化も検討する予定でしたが、ノートPCでも十分高速に動作するようになったため、今回はここで一旦終了としています。
なお、後から気づいたのですが、すでに領域分割部分については NumPy 実装が存在していました…。ただし、今回は効果レイヤーの分割処理も NumPy に置き換えたため、さらに高速に処理が行えるようになっています。
cProfile によるボトルネックの特定
Python の高速化においてボトルネックの特定には、標準ライブラリの cProfile
を使うと便利です:
プロファイリングしたい関数を以下のように呼び出すと、profile.prof
に結果が保存されます:
import cProfile
cProfile.run('func()', filename="profile.prof")
出力結果はテキストでも確認可能ですが、snakeviz
を使えばブラウザでグラフとして可視化できます。
cProfile の結果
今回は get_base
関数、特にその中で使用されている pandas の apply
関数が主なボトルネックであることがわかりました。
get_base
関数は領域分割を行う処理であり、以下のように各ピクセルの値を持つデータフレームを更新するために使われていますが、これは行列計算に置き換えられそうです:
pytoshop について
一部の処理が Cython で書かれており、pytoshop
はビルド済みの wheel を提供していないため、利用者が自身でビルドする必要があります。
特に Windows 環境では Visual Studio Build Tools が必要となり、インストールがやや煩雑なため、ビルド済みの wheel を用意しました(とりあえず Python 3.10 の Windows および Linux 向けのみ)。
おわりに
layerdivider
は、AI を使わず、CPU のみで動作する軽量なレイヤー分割ツールとして非常に面白い存在だと思います。
近年は 多様な分野で 深層学習ベースのアプローチが主流となっていますが、こうした非AIのアルゴリズムにも独自の強みや可能性があり、今後も注目していきたい分野です。
Discussion