keras-deeplab-v3-plusで人だけとってみる(ソース有り)
この投稿は自分のブログの転載です。
keras-deeplab-v3-plusで人だけとってみる - 機械音痴な情報系
Semantic Segmentationで人をとってきたいのでkeras-deeplab-v3-plusを使ってみました。
勿論本来は人以外も色々なものをとってこれます。
keras-deeplab-v3-plus - Github
準備
# 仮想環境の準備
$ 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を使って画像を出力
ここからは自分用にカスタマイズしていく。
多クラス分類だが、人だけとれれば良い。
import model
import cv2
img = cv2.imread('./test.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」でぐぐる。
一番上にぽいのが出てくる。
pascal-voc-classes.txt(NVIDIA/DIGITS) - Gtihub
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」でぐぐると以下のサイトが見つかる。
mobilenet_v2.py(keras-team/keras) - Github
「preprocess_input」というのがあるのでそれを使ってみよう。
import cv2
import numpy as np
import model
from keras.applications.mobilenetv2 import preprocess_input
img = preprocess_input(cv2.imread('./test.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('./test.jpg').astype("float"))
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
img = cv2.resize(img, (512, 512))
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("./person_musk.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の方が良さげではある。
Author And Source
この問題について(keras-deeplab-v3-plusで人だけとってみる(ソース有り)), 我々は、より多くの情報をここで見つけました https://qiita.com/saneatsu/items/e517ba5b14be9c1030df著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .