あきらぼ

テック系ブログ

物体検出モデルYOLOv5の使い方

こんにちは。

 

今回は物体検出のモデルYOLOv5を使って騒音がすごい住んでいるマンション前の交通量を計ってみるために使い方を確認してみました。

 

 

 

YOLOv5とは

まず、今回参考にしたのはYOLOv5のこちらのレポジトリ。

github.com

 

YOLOv5はその名の通りYOLOというベースのモデルからバージョンアップしていったものになります。

 

2015年にワシントン大学のJoseph Redmon氏によって提案された元々のベース(YOLO)の論文はこちらになります。

[1506.02640] You Only Look Once: Unified, Real-Time Object Detection

 

まずベースのアイデアの説明の前に識別(class probability prediction)と物体検出の違いについて簡単に説明させてください。

 

識別は以前行ったVGG16画像識別のように画像内の特徴量を検出してその画像がなにに該当するのか近しいものを推測します。

aki-lab.hatenadiary.com

 

一方、物体検出はその該当する物体が画像のどの部分にいるのかという追加のタスクが必要になります。

そこで簡単に思いつくのが識別を再帰的に画像の一部分に適応することで物体位置を検出するというスライディングウィンドウ法に代表されるような物体検出方法です。

しかし、こちらの方法では再帰的に識別処理を行わなければいけないので、計算負荷が大きくなってしまいリアルタイム性の高いアプリケーションには使用できません。

 

そこで、YOLOではその名前がYou Only Look Onceを示す通り、単一のNeural Networkで物体検出(物体の場所)と識別(物体が何か)を同時に行うことで一度の推定で物体検出を行おうというモデルになっています。

 

また、単一のNNとなっているので物体検出の最適化(損失)も一緒に評価できるので学習による物体検出性能の改善がしやすいというのも特徴となっています。

 

この論文をベースとしてv5までアップデートされています。

概要はこちらに説明があります。

YOLOv5 Documentation

 

また、YOLOv5はスマホアプリとしてもリリースされているんで簡単に試すことができます。

YOLOv5 🚀 and Vision AI ⭐

 

PyTorchで使ってみる

実際にYOLOv5を使ってみます。

PyTorchから直接モデルをしようできるので、公式のサンプルに従って以下のようにしました。

識別する画像は公式に従ってジダンです。(笑)

 

results.show()

リザルトのオブジェクトに対してshow()を行うと以下のようにラベリングされた画像を表示してくれます。

 

results.crop()

次にcrop()です。

物体の識別ごとに画像を切り出しくれます。

切り出した画像は実行ディレクトリにrunsというディレクトリが作られてその中に保存されます。

ディレクトリはこちら。

 

一点注意ですが、上記のshow()メソッドを一度使用してからcropするとラベルが残ってしまいます。

 

results.print()

次にprintメソッドです。

以下のように何を検出したのかと処理速度を表示してくれます。

image 1/1: 720x1280 2 persons, 2 ties
Speed: 232.0ms pre-process, 447.0ms inference, 6.0ms NMS per image at shape (1, 3, 384, 640)

 

results.pandas()

最後にpandasメソッドです。実際はpandasのxyxy[0]を参照しないと何がどこで検出されているかは分かりません。

複数画像を使うケースだと0番目以外も参照する必要があるのでしょうか。

恐らくこの物体検出モデルを応用していく上でもっとも使用すると思います。

         xmin        ymin         xmax        ymax  confidence  class    name
0  743.290527   48.343781  1141.756470  720.000000    0.879860      0  person
1  441.989594  437.336670   496.585114  710.036255    0.675119     27     tie
2  123.051056  193.238037   714.690674  719.771301    0.666694      0  person
3  978.989807  313.579468  1025.302856  415.526184    0.261517     27     tie

このように検出した物体の位置、物体のクラスがpandasのデータフレームとして取得することができます。

 

次回はこのデータフレームを使って、実際に道路の動画から自動車を検出してみます。

イメージはこんな感じです。

 

以上、YOLOv5の簡単な使い方でした。

 

 

【Python】Tkinterの再帰関数でRecursionError

こんにちは。

 

TKinterのafterによる再帰関数のエラーでハマったので少しそのこと書きます。

 

 

 

今回は以下のコードで「RecursionError: maximum recursion depth exceeded while calling a Python object」のエラーが生じてしまいました。

Tkinterでのafterメソッドでの再帰関数は定期実行でよく使う方法だと思います。

こちらは再帰関数によってメモリ使用量が増えすぎたりするのを防止するためのエラーだそうです。

 

 

結論としてはtk.afterで再帰する際にメソッドの引数はもともとないのですが、「()」を使用しないことでこちらのエラーは生じません。

 

こちらのコードでいう22行目の

self.after(100, self.DrawAnnotation())

self.after(100, self.DrawAnnotation)

に変更することでこちらのエラーは生じません。

引数があると再帰の際にメモリをリリースせずに新たに割り当ててしまうからでしょうか。

 

RaspberryPiで計測した環境センサ情報をSQLデータベースに書き込む

こんにちは。

 

今回は先日RaspberryPiで計測した環境データをSQLデータベースサーバーにアップロードします。

 

 

 

前回はCCS811とBME280から疑似CO2濃度と気圧を取得するところまで行いました。

RaspberryPiでCO2センサーCCS811を動かす - あきらぼ

RaspberryPiでBME280で気圧測定 - あきらぼ

 

今回はここで取得した値をSQLデータベースにアップロードします。

実際のコードはこちらです。

IPアドレス等は伏せています。)

 

実際にcrontabで定期実行させたときのデータベースを確認します。

 

eCO2の値が飛んでいるのは要確認ですが、15分毎にデータがアップロードされていることが確認できます。

 

次回はデータベースの値を使ってWEBページ上でこれらの値を可視化してみようと思います。

 

今回の環境モニタシステムのコードの全体はこちらになります。

GitHub - Aki-R/RoomConditionMonitor

 

 

PyTorchをWindows環境にインストールしてPyCharmで使用する

こんにちは。

今回はPyCharmでYOLOv5を使用するためにPyTorchをインストールしようとしたところ、上手くいかなかったので備忘録として残しておきます。
まず、私の環境はAnaconda等の仮想環境を使っていません。仮想環境を使っている場合のインストール方法はすぐに見つかったのですが、Windowsに直接Pythonをインストールしている場合です。


まず、PyCharmが使用しているPythonのパスを確認します。
SettingのProject Interpreterから確認することができます。

私の場合はAppDataの中ですね。

次にコマンドプロンプトでインストールしてるCUDAのバージョンを確認します。
CUDAをインストールしていなければ以下を参考にしてください。
Python Tensorflow でcudart64_110.dll not found - あきらぼ

GPUを使用しないでPyTorchを使用する場合はインストール不要です。

CUDAのバージョン確認は以下のコマンドで行えます。

nvcc -V

私の場合はV11.6でした。

次にCUDAバージョンに合ったPyCharmをインストールします。
以下のサイトでインストールのコマンドをコピーします。
pytorch.org


今回はpipを使用してインストールするので以下になります。

こちらのインストールコマンドをコピーして、pipでインストールしていきます。
pipはPythonInterpreterと同ディレクトリのScriptというディレクトリにあります。

私の場合は以下です。
C:\Users\UserName\AppData\Local\Programs\Python\Python38\Scripts

今回はこのディレクトリのpip3.pyに対して先ほどのコマンドを使用します。
pip3.pyのあるディレクトリでコマンドプロンプトを使用して、私の場合は以下のようになります。

python pip3.py install torch torchvision torchaudio --extra-index-url https://download.pytorch.org/whl/cu113

pip3ではなくpip3.pyに修正する必要があるのでご注意ください。
あとは勝手にPyTorchがインストールされます。

RaspberryPiでBME280で気圧測定

今回は気圧センサーであるBME280を使って気圧測定をしました。

 

最近梅雨入りしたせいで、ニュース等でも天気病などといって、気圧の低下に伴う体調不良が取り上げられるようになりました。
この天気病は気圧の絶対値ではなく、変化量が重要だと考えられています。

 

 

 

