keras-deeplab-v3-plusで人だけとってみる
Semantic Segmentationで人をとってきたいのでこのアーキテクチャを使って人と背景を分ける。
準備
# 仮想環境の準備 $ conda create -n keras-deeplab-v3-plus $ source activate keras-deeplab-v3-plus # モジュールインストール $ conda install tqdm $ conda install numpy $ conda install keras # 重みダウンロード $ python extract_weights.py $ python load_weights.py
Jupyterを使って画像を出力
ここからは自分用にカスタマイズしていく。 多クラス分類だが、人だけとれれば良い。
デフォルトで入っているimage1.jpgを使う。
import model import cv2 img = cv2.imread('./imgs/image1.jpg') img = cv2.resize(img, (512, 512)) # imgは0〜255の値をとる model_dlv3 = model.Deeplabv3() predicted = model_dlv3.predict(img[np.newaxis, ...]) print(predicted.shape) # (1, 512, 512, 21)
21クラス分類だが、どれが人なのか。
閾値がどうなっているのか知りたい。
が、プログラム内に無さげ。
「semantic segmentation 21 class names」でぐぐる。
一番上にぽいのが出てくる。 github.com 0が背景で、15が人と仮定する。
★追記
というかmodels.py
にdef Deeplabv3(weights='pascal_voc', ...
という行もあるのでこれで合っていると思われる。
person_score = predicted[0, :, : ,15] back_score = predicted[0, :, :, 0] mask = (person_score > back_score).astype("uint8") * 255 cv2.imwrite("test.jpg", mask)
出力してみると真っ黒。
考えられる原因
- OpenCVはBGRだがこれはRGBを使っている
- 0〜255ではなく-1〜1などで処理している
★追記
入力画像の大きさが小さすぎた&人が横になっていたのが原因でした(横になっていた際の出力例、RGBに変換した画像は下の方にあります)
入力の際の前処理
ところで、これはモデルとしてMobileNetv2を使用していた。
画像の前処理はどうやってるんだろう?
Kerasがmobilenetv2を提供していて、ResNetなどもpreprocess_input的な関数は提供している(らしい)。
ということで調べてみる。
こういう当たりが付けられるの強い。
といってもここらへん全部友人がやってくれた。圧倒的人任せ。
「mobilenetv2 preprocess keras」でぐぐると以下のサイトが見つかる。 github.com
preprocess_input
というのがあるのでそれを使ってみよう。
import cv2 import numpy as np import model from keras.applications.mobilenetv2 import preprocess_input img = preprocess_input(cv2.imread('./imgs/image1.jpg')) ## ここでエラー img = cv2.resize(img, (512, 512))
エラー発生
TypeError: ufunc 'true_divide' output (typecode 'd') could not be coerced to provided output parameter (typecode 'B') according to the casting rule ''same_kind''
最終的にはこんな感じに。
import cv2 import numpy as np import model from keras.applications.mobilenetv2 import preprocess_input img = preprocess_input(cv2.imread('./imgs/test.jpg').astype("float")) img = cv2.resize(img, (512, 512)) img.max() # 0.9921875 model_dlv3 = model.Deeplabv3() predicted = model_dlv3.predict(img[np.newaxis, ...]) person_score = predicted[0, :, : ,15] back_score = predicted[0, :, :, 0] mask = (person_score > back_score).astype("uint8") * 255 cv2.imwrite("test.jpg", mask)
出力結果
背景はデフォルトで黒、あとは人だけ取り出してみた。 上手いこととれた!
因みにこの人を横にすると人だと認識しない。
BGR→RGBにしてみる
OpenCVではデフォルトでBGRで扱うが、もしこのアーキテクチャではRGBで扱っていて、更に人を肌の色などで認識している場合、精度が異なってくる。
ってことで試す。
と言っても1行追加するだけだけど。
img = preprocess_input(cv2.imread('./imgs/R0_L0_ono_001360.jpg').astype("float")) img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) # 追加行 img = cv2.resize(img, (512, 512))
元画像を載せていないのでよくわからないと思うが、本来白色になってほしいところ(スカートの白色の部分)が白色にきちんとなっているしRGBの方が良さげではある。
シェルでは使えているPythonモジュールをJupyterNotebookで実行すると「ImportError: No module named module_name」が出てくる
問題点
はじめてPytorchを使った際に以下のようなエラーが。
ImportError: No module named torch
pip installする
$ pip install torch Requirement already satisfied: torch in /home/ubuntu/miniconda3/lib/python3.6/site-packages (0.4.1)
既にインストールされてる。
シェルでも問題なく使える
$ python Python 3.6.5 |Anaconda, Inc.| (default, Apr 29 2018, 16:14:56) [GCC 7.2.0] on linux Type "help", "copyright", "credits" or "license" for more information. >>> import torch >>>
はて…?
現状
現在はvenvで作った環境にいる。
$ conda create -n pytorch-segmentation-detection $ source activate pytorch-segmentation-detection (pytorch-segmentation-detection) ubuntu@ip-172-31-5-82:~/Code/pytorch-segmentation-detection$
が、Jupyter上で見るとこの「pytorch-segmentation-detection」というカーネルが存在しない。
解決策
そこで、ipykernelをインストールする。
$ conda install ipykernel $ ipython kernel install --user --name pytorch-segmentation-detection --display-name pytorch-segmentation-detection
出てきた!
参考
実行したファイルの残り時間をターミナルに表示する
機械学習のプログラムを書き始めると、大きいファイルを扱う機会が増えた。 そこでターミナルに残り時間を表示させたいと思ったので、 h5ファイルを作成する関数を例にしてメモっておく。
def create_h5(h5_fpath, image_fpaths, better_model, num): start_time = datetime.now() # 現在時刻取得 print('============================') print("Start: " + str(start_time)) print("Num : " + str(num)) # 読み込む画像の枚数 with h5py.File(h5_fpath, "w") as f: for i, image_fpath in enumerate(image_fpaths): # ここでファイルを読み込んでh5ファイルを作成する処理を行っていることとする # 100枚毎に残り時間を表示させる if i % 100 == 0 and i != 0: elapsed_time = datetime.now() - start_time # 経過時間 ave_time = elapsed_time/i # 現在における1つあたりの平均処理時間を算出 remain_time = (ave_time*num) - elapsed_time # 「平均*画像枚数」で全体的なかかる時間を計算し、経過時間を引く print(str(i)+": "+str(remain_time)+" left")
実際の出力はこんな感じ。
4200: 0:00:57.961352 left 4300: 0:00:50.587814 left 4400: 0:00:43.323896 left 4500: 0:00:35.996341 left 4600: 0:00:28.692517 left 4700: 0:00:21.979801 left 4800: 0:00:14.650676 left 4900: 0:00:07.381439 left
JupyterNotebookでファイルがリロードされない
リロードさせる方法
1. importlib.reload
import load_weights import model importlib.reload(load_weights) importlib.reload(model)
2. autoreload 2
以下をJupyterNotebookに貼り付ける。
% load_ext autoreload # 外部のモジュールautoreloadをロード % autoreload 2 # 実行する度にインポートしたモジュールをリロードする。
参考
Kerasで「AttributeError: 'NoneType' object has no attribute HOGEHOGE」
エラー
Kerasで重みを読み込む時に以下のエラー。
model_50 = model_50.load_weights('/host/weights/weights.013-7.248.hdf5') # AttributeError: 'NoneType' object has no attribute 'load_weights'
NoneType。。。
print(type(model_50)) # <class 'NoneType'>
解決策
代入はしなくて以下のようにするだけでmodel_50には代入される。
model_50.load_weights('/host/weights/weights.013-7.248.hdf5')
うん。大丈夫。
print(type(model_50)) # <class 'keras.engine.training.Model'>
Kerasで「ImportError: Could not import PIL.Image. The use of `array_to_img` requires PIL.」とPILのエラーが出る
エラー
ローカルではこのエラー見たことなかったんだけど、サーバ側で実行したらPILに関するエラーが。 Kerasで以下のようにimportしてるのにだめなのか…。
from keras.preprocessing.image import ( ImageDataGenerator, load_img, img_to_array, array_to_img )
解決策
condaでインストール。
$ conda install Pillow
もう一度実行したら… なんで!!OpenCVインストールしてなかったっけなぁ…。
ImportError: numpy.core.multiarray failed to import Traceback (most recent call last): File "datagen.py", line 4, in <module> import cv2 ImportError: numpy.core.multiarray failed to import
以下コマンドでインストール。
$ conda install -c conda-forge opencv
おしまい。
参考
AWSインスタンスをもらった時にやったこと
AWSインスタンスを割り当てられて、諸々の設定はやってあるので、それ以降自分用にやったことをメモっておく。
miniconda
Miniconda — Conda 上のサイトからインストール。
$ wget https://repo.continuum.io/miniconda/Miniconda3-latest-Linux-x86_64.sh
byobu
$ sudo apt-get install byobu
zsh
$ sudo apt-get install zsh $ /bin/zsh --version $ which zsh $ sudo vi /etc/shells # List of acceptable shells for chpass(1). # Ftpd will not allow users to connect who are not using # one of these shells. /bin/bash /bin/csh /bin/ksh /bin/sh /bin/tcsh /bin/zsh /usr/local/bin/zsh # この行を追加 # chshコマンドを利用してログインシェルを変更 $ chsh -s /usr/local/bin/zsh # whichの出力
以下参考。 saneeeatsu.hatenablog.com
公開鍵をGithub/Gitlabに登録
$ ssh-keygen $ cat .ssh/id_rsa.pub
コピーする際に使うMacのpbcopy
は、Ubuntuではxsel
に当たる。
以下参考。
saneeeatsu.hatenablog.com
マウント
$ ssh username@hogehoge.dip.jp -p 10022 $ exit $ mkdir ~/mount_host $ sudo apt-get install sshfs $ sshfs username@hogehoge.dip.jp:/host ~/spacely_host -o IdentityFile=/home/ubuntu/.ssh/id_rsa -p 10022 fuse: bad mount point `/home/ubuntu/spacely_host': Transport endpoint is not connected # エラー解決 $ fusermount -u ~/mount_host
参考 - Transport endpoint is not connected - Stackoverflow - sshfs - transport endpoint is not connected - Stackexchange