#はじめに
- 従来AIは学習させて使用するものでしたが、最近は汎用の学習済みモデルをダウンロードして使えるようになってます。この1つに__YOLOV5__があります。
- これを利用して、カメラ付きノートPCをAI監視カメラ( = 物体認識するカメラ)にしてみました。
- CPUだけでどれだけの速さになるか、試したかったためです。
###工夫したこと
- ローカル化
ネットワーク環境に縛られず、使えるようにしました。 - PCカメラから映像取り込み
カメラからの映像を処理するようにしました。 - 推定検出の処理軽量化
ハイスペックでないPCで動かすために、処理を減らしました。
- 正確性は劣るが軽量なモデル__yolov5s__を使用
- 推定時の画像を小さくして軽量化
- 検出結果の変数取得
検出結果の矩形を取得し、ヒットエリアに入ったら、表示を変更するようにしました。
#内容
###1.PC環境
実施したPC環境は以下のとおりです。GPUは計算に使ってません。
CPU | Celeron N4100 |
メモリ | 8GB LPDDR4 |
###2.前準備
Windowsで使えるようにするため、以下のツール / システムをインストールしました。
インストール時に参考にしたサイトも記載します。
1.python(使用したのはVer.3.7 )
実行時のベースシステムです。
(参考)https://qiita.com/ssbb/items/b55ca899e0d5ce6ce963
2.pip(使用したのはVer.21.2.4 )
他のツールをダウンロードする際に使うツールです。
(python3系ではバージョン3.4以降であれば、pythonのインストールと共にpipもインストールされます。)
(参考)https://gammasoft.jp/python/python-library-install/
3.OpenCV(使用したのはVer.4.5.3 )
画像系処理するためのライブラリです。
(参考)https://qiita.com/ideagear/items/3f0807b7bde05aa18240
4.PyTorch(使用したのはVer.1.9.1+cpu )
DeepLearningのライブラリです。CPUだけでやるため、Compute PlatformはCPUにしました。
(参考)https://qiita.com/thinknee/items/0c0c466928356c9a55af
5.YOLOV5(使用したのはVer.5.0 )
物体検出のアルゴリズムです。
(参考)https://github.com/ultralytics/yolov5
5.yolov5s.pt
使用する学習済みモデルです。
YOLOV5のフォルダで、例えば以下のコードを実行すると自動でダウンロードされます。
detect.py --source data/images/bus.jpg --weights yolov5s.pt
次に組むpyファイルと同じフォルダに置きます。
(このptファイルは、pyファイルを実行したときになければ、自動でダウンロードされます。)
###3.pyファイルの作成
組んだコードは次のとおりです。
import sys
import cv2
import torch
#--- 検出する際のモデルを読込 ---
#model = torch.hub.load('ultralytics/yolov5','yolov5s')#--- webのyolov5sを使用
model = torch.hub.load("../yolov5",'yolov5s',source='local')#--- localのyolov5sを使用
#--- 検出の設定 ---
model.conf = 0.5 #--- 検出の下限値(<1)。設定しなければすべて検出
model.classes = [0] #--- 0:person クラスだけ検出する。設定しなければすべて検出
#print(model.names) #--- (参考)クラスの一覧をコンソールに表示
#--- 映像の読込元指定 ---
#camera = cv2.VideoCapture("../pytorch_yolov3/data/sample.avi")#--- localの動画ファイルを指定
camera = cv2.VideoCapture(0) #--- カメラ:Ch.(ここでは0)を指定
#--- 画像のこの位置より左で検出したら、ヒットとするヒットエリアのためのパラメータ ---
pos_x = 240
while True:
#--- 画像の取得 ---
# imgs = 'https://ultralytics.com/images/bus.jpg'#--- webのイメージファイルを画像として取得
# imgs = ["../pytorch_yolov3/data/dog.png"] #--- localのイメージファイルを画像として取得
ret, imgs = camera.read() #--- 映像から1フレームを画像として取得
#--- 推定の検出結果を取得 ---
# results = model(imgs) #--- サイズを指定しない場合は640ピクセルの画像にして処理
results = model(imgs, size=160) #--- 160ピクセルの画像にして処理
#--- 出力 ---
#--- 検出結果を画像に描画して表示 ---
#--- 各検出について
for *box, conf, cls in results.xyxy[0]: # xyxy, confidence, class
#--- クラス名と信頼度を文字列変数に代入
s = model.names[int(cls)]+":"+'{:.1f}'.format(float(conf)*100)
#--- ヒットしたかどうかで枠色(cc)と文字色(cc2)の指定
if int(box[0])>pos_x :
cc = (255,255,0)
cc2 = (128,0,0)
else:
cc = (0,255,255)
cc2 = (0,128,128)
#--- 枠描画
cv2.rectangle(
imgs,
(int(box[0]), int(box[1])),
(int(box[2]), int(box[3])),
color=cc,
thickness=2,
)
#--- 文字枠と文字列描画
cv2.rectangle(imgs, (int(box[0]), int(box[1])-20), (int(box[0])+len(s)*10, int(box[1])), cc, -1)
cv2.putText(imgs, s, (int(box[0]), int(box[1])-5), cv2.FONT_HERSHEY_PLAIN, 1, cc2, 1, cv2.LINE_AA)
#--- ヒットエリアのラインを描画
cv2.line(imgs, (pos_x, 0), (pos_x, 640), (128,128,128), 3)
#--- 描画した画像を表示
cv2.imshow('color',imgs)
#--- (参考)yolo標準機能を使った出力 ---
# results.show()#--- yolo標準の画面表示
# results.print()#--- yolo標準のコンソール表示
#--- (参考)yolo標準の画面を画像取得してopencvで表示 ---
# pics = results.render()
# pic = pics[0]
# cv2.imshow('color',pic)
#--- 「q」キー操作があればwhileループを抜ける ---
if cv2.waitKey(1) & 0xFF == ord('q'):
break
###4.説明
####1. ローカル化
以下のhub関数のコードのところを1行目から2行目のように書き換え、ローカル処理にしました。
#model = torch.hub.load('ultralytics/yolov5','yolov5s')#--- webのyolov5sを使用
model = torch.hub.load("../yolov5",'yolov5s',source='local')#--- localのyolov5sを使用
####2. PCカメラから映像取り込み
以下のコードのところを1行目から2行目のように書き換え、カメラ画像を取り込むようにしました。
#camera = cv2.VideoCapture("../pytorch_yolov3/data/sample.avi")#--- localの動画ファイルを指定
camera = cv2.VideoCapture(0) #--- カメラ:Ch.(ここでは0)を指定
####3. 推定検出の処理軽量化
- 正確性は劣るが軽量なモデル__yolov5s__を使用
以下のコードで__yolov5s__を使うようにしました。
model = torch.hub.load("../yolov5",'yolov5s',source='local')#--- localのyolov5sを使用
YOLOV5のモデルには、yolov5n、yolov5s、yolov5m、yolov5l、yolov5xなどがあります。
(参考)https://github.com/ultralytics/yolov5/releases
- 推定時の画像を小さくして軽量化
以下のコードのところを1行目から2行目のように書き換え、処理画像を荒く小さくしました。
# results = model(imgs) #--- サイズを指定しない場合は640ピクセルの画像にして処理
results = model(imgs, size=160) #--- 160ピクセルの画像にして処理
####4. 検出結果の変数取得
以下のコードで各検出の変数をfor文で取得しました。
for *box, conf, cls in results.xyxy[0]: # xyxy, confidence, class
変数種類とこのコードにて代入される変数名の対応は下表のとおりです。
変数種類 | 変数名 |
---|---|
矩形の左上角のX座標 | box[0] |
矩形の左上角のY座標 | box[1] |
矩形の右下角のX座標 | box[2] |
矩形の右下角のY座標 | box[3] |
クラスの番号 | cls |
推定の信頼度 | conf |
これらの変数を利用して、後処理を変えることができます。
今回はヒットエリア(画面の左側)で検出したものは枠の色を変更するようにしました。
###5.結果
カメラ映像でも遅延が気にならない速さで処理できました。
ちなみに、results = model(imgs, size=160)
のところでsize=160
をsize=80
にするともっと速く処理できますが、検出ミスがひどくなりました。逆にsize=320
にすると遅延が気になるところまで遅くなりました。
#参考