そこで、実際に時系列の自宅の気圧データを取得することで体調管理をしましょうというのが目的です。
完成形はこちらです。

 

 

さて、実際に実装に移っていきます。

BME280とRaspberryPiはI2Cで接続しています。

詳細はこちら

aki-lab.hatenadiary.com

 

今回使用した気圧センサーはドイツの自動車部品メーカーのボッシュ製のBME280になります。

ACEIRMC BME280搭載 温湿度 気圧センサーモジュール 5V用 SPI I2C Arduino対応 Raspberry Pi (1個)

 

データシートはこちらになります。

https://www.bosch-sensortec.com/media/boschsensortec/downloads/datasheets/bst-bme280-ds002.pdf

 

基本的にはこちらのデータシートの指示通りにレジスタを叩いてデータを取得していきます。

 

まず、実際のコードがこちらになります。

 

基本的にはデータシート通りの実装なのですが、pythonで記述する際に、変数の型が明示的ではなかったので、Numpyを使用して明示的に型変換を行うことでデータシート通りの温度と気圧の補正を行っています。

 

実際に実行するとこんな感じです。

pi@raspberrypi: python3 BME280.py
Device ID is 0x60
BME280 is connected.
Temperature 26.88 degC
Pressure 998.76 hPa

こちらの温度は気圧センサ補正に使用しているのでセンサーの温度です。

なので、室温よりは少し高い値になっているので単純な環境センサ値としては使えなさそうです。

 

あまり、レジスタ直叩きで使用している記事を見なかったので参考になればと思います。

 

実際に使用してみると、天気とは関係なく気圧が変動していることや、気密性の高いマンションだと換気扇を使うことで圧力が下がってしまうことです。

次回、頭が痛くなったときは値を確認してみようと思います。

 

コードの全体はこちらになります。

GitHub - Aki-R/CCS811_BME280_RPi: Upload CCS811 and BME280 measurement to database by using RaspberryPi

 

 

RaspberryPiでCO2センサーCCS811を動かす

こんにちは。

 

今回はRaspberryPiでCCS811を動かしました。

 

 

 

前回はRaspberryPiへの接続まで完了していました。

aki-lab.hatenadiary.com

 

KEYESTUDIO DC 5V CCS811 CO2 二酸化炭素 TVOC 大気質 センサー モジュール for Arduino アルドゥイーノ アルディーノ 電子工作

 

そして今回は実際に値を読み取るところまでを行います。

しかし、基本的なI2Cのフローは前回STM32で行った場合と同じになります。

aki-lab.hatenadiary.com

 

同じことをRaspberryPiで実装した形になります。

なので詳細は省きます。

 

今回のコードはこちらになります。

 

このまま実行します。

pi@raspberrypi: python3 CCS811_RPi.py
Device ID is 0x81
CCS811 is connected.
Application mode is in active.
Measure Mode is set to Mode1.
eCO2: 405
eTVOC: 0

 

二酸化炭素換算量が問題なく取得できました。

 

あとはこのデータをデータベースにアップロードして部屋環境モニターで使用する予定です。

 

コード全文はこちらに保存しています。

GitHub - Aki-R/CCS811_BME280_RPi: Upload CCS811 and BME280 measurement to database by using RaspberryPi

 

 

【Tensorflow】【Keras】CNNでHololiveメンバーの識別をしてみる

こんにちは。

今回は先日のモデルに引き続き、ざっくりと最初のHololiveメンバー識別機を作ってみたのでそのことを書こうと思います。


まず今回作った識別機がどのように動くかの動画がこちらになります。

youtu.be

 

 

 

 

背景

今回識別器を作った理由としては最近流行っているHololiveのメンバーがどんどん増えていって覚えきれません。

しかし、サムネイル等には出てくるし、いちいち調べるのも面倒。

そこでAIを使って判定させてしまおうというのが今回作った動機になります。

 

今回参考にしたのはこちらの本です。実際のKerasのコードまで書いてあって分かりやすかったです。

Pythonによるディープラーニング (Compass Booksシリーズ) 単行本(ソフトカバー)

 

教師データ収集

まず、教師データ集めです。

