顔だけ認識したいという場合に顔の学習済みモデルが有れば
それを使用すれば済むんですが、いろいろ探したけど
見つからないか見つかったけどchainerで使える拡張子npzに
変換する時にエラーになったりして色々駄目だったので
試行錯誤しつつなんとか出来たのでその時の記録。
参考ページ
https://qiita.com/nakamura21/items/2b2ff6524710d167d618
いつもすいません。
■Ubuntuのインストール
Ubuntu18.4.2Lをまっさらな状態でインストール
& インストール中に最新化するか聞かれるので最新化する。
マシンのスペック
Intel(R) Core(TM) i5-4570 CPU @ 3.20GHz
メモリ16Gバイト
GeForce GT 1030
■ドライバーのインストール
sudo ubuntu-drivers autoinstall
sudo reboot
なんかグラボを付けている状態で
sudo ubuntu-drivers autoinstall ってすると
自動でドライバーが入るそうで。なんかすげー
っていうかWindowsではこれ常識か。
■グラボ認識しているか表示
nvidia-smi
■CUDAのインストール
sudo apt install nvidia-cuda-toolkit nvidia-driver-390
sudo reboot
■cuDNNのダウンロードとインストール
NVIDIAさんのページから持ってくる。
アカウント作ってログインする必要がある。
https://developer.nvidia.com/rdp/cudnn-archive
参考ページではcuDNN v7.1.2 (Mar 21, 2018), for CUDA 9.1 & 9.2ってなっているけど
mac用しかない。
適当に入れるといつものように悪い事が起きそうなので
nvcc -Vでcudaのバージョンを調べる
nvcc -V
nvcc: NVIDIA (R) Cuda compiler driver
Copyright (c) 2005-2017 NVIDIA Corporation
Built on Fri_Nov__3_21:07:56_CDT_2017
Cuda compilation tools, release 9.1, V9.1.85
※ 9.1な模様
9.1対応のを探して
Download cuDNN v7.1.3 (April 17, 2018), for CUDA 9.1
の
cuDNN v7.1.3 Library for Linux
をダウンロード
本当はUbuntu18.4用のを探したんだけどCuda9.1のはコレだったので。
あとでdarknetコンパイルするときにMakefileを変更する必要がある。
□展開
tar xzvf cudnn-9.1-linux-x64-v7.1.tgz
展開後のファイルの構成
cuda
├── NVIDIA_SLA_cuDNN_Support.txt
├── include
│ └── cudnn.h
└── lib64
├── libcudnn.so -> libcudnn.so.7
├── libcudnn.so.7 -> libcudnn.so.7.1.3
├── libcudnn.so.7.1.3
└── libcudnn_static.a
□インストール
sudo cp -a cuda/include/* /usr/lib/cuda/include/
sudo cp -a cuda/lib64/* /usr/lib/cuda/lib64/
vi ~/.bashrc
以下を追加
## CUDA and cuDNN paths
export PATH=/usr/lib/cuda/bin:${PATH}
export LD_LIBRARY_PATH=/usr/lib/cuda/lib64:${LD_LIBRARY_PATH}
□後片付け
sudo apt autoremove
sudo apt clean
□.bashrcを変更したのでterminalに反映
ここで今までっ使っていたterminalを閉じて
新しいterminalを起動
■DARKNETの入手とインストール
□gitをインストール
sudo apt install git
□DARKNETをインストール
git clone https://github.com/AlexeyAB/darknet.git
cd darknet
■DARKNETのコンパイル
vi Makefile
以下の箇所を修正
GPU=1
CUDNN=1
make
→エラーになる
□Makefileをubuntuに合わせて変更
COMMON+= -DGPU -I/usr/local/cuda/include/
↓
COMMON+= -DGPU -I/usr/lib/cuda/include
LDFLAGS+= -L/usr/local/cuda/lib64 -lcuda -lcudart -lcublas -lcurand
↓
LDFLAGS+= -L/usr/lib/cuda/lib64 -lcuda -lcudart -lcublas -lcurand
CFLAGS+= -DCUDNN -I/usr/local/cudnn/include
↓
CFLAGS+= -DCUDNN -I/usr/lib/cuda/include
LDFLAGS+= -L/usr/local/cudnn/lib64 -lcudnn
↓
LDFLAGS+= -L/usr/lib/cuda/lib64 -lcudnn
make
今度はうまく行ったっぽい。
□DARKNETの起動を確認
./darknet
usage: ./darknet <function>
よしよし。
ここまでOKか
■学習用のデータセットの準備
ここで再度先日の参考ページ登場
https://qiita.com/ha9kberry/items/1bc113cfcd9892a9ddbd
ほんと助かっています。
前回は01のデータセット準備までは出来ているはずなので。
と思ったんだけど。
圧縮ファイルがぶっ壊れてた。涙;;
→やり直す。やり直し部分も含めて以下へ記載しています。
■顔の学習の元になる顔の写真と顔の座標のファイルを整備
学習させるには顔の写真と、その写真の中の何処が顔なのかを入力する必要があり。
その元になるファイルはいろんなサイトで公開してもらっているようなので
これを使用する。
□顔の学習のもとになる顔の写真と顔の座標のファイルをダウンロード
http://mmlab.ie.cuhk.edu.hk/projects/WIDERFace/
WIDER Face Training Images
と
Face annotations
をダウンロードして解凍する
こんな感じで展開されます
.
├── WIDER_train
│ └── images
│ ├── 0--Parade
│ │ ├── 0_Parade_Parade_0_1014.jpg
│ │ ├── 0_Parade_Parade_0_1019.jpg
│ │ ├── 0_Parade_Parade_0_1040.jpg
│ │ ├── 0_Parade_Parade_0_1041.jpg
省略
│ ├── 1--Handshaking
│ │ ├── 1_Handshaking_Handshaking_1_102.jpg
│ │ ├── 1_Handshaking_Handshaking_1_105.jpg
│ │ ├── 1_Handshaking_Handshaking_1_113.jpg
省略
│ ├── 9_Press_Conference_Press_Conference_9_944.jpg
│ ├── 9_Press_Conference_Press_Conference_9_946.jpg
│ └── 9_Press_Conference_Press_Conference_9_97.jpg
├── wider_face_split
├── readme.txt
├── wider_face_test.mat
├── wider_face_test_filelist.txt
├── wider_face_train.mat
├── wider_face_train_bbx_gt.txt
├── wider_face_val.mat
└── wider_face_val_bbx_gt.txt
中を見ると集合写真とかのjpgが沢山と
wider_face_train_bbx_gt.txtが顔の座標が入っている模様。
□Annotationファイル作成の環境整備
参考ページの人はJupyter Notebookを使用しているようなんですが
自分は違うので自分で環境整備します。
sudo apt install python3
sudo apt install python3-pip
pip3 install opencv-python
□Annotationファイルを作成する前にファイルを整理する
vi generator.py
以下の内容で作成
import os
import cv2
import math
import random
txt_file = 'wider_face_split/wider_face_train_bbx_gt.txt'
with open(txt_file) as f:
num = f.read().count('jpg')
print('number of images:',num)
そのまま実行すると
python3 generator.py
number of images: 12880
となるんです。参考ページの結果は5451。
参考ページによるとなんでかはわかりませんけど
「予め0--Parade?20--Family_Groupのみ抽出」となっていますんで
wider_face_train_bbx_gt.txtを開いて
0--Parade?20--Family_Groupだけ残す。
ちなみに、このファイルの番号が曲者で
普通に20--Family_Groupの後ろを削除すればOKと思うじゃないですか?
しかーし、よく見ると
20--Family_Groupのあとには21--Festival/21_Festival_Festival_21_14.jpgが有って
その後ろは22→23→・・・・と続きますが
29の次が3--Riot/3_Riot_Riot_3_189.jpgになるので注意です。
それと、もう一つ。
Ubuntuに最初から入っていたテキストエディターなんですが、
これでやると、セーブしたときにファイルが崩れます。
適当に他の行とくっついて以下のような行が発生して後ろの工程でエラーになりますので注意です。
「264--Dancing/4_Dancing_Dancing_4_71.jpg」
もう一回実行
python3 generator.py
number of images: 5451
参考ページと同じでok
□解説 Annotationファイルの構成
0_Parade_marchingband_1_45.txt
0 0.68017578125 0.9162995594713657 0.0400390625 0.07342143906020558
0 0.02978515625 0.8127753303964758 0.0185546875 0.027900146842878122
- 各バウンディングボックスごとにクラス x座標 y座標 ボックス幅 ボックス高さ
- 座標はバウンディングボックスの中心座標
- 座標、幅・高さともに、画像の幅・高さに対する相対値
- Annotationファイルは、画像ファイルと同じディレクトリ内に保存
上記の形式になるように変換する。
その為のプログラムは参考ページを参考に作成する。
□変換プログラム
vi generator2.py
以下の内容で作成
import cv2
def generator():
num = 5451
with open("wider_face_train_bbx_gt.txt") as f:
img_paths=[]
for i in range(num):
# 両端の空白や改行を除去して1行ずつ読み込む
img_path=f.readline().strip()
# 画像パス一覧取得
img_paths.append(img_path)
# 画像を読み込み幅・高さ取得
im = cv2.imread(img_path)
im_h, im_w, im_c = im.shape
# '/'で分割
split=img_path.split('/')
# Annotationファイルを格納するディレクトリ取得
dir_name=split[0]
# Annotationファイル名作成
file_name=split[1].replace('.jpg', '.txt')
# ボックス数取得
count = int(f.readline())
readline=[]
readlines=[]
for j in range(count):
readline=f.readline().split()
# ボックスの左上座標を取得
xmin=int(readline[0])
ymin=int(readline[1])
# ボックスの幅・高さを取得
w=int(readline[2])
h=int(readline[3])
# ボックスの中央座標(相対値)を作成
xcenter=str((xmin+w/2)/im_w)
ycenter=str((ymin+h/2)/im_h)
# ボックスの幅・高さを相対値に変換
w=str(w/im_w)
h=str(h/im_h)
class_num='0'
# クラス x座標 y座標 ボックス幅 ボックス高さを半角スペースで結合
string=' '.join([class_num, xcenter, ycenter, w, h])
readlines.append(string)
# 改行で結合
readlines_str='¥n'.join(readlines)
# 該当するディレクトリ内にAnnotationファイルを保存
with open(dir_name+'/'+file_name, 'w') as j:
j.write(readlines_str)
# 画像パス一覧を出力
return img_paths
img_paths = generator()
これを動かすのにディレクトリ構成を以下のように変更
.
├── 0--Parade
│ ├── 0_Parade_Parade_0_1014.jpg
│ ├── 0_Parade_Parade_0_1019.jpg
│ ├── 0_Parade_Parade_0_1040.jpg
省略
├── 1--Handshaking
│ ├── 1_Handshaking_Handshaking_1_102.jpg
│ ├── 1_Handshaking_Handshaking_1_105.jpg
│ ├── 1_Handshaking_Handshaking_1_113.jpg
省略
│ ├── 9_Press_Conference_Press_Conference_9_946.jpg
│ └── 9_Press_Conference_Press_Conference_9_97.jpg
├── generator2.py
└── wider_face_train_bbx_gt.txt
そこで
python3 generator2.py を実行。
実行すると、jpgファイルと同じディレクトリにjpg部分をtxtにしたファイルが作成される
.
├── 0--Parade
│ ├── 0_Parade_Parade_0_1014.jpg
│ ├── 0_Parade_Parade_0_1014.txt
│ ├── 0_Parade_Parade_0_1019.jpg
│ ├── 0_Parade_Parade_0_1019.txt
│ ├── 0_Parade_Parade_0_1040.jpg
│ ├── 0_Parade_Parade_0_1040.txt
省略
├── 1--Handshaking
│ ├── 1_Handshaking_Handshaking_1_102.jpg
│ ├── 1_Handshaking_Handshaking_1_102.txt
│ ├── 1_Handshaking_Handshaking_1_105.jpg
│ ├── 1_Handshaking_Handshaking_1_105.txt
│ ├── 1_Handshaking_Handshaking_1_113.jpg
│ ├── 1_Handshaking_Handshaking_1_113.txt
省略
│ ├── 9_Press_Conference_Press_Conference_9_946.jpg
│ ├── 9_Press_Conference_Press_Conference_9_946.txt
│ ├── 9_Press_Conference_Press_Conference_9_97.jpg
│ └── 9_Press_Conference_Press_Conference_9_97.txt
├── generator2.py
└── wider_face_train_bbx_gt.txt
□trainデータ、testデータそれぞれで使う画像のパス一覧テキストファイルを作成
プログラムを見るとfaceというディレクトリの中のファイル一覧を取ってくるようになっているようなのと、
0--Parade?20--Family_Group以外が有るとうまく行かないようなんで
以下の構成に変更
21--Festival以降のフォルダーは削除
.
├── face
│ ├── 0--Parade
│ │ ├── 0_Parade_Parade_0_1014.jpg
│ │ ├── 0_Parade_Parade_0_1014.txt
│ │ ├── 0_Parade_Parade_0_1019.jpg
│ │ ├── 0_Parade_Parade_0_1019.txt
省略
│ ├── 1--Handshaking
│ │ ├── 1_Handshaking_Handshaking_1_102.jpg
│ │ ├── 1_Handshaking_Handshaking_1_102.txt
│ │ ├── 1_Handshaking_Handshaking_1_105.jpg
│ │ ├── 1_Handshaking_Handshaking_1_105.txt
省略
│ ├── 9_Press_Conference_Press_Conference_9_97.jpg
│ └── 9_Press_Conference_Press_Conference_9_97.txt
├── generator3.py
└── wider_face_split
└── wider_face_train_bbx_gt.txt
・trainingとtestに分けるプログラム
vi generate3.py
以下の内容で作成
import math
import glob
num = 5451
# testデータの比率
test_size=0.1
test_num=math.floor(num*test_size)
train_num=num-test_num
print('number of train images:', train_num)
print('number of test images:', test_num)
# 画像データを格納しているディレクトリ
img_paths=glob.glob("face/*/*.jpg")
# trainファイル作成
train_list=img_paths[:train_num]
train_str='¥n'.join(train_list)
with open('train.txt', 'w') as f:
f.write(train_str)
# testファイル作成
test_list=img_paths[train_num:]
test_str='¥n'.join(test_list)
with open('test.txt', 'w') as f:
f.write(test_str)
・実行
python generator3.py
以下の様にtest.txtファイルとtrain.txtファイルができる
test.txt
内容は以下の通り
face/2--Demonstration/2_Demonstration_Demonstration_Or_Protest_2_485.jpg
face/2--Demonstration/2_Demonstration_Political_Rally_2_190.jpg
face/2--Demonstration/2_Demonstration_Protesters_2_14.jpg
face/2--Demonstration/2_Demonstration_Political_Rally_2_469.jpg
省略
train.txt
内容は以下の通り
face/16--Award_Ceremony/16_Award_Ceremony_Awards_Ceremony_16_325.jpg
face/16--Award_Ceremony/16_Award_Ceremony_Awards_Ceremony_16_82.jpg
face/16--Award_Ceremony/16_Award_Ceremony_Awards_Ceremony_16_538.jpg
face/16--Award_Ceremony/16_Award_Ceremony_Awards_Ceremony_16_41.jpg
省略
・結果的に以下のディレクトリ構成になる
.
├── face
│ ├── 0--Parade
│ ├── 0--Parade
│ │ ├── 0_Parade_Parade_0_1014.jpg
│ │ ├── 0_Parade_Parade_0_1014.txt
│ │ ├── 0_Parade_Parade_0_1019.jpg
│ │ ├── 0_Parade_Parade_0_1019.txt
省略
│ │ ├── 9_Press_Conference_Press_Conference_9_946.jpg
│ │ ├── 9_Press_Conference_Press_Conference_9_946.txt
│ │ ├── 9_Press_Conference_Press_Conference_9_97.jpg
│ │ └── 9_Press_Conference_Press_Conference_9_97.txt
省略
├── generator3.py
├── test.txt
├── train.txt
└── wider_face_split
└── wider_face_train_bbx_gt.txt
■02.Darknetで学習を実施。
参考ページ
https://qiita.com/ha9kberry/items/e7c822dd0874e5a24639
ほんといつも助かっています。
ここまでの操作でダークネットのインストールとコンパイルで成功しているので
その続きから行う。
□weightをダウンロード
wget https://pjreddie.com/media/files/darknet53.conv.74
□設定ファイル作成
vi cfg/obj.data
以下の内容で作成
classes = 1
train = face/train.txt
valid = face/test.txt
names = cfg/obj.names
backup = backup/
vi cfg/obj.name
以下の内容で作成
face
□設定ファイルの編集
yolov3.cfg編集
vi cfg/yolov3.cfg
Line 3:コメントアウト
Line 4:コメントアウト
Line 6:batch=24に設定
Line 7:subdivisions=8に設定
※変更箇所は「→」の所
1 [net]
2 # Testing
→ 3 #batch=1
→ 4 #subdivisions=1
5 # Training
→ 6 batch=24
→ 7 subdivisions=8
8 width=416
9 height=416
10 channels=3
11 momentum=0.9
filters=(classes+5)*3
Line 603:filters=18に設定
Line 610:classes=1に設定
Line 689:filters=18に設定
Line 696:classes=1に設定
Line 776:filters=18に設定
Line 783:classes=1に設定
599 [convolutional]
600 size=1
601 stride=1
602 pad=1
→ 603 filters=18
604 activation=linear
605
606
607 [yolo]
608 mask = 6,7,8
609 anchors = 10,13, 16,30, 33,23, 30,61, 62,45, 59,119, 116,90, 156,198, 373,326
→ 610 classes=1
611 num=9
612 jitter=.3
613 ignore_thresh = .7
614 truth_thresh = 1
615 random=1
685 [convolutional]
686 size=1
687 stride=1
688 pad=1
→ 689 filters=18
690 activation=linear
691
692
693 [yolo]
694 mask = 3,4,5
695 anchors = 10,13, 16,30, 33,23, 30,61, 62,45, 59,119, 116,90, 156,198, 373,326
→ 696 classes=1
697 num=9
698 jitter=.3
699 ignore_thresh = .7
700 truth_thresh = 1
701 random=1
772 [convolutional]
773 size=1
774 stride=1
775 pad=1
→ 776 filters=18
777 activation=linear
780 [yolo]
781 mask = 0,1,2
782 anchors = 10,13, 16,30, 33,23, 30,61, 62,45, 59,119, 116,90, 156,198, 373,326
→ 783 classes=1
□darknetディレクトリの構成
darknet/
├ backup/
├ cfg/
│ ├ yolov3.cfg
│ ├ obj.data
│ ├ obj.name
省略
├ face/
│ ├ test.txt
│ ├ train.txt
│ ├0--Parade
│ ├2--Demonstration
省略
├ darknet
├ Makefile
├ darknet53.conv.74
省略
■学習実行
./darknet detector train cfg/obj.data cfg/yolov3.cfg darknet53.conv.74
エラーになる。
yolov3
layer filters size input output
0 conv 32 3 x 3 / 1 416 x 416 x 3 -> 416 x 416 x 32 0.299 BF
1 conv 64 3 x 3 / 2 416 x 416 x 32 -> 208 x 208 x 64 1.595 BF
省略
35 conv 256 3 x 3 / 1 52 x 52 x 128 -> 52 x 52 x 256 1.595 BF
36 Shortcut Layer: 33
37 Try to set subdivisions=64 in your cfg-file.
CUDA status Error: file: ./src/cuda.c : () : line: 213 : build time: Mar 9 2019 - 09:54:27
CUDA Error: out of memory
CUDA Error: out of memory: File exists
darknet: ./src/utils.c:281: error: Assertion `0' failed.
中止 (コアダンプ)
メモリが足りないってよ。
GT1030の搭載メモリは2Gバイト
ここで試行錯誤。
6 batch=24
7 subdivisions=8
の数字をいろいろイジっても駄目で。
google先生に聞いてみた。
先人の声
「私はあなたのGPUのメモリが不足していると思います。
Yolov3が完全にGPUにロードされたとき、
それは私のコンピュータ上でデフォルト設定(416 * 416)と
プラス表示および他のアプリケーションから
300ish MiBで約1600MBのメモリを必要とします。
より大きなメモリを搭載したGPUで実行するか、
cfgファイルの幅と高さの設定を減らしてみてください
(サイズを小さくすると、検出結果に影響が出る可能性があります)。」
と仰っております。
画面フレーム?のサイズを減らすと検出結果に影響が出るよ。
と言っておられますがGT1030しか持っていないのでしょうがないよねー
「ふん。働いてお金を沢山貯めてもっと良いのを買うんだ!!」
しかし画面フレーム?のサイズを減らせばGPUのメモリ消費が少ないとの事なので
半分ぐらいにして再度実行
→まだエラーになる。
では元の数字の4分の1ぐらいで実行。なんかうまく行くっぽい。
追加の変更は以下の通り。
vi cfg/yolov3.cfg
Line 8:width=128に設定
Line 9:height=128に設定
1 [net]
2 # Testing
3 # batch=1 ←コメントにした
4 # subdivisions=1 ←コメントにした
5 # Training
6 batch=24 ←コメントを外して24にした
7 subdivisions=8 ←コメントを外して8にした
8 width=128 ←128にした
9 height=128 ←128にした
10 channels=3
11 momentum=0.9
後ろの方のfiltersとclassesはそのまま同じ
Line 603:filters=18に設定
Line 610:classes=1に設定
Line 689:filters=18に設定
Line 696:classes=1に設定
Line 776:filters=18に設定
Line 783:classes=1に設定
□学習の様子
136: 103.537476, 132.362717 avg loss, 0.000000 rate, 1.965623 seconds, 3264 images
Loaded: 0.000034 seconds
Region 82 Avg IOU: -nan, Class: -nan, Obj: -nan, No Obj: 0.510125, .5R: -nan, .75R: -nan, count: 0
Region 94 Avg IOU: -nan, Class: -nan, Obj: -nan, No Obj: 0.442774, .5R: -nan, .75R: -nan, count: 0
Region 106 Avg IOU: 0.137911, Class: 0.430334, Obj: 0.358204, No Obj: 0.337541, .5R: 0.031250, .75R: 0.000000, count: 32
Region 82 Avg IOU: -nan, Class: -nan, Obj: -nan, No Obj: 0.511793, .5R: -nan, .75R: -nan, count: 0
Region 94 Avg IOU: -nan, Class: -nan, Obj: -nan, No Obj: 0.444947, .5R: -nan, .75R: -nan, count: 0
Region 106 Avg IOU: 0.050849, Class: 0.419898, Obj: 0.387084, No Obj: 0.337189, .5R: 0.000000, .75R: 0.000000, count: 69
Region 82 Avg IOU: -nan, Class: -nan, Obj: -nan, No Obj: 0.507179, .5R: -nan, .75R: -nan, count: 0
Region 94 Avg IOU: -nan, Class: -nan, Obj: -nan, No Obj: 0.442994, .5R: -nan, .75R: -nan, count: 0
Region 106 Avg IOU: 0.038144, Class: 0.419298, Obj: 0.349665, No Obj: 0.337408, .5R: 0.000000, .75R: 0.000000, count: 64
Region 82 Avg IOU: -nan, Class: -nan, Obj: -nan, No Obj: 0.508707, .5R: -nan, .75R: -nan, count: 0
Region 94 Avg IOU: -nan, Class: -nan, Obj: -nan, No Obj: 0.442302, .5R: -nan, .75R: -nan, count: 0
Region 106 Avg IOU: 0.320144, Class: 0.395719, Obj: 0.325046, No Obj: 0.337644, .5R: 0.250000, .75R: 0.250000, count: 4
Region 82 Avg IOU: -nan, Class: -nan, Obj: -nan, No Obj: 0.513188, .5R: -nan, .75R: -nan, count: 0
Region 94 Avg IOU: -nan, Class: -nan, Obj: -nan, No Obj: 0.444114, .5R: -nan, .75R: -nan, count: 0
Region 106 Avg IOU: 0.062433, Class: 0.457910, Obj: 0.391780, No Obj: 0.337275, .5R: 0.000000, .75R: 0.000000, count: 44
Region 82 Avg IOU: -nan, Class: -nan, Obj: -nan, No Obj: 0.507034, .5R: -nan, .75R: -nan, count: 0
Region 94 Avg IOU: -nan, Class: -nan, Obj: -nan, No Obj: 0.443162, .5R: -nan, .75R: -nan, count: 0
Region 106 Avg IOU: 0.150425, Class: 0.570029, Obj: 0.337372, No Obj: 0.337979, .5R: 0.000000, .75R: 0.000000, count: 7
Region 82 Avg IOU: -nan, Class: -nan, Obj: -nan, No Obj: 0.512920, .5R: -nan, .75R: -nan, count: 0
Region 94 Avg IOU: -nan, Class: -nan, Obj: -nan, No Obj: 0.443773, .5R: -nan, .75R: -nan, count: 0
Region 106 Avg IOU: 0.057833, Class: 0.500358, Obj: 0.431524, No Obj: 0.336149, .5R: 0.000000, .75R: 0.000000, count: 57
Region 82 Avg IOU: -nan, Class: -nan, Obj: -nan, No Obj: 0.512746, .5R: -nan, .75R: -nan, count: 0
Region 94 Avg IOU: -nan, Class: -nan, Obj: -nan, No Obj: 0.444053, .5R: -nan, .75R: -nan, count: 0
Region 106 Avg IOU: 0.366167, Class: 0.522596, Obj: 0.302629, No Obj: 0.339804, .5R: 0.000000, .75R: 0.000000, count: 7
nvidia-smi -l で見ていると
GPUの使用率はほぼ100%に張り付き
メモリーが1992Mしか搭載していないところ
1658Mバイト使用している。
Sat Mar 9 16:33:12 2019
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 390.116 Driver Version: 390.116 |
|-------------------------------+----------------------+----------------------+
| GPU Name Persistence-M| Bus-Id Disp.A | Volatile Uncorr. ECC |
| Fan Temp Perf Pwr:Usage/Cap| Memory-Usage | GPU-Util Compute M. |
|===============================+======================+======================|
| 0 GeForce GT 1030 Off | 00000000:01:00.0 On | N/A |
| 57% 61C P0 N/A / 30W | 1658MiB / 1992MiB | 97% Default |
+-------------------------------+----------------------+----------------------+
+-----------------------------------------------------------------------------+
| Processes: GPU Memory |
| GPU PID Type Process name Usage |
|=============================================================================|
| 0 861 G /usr/lib/xorg/Xorg 152MiB |
| 0 1005 G /usr/bin/gnome-shell 117MiB |
| 0 9839 G ...uest-channel-token=11718656754115347387 27MiB |
| 0 17442 C ./darknet 1349MiB |
+-----------------------------------------------------------------------------+
うまく行く予感しかしない。
ちなみにCPUの使用率はほぼぼ0でした。
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
r b swpd free buff cache si so bi bo in cs us sy id wa st
0 0 0 241176 315680 10381696 0 0 0 0 1049 1705 21 5 74 0 0
0 0 0 241476 315680 10381696 0 0 0 0 396 1413 2 3 94 0 0
1 0 0 241352 315680 10381696 0 0 0 0 441 1783 3 3 94 0 0
1 0 0 241352 315680 10381696 0 0 0 0 1078 1552 22 2 75 0 0
0 0 0 241104 315680 10381696 0 0 0 0 449 1676 4 2 94 0 0
0 0 0 241228 315680 10381696 0 0 0 0 1043 1937 21 4 75 0 0
CPUも使ったほうが、もう少しは早いかもと思ったりとか、
実はGPU無しでも結構行けるのでは?
などと思うのは無謀なのだろうか?
これで終わるまで待つ。
いやいや、参考ページによると「avg lossに変化が見られなくなったので強制終了」となっているので
時々avg lossの数字を確認する必要がありそうです。
最初が340ぐらい。
これで一晩放置プレー。おれは酒を飲む。そして寝る。zzzz..
そして朝。
さて、avg lossの数字を確認する。
4.32とかになっております。
これで行けそうな気がするので
darknet/backupフォルダーを確認すると
-rw-r--r-- 1 miha miha 246305388 3月 9 17:14 yolov3_1000.weights
-rw-r--r-- 1 miha miha 246305388 3月 9 17:57 yolov3_2000.weights
-rw-r--r-- 1 miha miha 246305388 3月 9 18:39 yolov3_3000.weights
-rw-r--r-- 1 miha miha 246305388 3月 9 19:22 yolov3_4000.weights
-rw-r--r-- 1 miha miha 246305388 3月 9 20:05 yolov3_5000.weights
-rw-r--r-- 1 miha miha 246305388 3月 9 20:46 yolov3_6000.weights
-rw-r--r-- 1 miha miha 246305388 3月 9 21:28 yolov3_7000.weights
-rw-r--r-- 1 miha miha 246305388 3月 9 22:10 yolov3_8000.weights
-rw-r--r-- 1 miha miha 246305388 3月 9 22:52 yolov3_9000.weights
-rw-r--r-- 1 miha miha 246305388 3月 9 23:34 yolov3_10000.weights
-rw-r--r-- 1 miha miha 246305388 3月 10 00:17 yolov3_11000.weights
-rw-r--r-- 1 miha miha 246305388 3月 10 01:00 yolov3_12000.weights
-rw-r--r-- 1 miha miha 246305388 3月 10 01:41 yolov3_13000.weights
-rw-r--r-- 1 miha miha 246305388 3月 10 02:22 yolov3_14000.weights
-rw-r--r-- 1 miha miha 246305388 3月 10 03:03 yolov3_15000.weights
-rw-r--r-- 1 miha miha 246305388 3月 10 03:45 yolov3_16000.weights
-rw-r--r-- 1 miha miha 246305388 3月 10 04:05 yolov3_last.weights
とファイルが出来ております。なんかすごく早起きしちゃいました。11時間経過ぐらいでしょうか?
ファイル名を見ると、40分おきぐらいに1000づつ数字が加算されていますね。
これは学習回数との事。
これの最後のlastをいつものWindowsのchainer+yoloの環境に持っていって顔を認識できるか試す。
■chainer+yolo3で顔認識
□chainerで読み込めるnpzの形式に変更する
copy yolov3_last.weights yolo3-face_final.weights
python darknet2npz.py --model yolo_v3 --n-fg-class 1 yolo3-face_final.weights yolo3-face_final.weights.npz
□classの一覧ファイルの作成
yolo3-face.list
以下の内容で作成
face
□実行!!
python yolo3.py --pretrained-model yolo3-face_final.weights.npz --class_num 1 --class_list yolo3-face.list 0
最後のパラメーター0はビデオストリーミングの0からリアルタイム
その代わりにファイル名を指定すればファイルに対して処理を行う。
□実行結果
python yolo3.py --pretrained-model yolo3-face_final.weights.npz --class_num 1 --class_list yolo3-face.list face.jpg
python yolo3.py --pretrained-model yolo3-face_final.weights.npz --class_num 1 --class_list yolo3-face.list face2.jpg
□プログラムは前と同じ
import time
import argparse
import matplotlib.pyplot as plt
import cv2
import numpy as np
from timeit import default_timer as timer
import chainer
from chainercv.datasets import voc_bbox_label_names
from chainercv.datasets import coco_bbox_label_names
from chainercv.links import YOLOv3
#色のテーブル 150まで対応
label_colors = (
(120, 120, 120),
(180, 120, 120),
(6, 230, 230),
(80, 50, 50),
(4, 200, 3),
(120, 120, 80),
(140, 140, 140),
(204, 5, 255),
(230, 230, 230),
(4, 250, 7),
(224, 5, 255),
(235, 255, 7),
(150, 5, 61),
(120, 120, 70),
(8, 255, 51),
(255, 6, 82),
(143, 255, 140),
(204, 255, 4),
(255, 51, 7),
(204, 70, 3),
(0, 102, 200),
(61, 230, 250),
(255, 6, 51),
(11, 102, 255),
(255, 7, 71),
(255, 9, 224),
(9, 7, 230),
(220, 220, 220),
(255, 9, 92),
(112, 9, 255),
(8, 255, 214),
(7, 255, 224),
(255, 184, 6),
(10, 255, 71),
(255, 41, 10),
(7, 255, 255),
(224, 255, 8),
(102, 8, 255),
(255, 61, 6),
(255, 194, 7),
(255, 122, 8),
(0, 255, 20),
(255, 8, 41),
(255, 5, 153),
(6, 51, 255),
(235, 12, 255),
(160, 150, 20),
(0, 163, 255),
(140, 140, 140),
(250, 10, 15),
(20, 255, 0),
(31, 255, 0),
(255, 31, 0),
(255, 224, 0),
(153, 255, 0),
(0, 0, 255),
(255, 71, 0),
(0, 235, 255),
(0, 173, 255),
(31, 0, 255),
(11, 200, 200),
(255, 82, 0),
(0, 255, 245),
(0, 61, 255),
(0, 255, 112),
(0, 255, 133),
(255, 0, 0),
(255, 163, 0),
(255, 102, 0),
(194, 255, 0),
(0, 143, 255),
(51, 255, 0),
(0, 82, 255),
(0, 255, 41),
(0, 255, 173),
(10, 0, 255),
(173, 255, 0),
(0, 255, 153),
(255, 92, 0),
(255, 0, 255),
(255, 0, 245),
(255, 0, 102),
(255, 173, 0),
(255, 0, 20),
(255, 184, 184),
(0, 31, 255),
(0, 255, 61),
(0, 71, 255),
(255, 0, 204),
(0, 255, 194),
(0, 255, 82),
(0, 10, 255),
(0, 112, 255),
(51, 0, 255),
(0, 194, 255),
(0, 122, 255),
(0, 255, 163),
(255, 153, 0),
(0, 255, 10),
(255, 112, 0),
(143, 255, 0),
(82, 0, 255),
(163, 255, 0),
(255, 235, 0),
(8, 184, 170),
(133, 0, 255),
(0, 255, 92),
(184, 0, 255),
(255, 0, 31),
(0, 184, 255),
(0, 214, 255),
(255, 0, 112),
(92, 255, 0),
(0, 224, 255),
(112, 224, 255),
(70, 184, 160),
(163, 0, 255),
(153, 0, 255),
(71, 255, 0),
(255, 0, 163),
(255, 204, 0),
(255, 0, 143),
(0, 255, 235),
(133, 255, 0),
(255, 0, 235),
(245, 0, 255),
(255, 0, 122),
(255, 245, 0),
(10, 190, 212),
(214, 255, 0),
(0, 204, 255),
(20, 0, 255),
(255, 255, 0),
(0, 153, 255),
(0, 41, 255),
(0, 255, 204),
(41, 0, 255),
(41, 255, 0),
(173, 0, 255),
(0, 245, 255),
(71, 0, 255),
(122, 0, 255),
(0, 255, 184),
(0, 92, 255),
(184, 255, 0),
(0, 133, 255),
(255, 214, 0),
(25, 194, 194),
(102, 255, 0),
(92, 0, 255),
(0, 0, 0)
)
def main():
parser = argparse.ArgumentParser()
parser.add_argument('--gpu', type=int, default=-1)
parser.add_argument('--pretrained-model', default='voc0712')
parser.add_argument('--class_num', default=20)
parser.add_argument('--class_list', default=0)
parser.add_argument('video')
args = parser.parse_args()
#
#パラメータ解析
# python yolo3.py 0
# デフォルトではvoc0712のモデルをダウンロードして来ます。認識できるのは20種類
#
# python yolo3.py --pretrained-model yolov3.weights.npz --class_num 80 --class_list yolov3.list 0
# --pretrained-model
# darknet2npz.pyで変換した学習済みモデルyolov3.weights.npzを指定
# --class_num
# 上記学習済みモデルのクラス数
# --class_list
# 上記学習済みモデルのクラス名一覧 1行に1クラス
# ビデオ
# WEBカメラの場合は0
# 動画ファイルの場合はファイル名
#
if args.pretrained_model=='voc0712' :
label_names = voc_bbox_label_names
model = YOLOv3(20, 'voc0712')
else :
print(args.class_list)
if args.class_list==0 :
label_names = coco_bbox_label_names
else:
f = open(args.class_list, "r")
name_list = []
for line in f:
line = line.strip()
name_list.append(line)
f.close()
label_names = name_list
model = YOLOv3(n_fg_class=int(args.class_num), pretrained_model=args.pretrained_model)
#GPU対応
# CPUなら省略
# GPUなら0
if args.gpu >= 0:
chainer.cuda.get_device_from_id(args.gpu).use()
model.to_gpu()
#
#対応しているクラス名一覧を表示する
#
for name in label_names:
print(name)
#
#WEBカメラまたは動画ファイルを開く
#
if args.video == "0":
vid = cv2.VideoCapture(0)
else:
vid = cv2.VideoCapture(args.video)
if not vid.isOpened():
raise ImportError("Couldn't open video file or webcam.")
# Compute aspect ratio of video
vidw = vid.get(cv2.CAP_PROP_FRAME_WIDTH)
vidh = vid.get(cv2.CAP_PROP_FRAME_HEIGHT)
# vidar = vidw / vidh
print(vidw)
print(vidh)
accum_time = 0
curr_fps = 0
fps = "FPS: ??"
prev_time = timer()
frame_count = 1
while True:
ret, frame = vid.read()
if ret == False:
time.sleep(5)
print("Done!")
return
# BGR -> RGB
rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
# Result image
result = frame.copy()
# (H, W, C) -> (C, H, W)
img = np.asarray(rgb, dtype = np.float32).transpose((2, 0, 1))
# Object Detection
bboxes, labels, scores = model.predict([img])
bbox, label, score = bboxes[0], labels[0], scores[0]
print("----------")
nPerson = 0
nBottle = 0
if len(bbox) != 0:
for i, bb in enumerate(bbox):
# print(i)
lb = label[i]
conf = score[i].tolist()
ymin = int(bb[0])
xmin = int(bb[1])
ymax = int(bb[2])
xmax = int(bb[3])
class_num = int(lb)
# Draw box 1
cv2.rectangle(result, (xmin, ymin), (xmax, ymax),
label_colors[class_num], 2)
# Draw box 2
# cv2.rectangle(result, (xmin, ymin), (xmax, ymax), (0,255,0), 2)
#text = label_names[class_num] + " " + ('%.2f' % conf)
text = label_names[class_num] + " " + ('%.2f' % conf)
print(text)
if(label_names[class_num] == 'person'):
nPerson = nPerson + 1
if(label_names[class_num] == 'bottle'):
nBottle = nBottle + 1
text_top = (xmin, ymin - 10)
text_bot = (xmin + 80, ymin + 5)
text_pos = (xmin + 5, ymin)
# Draw label 1
cv2.rectangle(result, text_top, text_bot,
label_colors[class_num], -1)
cv2.putText(result, text, text_pos,
cv2.FONT_HERSHEY_SIMPLEX, 0.35, (0, 0, 0), 1)
# Draw label 2
# cv2.rectangle(result, text_top, text_bot, (255,255,255), -1)
# cv2.putText(result, text, text_pos,
# cv2.FONT_HERSHEY_SIMPLEX, 0.35, (0, 0, 0), 1)
print("==========")
print("Number of people : " + str(nPerson))
print("Number of bottle : " + str(nBottle))
# Calculate FPS
curr_time = timer()
exec_time = curr_time - prev_time
prev_time = curr_time
accum_time = accum_time + exec_time
curr_fps = curr_fps + 1
if accum_time > 1:
accum_time = accum_time - 1
fps = "FPS:" + str(curr_fps)
curr_fps = 0