概要
PIFuHDという、1枚(or 複数枚)の写真から立体的なメッシュを生成するというDeep Learningのモデルを試したのでそのメモです。
それを、Windows環境で実行するのに色々ハマりどころがあったのでそのメモです。
GitHubに上がっている動画を引用すると、以下のようなことができるものです。
環境構築
今回の環境はAnacondaを利用しています。(PIFuHDではPythonを利用しているのでPython環境が必要)
通常はAnacondaをインストールするとGUIもついてくるのでそこで環境の設定を行うことができます。
またそこから、Anacondaの環境が設定された状態のターミナルを起動することもできるので、コマンドラインからPythonスクリプトを実行するだけであればそれで事足ります。
しかし、色々なDeep Learningなモデルを試していると必ずShellスクリプトを扱う瞬間があります。
当然、Windowsのコマンドプロンプトでは実行できません。
ということで今回はGit for WindowsのBash環境でもAnaconda(conda
コマンド)を利用するようにセットアップしたいと思います。
(PIFuHDのデモを試すだけなら.sh
内のいくつかのコマンドを自分で叩けばいいだけなので必要ないと言えばないのですが)
Anacondaのインストール後、Git for Windows上でconda
コマンドが使えるように設定します。
Anacondaをインストール
まずはAnacondaをインストールします。
Anacondaのページの「Get Started」ボタンをクリックし、Install Anaconda Individual Editionをクリックしてダウンロードページに飛びます。
ダウンロードページにDownloadボタンがあるのでそれをクリックすると、ページ下部にあるダウンロードリンクの箇所までスクロールするので、そこから64-Bit Graphical Installerを選んでインストーラをダウンロードし、Anacondaをインストールします。
Pathを通す
インストールが終わったら、Bashが認識するようにはPathを通します。
するとconda
コマンド自体は認識してくれるようになります。
自分の環境では.basahrc
に以下を追記しました。
export PATH=$PATH:/c/Users/[USER_NAME]/anaconda3
export PATH=$PATH:/c/Users/[USER_NAME]/anaconda3/Scripts
インストールした場所に応じて適宜書き換えてください。
デフォルトのままであれば上と同じで大丈夫だと思います。
conda activate
でエラーが出る
Pathを通したあと、Anacondaの環境をActivateしようと$ conda activate
を実行すると以下のようなエラーが発生しました。
$ conda activate
CommandNotFoundError: Your shell has not been properly configured to use 'conda activate'.
If using 'conda activate' from a batch script, change your
invocation to 'CALL conda.bat activate'.
To initialize your shell, run
$ conda init <SHELL_NAME>
Currently supported shells are:
- bash
- cmd.exe
- fish
- tcsh
- xonsh
- zsh
- powershell
See 'conda init --help' for more information and options.
IMPORTANT: You may need to close and restart your shell after running 'conda init'.
以下の記事を参考に解決しました。
どうやらconda init
を実行すると自動的に書き込まれるものが書き込まれないための問題のようです。
なので手動で.bashrc
に以下を追記することで無事、Git for WindowsのBash上でもconda
が認識され、利用することができるようになりました。
# >>> conda init >>>
__conda_setup="$(CONDA_REPORT_ERRORS=false '$HOME/anaconda3/bin/conda' shell.bash hook 2> /dev/null)"
if [ $? -eq 0 ]; then
\eval "$__conda_setup"
else
if [ -f "$HOME/anaconda3/etc/profile.d/conda.sh" ]; then
. "$HOME/anaconda3/etc/profile.d/conda.sh"
CONDA_CHANGEPS1=false conda activate base
else
\export PATH="$PATH:$HOME/anaconda3/bin"
fi
fi
unset __conda_setup
# <<< conda init <<<
これを追記してから$ source ~/.bashrc
をするか、ターミナルを再起動すると無事、$ conda activate [ENV_NAME]
を実行することができるようになります。
うまく環境が適用されれば、プロンプトに環境名が表示されると思います。
PIFuHD向けのセットアップ
Anacondaの環境構築が終わったら、次にPIFUHD向けのセットアップをしていきます。
GitHubのREADMEには以下のように記述されているので、これらが利用可能なようにセットアップしていきます。
Requirements
- Python 3
- PyTorch tested on 1.4.0, 1.5.0
- json
- PIL
- skimage
- tqdm
- cv2
For visualization
- trimesh with pyembree
- PyOpenGL
- freeglut (use
sudo apt-get install freeglut3-dev
for ubuntu users) - ffmpeg
ちなみに手動によるセットアップについては、HDがつかないバージョンのリポジトリのREADMEに以下のように書かれているので、これを参考にセットアップしました。
(参考にしたのはOR manually setup environmentの部分です。それより上の部分はminicondaを使っていたりするので今回は参考にしていません)
Windows demo installation instuction
- Install miniconda
- Add
conda
to PATH - Install git bash
- Launch
Git\bin\bash.exe
-
eval "$(conda shell.bash hook)"
thenconda activate my_env
because of this - Automatic
env create -f environment.yml
(look this) - OR manually setup environment
conda create —name pifu python where pifu is name of your environment
conda activate
conda install pytorch torchvision cudatoolkit=10.1 -c pytorch
conda install pillow
conda install scikit-image
conda install tqdm
conda install -c menpo opencv
- Download wget.exe
- Place it into
Git\mingw64\bin
sh ./scripts/download_trained_model.sh
- Remove background from your image (this, for example)
- Create black-white mask .png
- Replace original from sample_images/
- Try it out -
sh ./scripts/test.sh
- Download Meshlab because of this
- Open .obj file in Meshlab
追加で必要なモジュールをインストールする
上記以外に、追加で以下のものもインストールしました。(PIFuHDのREADMEには書いてある)
それぞれ以下のようにインストールします。
$ conda install -c conda-forge trimesh
$ conda install -c anaconda pyopengl
WindowsにGLUTをインストールする
GLUTをインストールしないままにサンプルを試しに実行してみると以下のエラーが発生しました。
OpenGL.error.NullFunctionError: Attempt to call an undefined function glutInit, check for bool(glutInit) before calling
GLUTがないためのエラーです。
が、インストール方法が分からず、こちらの記事に助けられました。
この記事内では、さらに別の記事を参考に解消したと書かれています。
別の記事はこちら(WindowsのPythonでOpenGLを使う - TadaoYamaokaの日記)
そちらから引用させていただくと、
FreeGLUTのインストール
PyOpenGLとは別に、GLUTをインストールする必要がある。
GLUTは、OpenGLをプラットフォーム非依存で扱うためのライブラリのようだ。
本家のGLUTは、Windowsの64bitのバイナリがダウンロードできない。
代わりに、64bitのバイナリが提供されているFreeGLUTを導入する。
FreeGLUTのページから
Martin Payne's Windows binaries (MSVC and MinGW)
のリンクをたどり、
Download freeglut 3.0.0 for MSVC
からfreeglut-MSVC-3.0.0-2.mp.zipをダウンロードする。
zipファイル内のfreeglut\bin\x64\にあるfreeglut.dllをC:\Windows\System32にコピーする。
これで、GLUTが使用できるようになる。
ffmpegのインストール
ffmpegのインストールについてはこちらの記事を参考にさせていただきました。
基本的にはexe
ファイルを落としてきて、それを保存しPathに追加して認識させるだけです。
上記記事はコマンドプロンプトで使う例ですが、今回はGit Bashを利用しているので、.bashrc
に以下のようにパスを追加しました。
export PATH=$PATH:/path/to/bin/ffmpeg
Pythonファイルを修正
参考にしたこちらの記事にも書かれていますが、上記までのセットアップを終えてもなおエラーが出ました。
発生したエラーは以下。
Traceback (most recent call last):
File "C:\Users\[USER_NAME]\anaconda3\envs\pifu\lib\runpy.py", line 193, in _run_module_as_main
"__main__", mod_spec)
File "C:\Users\[USER_NAME]\anaconda3\envs\pifu\lib\runpy.py", line 85, in _run_code
exec(code, run_globals)
File "D:\MyDesktop\Python-Projects\pifuhd\apps\render_turntable.py", line 69, in <module>
renderer = ColorRender(width=args.width, height=args.height)
File "D:\MyDesktop\Python-Projects\pifuhd\lib\render\gl\color_render.py", line 34, in __init__
CamRender.__init__(self, width, height, name, program_files=program_files)
File "D:\MyDesktop\Python-Projects\pifuhd\lib\render\gl\cam_render.py", line 32, in __init__
Render.__init__(self, width, height, name, program_files, color_size, ms_rate)
File "D:\MyDesktop\Python-Projects\pifuhd\lib\render\gl\render.py", line 45, in __init__
_glut_window = glutCreateWindow("My Render.")
File "C:\Users\[USER_NAME]\anaconda3\envs\pifu\lib\site-packages\OpenGL\GLUT\special.py", line 73, in glutCreateWindow
return __glutCreateWindowWithExit(title, _exitfunc)
ctypes.ArgumentError: argument 1: <class 'TypeError'>: wrong type
上記の記事を参考にさせてもらうと、lib/render/gl/render.py
内の以下の箇所を書き換えることで解決するようです。
class Render:
def __init__(self, width=1600, height=1200, name='GL Renderer',
program_files=['simple.fs', 'simple.vs'], color_size=1, ms_rate=1):
self.width = width
self.height = height
self.name = name
self.display_mode = GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH
self.use_inverse_depth = False
global _glut_window
if _glut_window is None:
glutInit()
glutInitDisplayMode(self.display_mode)
glutInitWindowSize(self.width, self.height)
glutInitWindowPosition(0, 0)
# 引数の文字列の指定に`b`を加える
#_glut_window = glutCreateWindow("My Render.")
_glut_window = glutCreateWindow(b"My Render.")
デモを実行して結果を出力する
さて、これで本当にセットアップが完了しました。
あとは、用意されているデモ用のスクリプトを走らせるだけです。
bash ./scripts/demo.sh
これを実行すると以下のように、サンプル写真から出力された動画が表示されます。
ちなみにこのモデルを生成する元になった写真はこちら↓
独自の写真でメッシュを生成する
まず、メッシュを生成するのに使ったShellスクリプトを見てみましょう。
# Copyright (c) Facebook, Inc. and its affiliates. All rights reserved.
python -m apps.simple_test
# python apps/clean_mesh.py -f ./results/pifuhd_final/recon
python -m apps.render_turntable -f ./results/pifuhd_final/recon -ww 512 -hh 512
内容はたったこれだけです。
ひとつコメントアウトされていますが、これは多分、前に生成したメッシュなどをクリアするかどうかでしょう。
最初の処理(apps/simple_test.py
)を見てみるといくつかのパラメータを設定していました。
# Copyright (c) Facebook, Inc. and its affiliates. All rights reserved.
from .recon import reconWrapper
import argparse
###############################################################################################
## Setting
###############################################################################################
parser = argparse.ArgumentParser()
parser.add_argument('-i', '--input_path', type=str, default='./sample_images')
parser.add_argument('-o', '--out_path', type=str, default='./results')
parser.add_argument('-c', '--ckpt_path', type=str, default='./checkpoints/pifuhd.pt')
parser.add_argument('-r', '--resolution', type=int, default=512)
parser.add_argument('--use_rect', action='store_true', help='use rectangle for cropping')
args = parser.parse_args()
###############################################################################################
## Upper PIFu
###############################################################################################
resolution = str(args.resolution)
start_id = -1
end_id = -1
cmd = ['--dataroot', args.input_path, '--results_path', args.out_path,\
'--loadSize', '1024', '--resolution', resolution, '--load_netMR_checkpoint_path', \
args.ckpt_path,\
'--start_id', '%d' % start_id, '--end_id', '%d' % end_id]
reconWrapper(cmd, args.use_rect)
設定項目は入力データの場所、出力データの場所、解像度、などですね。
入力について見てみると./sample_images
フォルダの画像を使うようですね。
ということで、そこにメッシュを生成したい画像を配置して実行してみました。
結果はこちら。
正常に生成できてますね。
(元画像は拾ってきたものなのでここでは載せません)
元々入っているもの以外でも正常に生成できることが確認できました。
Out of Memoryでメッシュが生成されない
数回しか遭遇しなかった問題ですが、いくつかメッシュを生成しようと試していたところ、CUDAのOut of Memoryエラーでメッシュの生成が中断するという問題がありました。
正常なメモリ解放の方法があるのかもしれませんが、いったん、$ conda deactivate
をすることで解消できました。
(一度やってからはそのあとはメモリエラー出ず・・謎)
もし遭遇した場合は試してみてください。
生成に成功した環境
こちらの記事を参考に、PIFuHDの出力に成功したAnacondaの環境を貼っておきます。
Anacondaのインストールリスト
\# This file may be used to create an environment using: \# $ conda create --name --file \# platform: win-64 @EXPLICIT https://repo.anaconda.com/pkgs/main/win-64/blas-1.0-mkl.conda https://conda.anaconda.org/conda-forge/win-64/ca-certificates-2020.6.20-hecda079_0.tar.bz2 https://repo.anaconda.com/pkgs/main/win-64/icc_rt-2019.0.0-h0cc432a_1.conda https://repo.anaconda.com/pkgs/main/win-64/intel-openmp-2020.1-216.conda https://repo.anaconda.com/pkgs/main/win-64/vs2015_runtime-14.16.27012-hf0eaf9b_3.conda https://repo.anaconda.com/pkgs/main/win-64/mkl-2020.1-216.conda https://repo.anaconda.com/pkgs/main/win-64/vc-14.1-h0510ff6_4.conda https://repo.anaconda.com/pkgs/main/win-64/cudatoolkit-10.1.243-h74a9793_0.conda https://repo.anaconda.com/pkgs/main/win-64/icu-58.2-ha925a31_3.conda https://repo.anaconda.com/pkgs/main/win-64/jpeg-9b-hb83a4c4_2.conda https://repo.anaconda.com/pkgs/main/win-64/lz4-c-1.9.2-h62dcd97_1.conda https://conda.anaconda.org/conda-forge/win-64/openssl-1.1.1g-he774522_1.tar.bz2 https://repo.anaconda.com/pkgs/main/win-64/tk-8.6.10-he774522_0.conda https://repo.anaconda.com/pkgs/main/win-64/xz-5.2.5-h62dcd97_0.conda https://repo.anaconda.com/pkgs/main/win-64/yaml-0.2.5-he774522_0.conda https://repo.anaconda.com/pkgs/main/win-64/zlib-1.2.11-h62dcd97_4.conda https://repo.anaconda.com/pkgs/main/win-64/hdf5-1.8.20-hac2f561_1.conda https://repo.anaconda.com/pkgs/main/win-64/libpng-1.6.37-h2a8f88b_0.conda https://repo.anaconda.com/pkgs/main/win-64/sqlite-3.33.0-h2a8f88b_0.conda https://repo.anaconda.com/pkgs/main/win-64/zstd-1.4.5-h04227a9_0.conda https://repo.anaconda.com/pkgs/main/win-64/freetype-2.10.2-hd328e21_0.conda https://repo.anaconda.com/pkgs/main/win-64/libtiff-4.1.0-h56a325e_1.conda https://repo.anaconda.com/pkgs/main/win-64/python-3.7.7-h81c818b_4.conda https://repo.anaconda.com/pkgs/main/win-64/qt-5.9.7-vc14h73c81de_0.conda https://repo.anaconda.com/pkgs/main/noarch/cloudpickle-1.5.0-py_0.conda https://repo.anaconda.com/pkgs/main/noarch/decorator-4.4.2-py_0.conda https://repo.anaconda.com/pkgs/main/win-64/kiwisolver-1.2.0-py37h74a9793_0.conda https://repo.anaconda.com/pkgs/main/win-64/libopencv-3.4.2-h20b85fd_0.conda https://repo.anaconda.com/pkgs/main/win-64/ninja-1.10.0-py37h7ef1ec2_0.conda https://repo.anaconda.com/pkgs/main/win-64/olefile-0.46-py37_0.conda https://conda.anaconda.org/anaconda/win-64/pyopengl-3.1.1a1-py37_0.tar.bz2 https://repo.anaconda.com/pkgs/main/noarch/pyparsing-2.4.7-py_0.conda https://conda.anaconda.org/conda-forge/win-64/python_abi-3.7-1_cp37m.tar.bz2 https://repo.anaconda.com/pkgs/main/win-64/pyyaml-5.3.1-py37he774522_1.conda https://repo.anaconda.com/pkgs/main/win-64/sip-4.19.8-py37h6538335_0.conda https://repo.anaconda.com/pkgs/main/noarch/six-1.15.0-py_0.conda https://repo.anaconda.com/pkgs/main/noarch/toolz-0.10.0-py_0.conda https://repo.anaconda.com/pkgs/main/win-64/tornado-6.0.4-py37he774522_1.conda https://repo.anaconda.com/pkgs/main/noarch/tqdm-4.48.2-py_0.conda https://repo.anaconda.com/pkgs/main/win-64/wincertstore-0.2-py37_0.conda https://conda.anaconda.org/conda-forge/win-64/certifi-2020.6.20-py37hc8dfbb8_0.tar.bz2 https://repo.anaconda.com/pkgs/main/win-64/cycler-0.10.0-py37_0.conda https://repo.anaconda.com/pkgs/main/win-64/cytoolz-0.10.1-py37he774522_0.conda https://repo.anaconda.com/pkgs/main/noarch/dask-core-2.23.0-py_0.conda https://repo.anaconda.com/pkgs/main/win-64/mkl-service-2.3.0-py37hb782905_0.conda https://repo.anaconda.com/pkgs/main/win-64/pillow-7.2.0-py37hcc1f983_0.conda https://repo.anaconda.com/pkgs/main/win-64/pyqt-5.9.2-py37h6538335_2.conda https://repo.anaconda.com/pkgs/main/noarch/python-dateutil-2.8.1-py_0.conda https://repo.anaconda.com/pkgs/main/win-64/numpy-base-1.19.1-py37ha3acd2a_0.conda https://repo.anaconda.com/pkgs/main/win-64/setuptools-49.6.0-py37_0.conda https://repo.anaconda.com/pkgs/main/noarch/networkx-2.4-py_1.conda https://repo.anaconda.com/pkgs/main/win-64/wheel-0.34.2-py37_0.conda https://repo.anaconda.com/pkgs/main/win-64/pip-20.2.2-py37_0.conda https://conda.anaconda.org/conda-forge/noarch/trimesh-3.8.1-pyh9f0ad1d_0.tar.bz2 https://repo.anaconda.com/pkgs/main/noarch/imageio-2.9.0-py_0.conda https://repo.anaconda.com/pkgs/main/win-64/matplotlib-3.3.1-0.conda https://repo.anaconda.com/pkgs/main/win-64/matplotlib-base-3.3.1-py37hba9282a_0.conda https://repo.anaconda.com/pkgs/main/win-64/mkl_fft-1.1.0-py37h45dec08_0.conda https://repo.anaconda.com/pkgs/main/win-64/mkl_random-1.1.1-py37h47e9c7a_0.conda https://repo.anaconda.com/pkgs/main/win-64/numpy-1.19.1-py37h5510c5b_0.conda https://repo.anaconda.com/pkgs/main/win-64/py-opencv-3.4.2-py37hc319ecb_0.conda https://conda.anaconda.org/pytorch/win-64/pytorch-1.6.0-py3.7_cuda101_cudnn7_0.tar.bz2 https://repo.anaconda.com/pkgs/main/win-64/pywavelets-1.1.1-py37he774522_0.conda https://repo.anaconda.com/pkgs/main/win-64/scipy-1.5.0-py37h9439919_0.conda https://repo.anaconda.com/pkgs/main/win-64/opencv-3.4.2-py37h40b0b35_0.conda https://repo.anaconda.com/pkgs/main/win-64/scikit-image-0.16.2-py37h47e9c7a_0.conda https://conda.anaconda.org/pytorch/win-64/torchvision-0.7.0-py37_cu101.tar.bz2 ```上記は以下のコマンドで書き出したものです。
$ conda list --explicit > env_name.txt
上記リストをコピペして、以下のコマンドで環境が構築できます。
$ conda create -n [env_name] --file env_name.txt
最後に
1枚の写真からこれだけのメッシュが生成されるのは驚きですね。
しかも複数枚の写真から生成させるとさらに精度が高くなるようです。
(しかも動画からも生成できるみたい)
近い将来、今までは写真でシェアしていたものをこうした3Dモデルの形でシェアする時代が来るのでしょうね。
AR時代においては立体的にデータがシェアされるのは間違いないでしょうから、今からそういう時代が来るのが楽しみです。