今回はGoogle検索を使ってHololiveメンバー58名分のデータをを集めました。

メンバー一覧はこちら。

所属タレント一覧 | hololive(ホロライブ)公式サイト

 

画像収集方法はこちらです。

aki-lab.hatenadiary.com

 

全部で集まった画像データは24254枚、平均一人あたり約400万になります。

しかし、インドネシア勢とはまだ画像データが少なく、あまり検出できていませんでした。

例えば、こぼ・かなえるはデータ数が少なく、集めたデータも本に以外のデータばかりだったので正しく識別できていませんでした。

 

 

そこで、後でYoutubeのサムネイル等から画像を集めて、正しいデータだけを残すようにすればまた精度が上がると思います。

 

識別CNNモデル

次に今回のモデルにはKerasに既に用意されている識別でよく使われるVGG16モデルをベースに使用します。

入力画像サイズは256×256です。

 

Model: "sequential"
_________________________________________________________________
 Layer (type)                Output Shape              Param #   
=================================================================
 rescaling (Rescaling)       (None, 256, 256, 3)       0         
                                                                 
 random_rotation (RandomRota  (None, 256, 256, 3)      0         
 tion)                                                           
                                                                 
 random_zoom (RandomZoom)    (None, 256, 256, 3)       0         
                                                                 
 random_flip (RandomFlip)    (None, 256, 256, 3)       0         
                                                                 
 random_translation (RandomT  (None, 256, 256, 3)      0         
 ranslation)                                                     
                                                                 
 vgg16 (Functional)          (None, None, None, 512)   14714688  
                                                                 
 flatten (Flatten)           (None, 32768)             0         
                                                                 
 dense (Dense)               (None, 512)               16777728  
                                                                 
 dropout (Dropout)           (None, 512)               0         
                                                                 
 dense_1 (Dense)             (None, 58)                29754     
                                                                 
=================================================================
Total params: 31,522,170
Trainable params: 23,886,906
Non-trainable params: 7,635,264
_________________________________________________________________

 

上流のRandom層は過学習対策になります。

最初からこの層を追加した状態で学習のハイパーパラメータ等設定していたので少し沼ってしまいました。

詳細はこちら。

 

aki-lab.hatenadiary.com

 

また、VGG16の内、下流側4層のみをパラメータ学習可能としています。

 

学習

まず、学習にあたって集まったデータの80%を学習用、20%を検証用としてランダムに分割します。

学習・最適化は以下のようにしています。

  • Optimizer:Adam
  • 損失:Categorical Crossentropy
  • 学習率:1.0e-4
  • バッチサイズ:128

 実際に学習を始めると、すぐに過学習に入ります。

 

10エポックを過ぎたあたりで過学習が始まっています。

最大精度で60%を少し超えるぐらいでした。

そこで最大精度のものを使用したのが動画で使用しているモデルになります。

 

識別器

最後にモデルを学習してそれで終わりでは、全く役に立たないので、実際にYotubeや画像で範囲を選択すると判定してくれるようなアプリを作ってみました。

 

今回はTkinterを使用して簡単なGUIの識別器を作りました。

詳細な説明はここではしませんが、ウィンドウを透明の256X256ピクセルのサイズにすることで、そこの表示を読み取ってモデルで判定させています。

 

一番確度(そうである可能性)の高いメンバー名を表示するようにしています。

詳しくはソースコードをご参照ください。

 

問題点

実際使ってみた問題点として、256x256のウィンドウサイズだと、二人以上のメンバーが同時にウィンドウ内に入ってしまうケースが多く、どちらを検出しているのか分かりません。

そこで領域も検出できるようにすると便利さ増すかなと思っています。

そのあたりも使える方法がないか調べて実装してみようと思います。

 

 

 

今回使用したコードは以下になります。(適宜アップデートするかもしれませんが。)

GitHub - Aki-R/Hololive_Categorizer: CNN categorizer for VTuber Holilive members

 

また、識別対象を増やしたり、精度改善も暇な時にでもしていこうと思います。

(人力で画像データ集めと振り分けが少し必要そう。こういう仕事をアノテーターというらしいです(笑))