あきらぼ

テック系ブログ

iPhoneの写真をheicファイルからjpegファイルにpython で変換する

またやってしまいました。

 

今までWindowsユーザーの私はiphone のデフォルト設定であるheicフォーマットの写真を扱いづらいのでjpeg保存にしていたのですが、iPhoneを買い替えた際に元の設定に戻ってしまっていました。

 

heicは圧縮率が高いので便利な面もありますが、こうやってブログを書いたりする際にWindowsPCで読み込んだり加工しづらく困ってしまいます。

すでに写真はheicのままAmazonPhotoにアップロードされてしまっているし。

 

 

 

そこで今回はpythonでheicからjpegへ変換するスクリプトを書いてみました。

 

変換で使用するパッケージはpillow_heifです。

以下のコマンドでインストールします。

sudo pip install pillow_heif

windowsなら

python -m pip install pillow_heif

 

あとはChatGPTさんに協力してもらいながらスクリプトを書きます。

GPTさん優秀なプロンプトエンジニアなので、適切に指示すれば綺麗に作ってくれます。

 

 

あとは入力にheicファイルが保存されているディレクトリと変換したファイルを保存したいディレクトリを指定して使用します。

python heic_jpeg_converter.py -i input_directory -o output_directory

実際の例はこんな感じ。

python heic_jpeg_converter.py -i path/to/heic_files -o path/to/output_directory

 

とりあえず、これで変換してブログ用の画像等を変換して使いました。

 

今回作成したスクリプトはこちら。

github.com

Streamlitで部屋の温度・湿度モニターの可視化ボード作成

こんにちは。

 

今回はStreamlitを使って以前作った部屋の温湿度モニターの可視化ボードを作ってみました。

以前はChart.jsを使ってグラフ化していたのですが、Streamlitを使うと簡単にもっとInteractiveな表示ができそうなので試してみた次第です。

 

前回Chat.jsを使った際の記事はこちら。

 

aki-lab.hatenadiary.com

 

Streamlitとは?

Streamlitとはpythonのwebフレームワークで、データ解析に特化したフレームワークになります。

Pandasなどと相性がよく、データサイエンスやAIのフィールドでよく利用されているようです。

実際、私も仕事で解析のスクリプト組んだとしても結果の共有に悩む場面が多いですが、こういったWEBで表示できると共有先の環境に合わせる必要がなく便利というわけです。

 

streamlit.io

 

実際、使用してみた感じでもWEB上で細かくデータも見ることができるのでとても便利です。

一時解析ぐらいできてしまうぐらいインタラクティブに動かせるのも魅力です。

実際のサンプルサイト

今回使った実際のサンプルサイトはこちらになります。

JSON形式のデータを読み込んで表示しています。

https://aki-r-streamlit-sample-app-gkayym.streamlit.app/

 

まずはLineグラフに関して。

SreamlitのAPIにも線グラフのAPIはありますが、Plotlyと組み合わせられるのでグラフはPlotlyで表示しています。

Plotlyの方がカスタマイズ性が高いです。

実際見てもらうとドラッグ、ズームも簡単でPNGで出力もできます。

 

以前使っていたChart.jsよりもグリグリと動かせるので使い勝手がとても良いです。

 

次にPandasのデータフレーム表示に関して。

データフレームを簡単に表示できるだけでなく、変数名のところをクリックすることで簡単にソートできてしまいます。

これだけで簡単な一時解析できるぐらいの便利さです。

 

こんな形で、データ表示としては強力なGUIを作ることができます。

 

実装コード

今回上記のサンプルを作成したのは以下のコードです。

GUIアプリですが、この程度であれば非同期やコールバックを考えずにそこそこ実装できます。

 

 

公開はサーバーであればstreamlitをpipでインストールして実行するだけ。

今回添付したサンプルはstreamlitの機能でgithub連携で公開していてデプロイも楽ちんです。

 

今回のコードはこちらです。

github.com

 

以上、Streamlitでの可視化ダッシュボード作成でした。

 

【Tensorflow】【Python】PythonとSpleeterでYoutubeから動画をダウンロードして音楽とボーカル音声を分離して保存する。

こんにちは。

 

今回は音声と演奏を分けるSpleeterを使用してYoutubeから動画をダウンロードして音声と演奏を分けてみようと思います。

 

こんなことができるようになります。

www.youtube.com

 

 

 

 

Spleeter

Spleeterとは音楽ストリーミングサービス「dezzer」が公開しているオープンソースのTensorflowをつかったAIの演奏分離ライブラリになります。

 

Deezer Research - Spleeter

 

GitHub - deezer/spleeter: Deezer source separation library including pretrained models.

 

最大でボーカル / ドラム / ベース / ピアノ / その他 の5つの音に分解することができます(5 stems)

 

今回はボーカルと演奏の二つに分けていきます。

 

インストール

今回はYouTubeからPythonで動画をダウンロードするのにpytubeのパッケージを使います。

ダウンロードした動画から音声mp3の抽出はffmpeg、最後に音声分離のspleeterを使用します。

それぞれpipでインストールできるのでインストールします。

 

コード

コードはとりあえず以下のようにしました。

 

 

流れとしては

  1. pytubeでmp4として動画をYoutubeからダウンロード
  2. ffmpegでmp4から音声だけのmp3を抽出
  3. 抽出したmp3からspleeterでボーカル・演奏分離

みたいな感じです。

 

ちなみにSpleeterによる分離する音声の時間をdurationで決められるのですが、デフォルトで10分、伸ばしても1000秒程度までで、それ以上だとエラーを吐いてしまいます。

 

暇なときに10分毎に処理できるようにアップデートしようと思います。

 

あとは、出力されたmp3をうまく使えば冒頭の動画のようにできます。

 

コードのレポジトリはこちら。

GitHub - Aki-R/YouTube_Downloader

 

これでVtuber歌枠を編集しやすくなりました。

 

 

【Keras】【Tensorflow】VGG16ベースのモデルをSequentialモデルとFunctionalモデルで作る

こんにちは。

 

今回は以前作ったVGG16ベースで作った画像分類器をSequentialからFunctionalでモデルを作り直そうと思います。

 

以前作った画像分類器の記事はこちら。

aki-lab.hatenadiary.com

 

 

 

 

Sequential

前回はSequentialモデルでVGG16をベースとして前段にデータ拡張、後段に全結合層を追加していました。

 

具体的なコードはこんな感じ。

実際にモデルを確認してみます。

上記コードで作ったモデルに対して以下のように詳細を確認します。

model.summary()

以下のように表示されます。

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
_________________________________________________________________

 

Functional

次は同じモデルをFunctionalモデルで作成します。

作成コードはこちらです。

 

先ほどと同じようにモデルを確認します。

Model: "model"
_________________________________________________________________
 Layer (type)                Output Shape              Param #
=================================================================
 input_1 (InputLayer)        [(None, 256, 256, 3)]     0

 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)

 block1_conv1 (Conv2D)       (None, 256, 256, 64)      1792

 block1_conv2 (Conv2D)       (None, 256, 256, 64)      36928

 block1_pool (MaxPooling2D)  (None, 128, 128, 64)      0

 block2_conv1 (Conv2D)       (None, 128, 128, 128)     73856

 block2_conv2 (Conv2D)       (None, 128, 128, 128)     147584

 block2_pool (MaxPooling2D)  (None, 64, 64, 128)       0

 block3_conv1 (Conv2D)       (None, 64, 64, 256)       295168

 block3_conv2 (Conv2D)       (None, 64, 64, 256)       590080

 block3_conv3 (Conv2D)       (None, 64, 64, 256)       590080

 block3_pool (MaxPooling2D)  (None, 32, 32, 256)       0

 block4_conv1 (Conv2D)       (None, 32, 32, 512)       1180160

 block4_conv2 (Conv2D)       (None, 32, 32, 512)       2359808

 block4_conv3 (Conv2D)       (None, 32, 32, 512)       2359808

 block4_pool (MaxPooling2D)  (None, 16, 16, 512)       0

 block5_conv1 (Conv2D)       (None, 16, 16, 512)       2359808

 block5_conv2 (Conv2D)       (None, 16, 16, 512)       2359808

 block5_conv3 (Conv2D)       (None, 16, 16, 512)       2359808

 block5_pool (MaxPooling2D)  (None, 8, 8, 512)         0

 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
_________________________________________________________________

VGG16モデルが展開されてしまっていますが、意図通り、Functionalモデルで作成することができました。

 

次回はこちらで学習させて量子化した計量モデルを作っていこうと思います。

 

 

物体検出モデルYOLOv5を用いて家の前の交通量調査をしてみた

こんにちは。

 

先日、YOLOv5の使い方を確認しました。

aki-lab.hatenadiary.com

 

今度はこのモデルを使って、当初の目的である交通量調査を行いたいと思います。

こんな感じになります。

 

 

 

将来的にはリアルタイムで交通量をモニタしたいのですが、まずはコンセプト検証ということで録画したビデオ映像に対して交通量調査機能を実装していこうと思います。

 

そこで、まずはカメラの出番です。

結構昔のモデルにはなってしまいますがGoPro Hero3になります。

 

バッテリーは死んでいたのですが、互換品購入してバッテリー入れ替えたら時間的には十分な時間録画できそうです。

Amazon | Smatree GoPro Hero3 用1290mAhバッテリー2個 充電器とUSBコード付き CHDHX-301-JP | カメラ用アクセサリキット 通販

 

ベランダのへりに固定したら動画を撮影します。

 

約1時間の動画が撮影できました。

以下がその一部になります。

 

youtu.be

 

この動画に対してYOLOv5の物体検出モデルを使って交通量をカウントしていきます。

 

まず手始めに動画に対して車として認識されたものを四角で囲ってみます。

確度(その物体の確からしさ)が高いものは青色、低いものは緑色で囲うようにしています。

 

youtu.be

 

白いガードレールを誤検出してしまっていますね。

確かに白いハイエースに見えないこともない?

 

次に物体をトラッキングしていきます。

交通量をカウントするためには検出した物体がどのように移動していくのかをトラッキングしていく必要があります。

カルマンフィルタを使って確率論的に処理したり、検出したオブジェクトの特徴量から同じ物体をトラッキングしたりと様々な手法があるようですが、とりあえず思い付きで作ってみました。

 

ラッキングに必要な工程としては以下になります。

1.オブジェクトの新規生成

2.オブジェクトの移動

3.オブジェクトの消失

となります。

 

今回はざっくりいうと、

1.オブジェクトの新規生成は今まで何も近傍にオブジェクトがなかったところにオブジェクトが生成された場合に新規オブジェクトとしてID付与。

2.検出中心の近傍にオブジェクトがあった場合はそのオブジェクトが移動したものとしてIDを継承。

3.オブジェクトの近傍に検出が無い場合はオブジェクトが消失したものとする

といった方式です。

 

このベースに加えて、新規生成場所や消失場所を制限させたり、近傍の定義を左右に長くする(道路的に上下の移動はほとんどない)等でトラッキングしやすいようにしています。

 

とりあえず、作ってみます。

オブジェクト一つ一つに固有の番号(ID)を付与して表示してみます。

youtu.be

 

オブジェクトの消失がうまくいかなかったり、逆に新規オブジェクトとして認識されてしまってIDが変化し続けてしまったりしていますね。

バグを修正していきます。

 

バグを修正したらコントロールライン(検査ライン)を決めて、そこを通過するオブジェクトの数をカウントしてきます。

 

とりあえず左方向の交通量をカウントします。

右下に交通量カウントを表示しています。

 

youtu.be

 

とりあえず私がテキトーに交通量カウントするのと同じぐらいの精度は出せているかなと思います。

 

やはりトラック等の大型車両で奥の車線が見えなくなったり、手前が見切れて上手く検出できなかったりと改善点は多々ありますが、作りたかったものはとりあえず完成です。

 

改善点としてはやはりオブジェクトトラッキングでカルマンフィルタ等の分散を用いた実装にしたいですね。

 

次にやるとしたら、これをリアルタイムで動かすことです。

全日交通量を監視するとなると常にリアルタイムで監視する必要があります。

するとPCはつけっぱなしできないので、低消費電力でギリギリYOLOv5がリアルタイムで動くハードウェアが必要になってきます。

JETSONとかですかね。(笑)

Amazon | NVIDIA Jetson Nano 2GB デベロッパーキット (945-13541-0000-000) | NVIDIA | グラフィックボード 通販

 

RaspberryPiの処理能力でもいけるのでしょうか。

Amazon | RasTech Raspberry Pi 4 Model B(RAM 2GB)ラズベリーパイ4B 技適マーク付き/ 32GBのMicroSDカード/ 5V 3A USB-Type-C ON/OFFスイッチ付き電源アダプター/2つのMicroHDMI-to-HDMIケーブルラインラズパイ専用ケース/冷却ファン/三つヒートシンク/ドライバー/カードリーダ 日本語取扱説明書 | R∞RasTech | ベアボーンPC 通販

 

とりあえずこんなところで、私としては自宅前が20分で片側二車線だけで100台以上通過する騒音ひどい環境だということが認識できたので満足です。

 

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

github.com

 

以上、今回の開発でした。

 

追記

物体追跡(Object Tracking)のモデルとしてByteTrackというものをYOLOv5と合わせて使用している人が多いですね。

今度、使ってみようかなと思います。

【やってみた】YOLOv5+ByteTrackでオブジェクトトラッキング! - 神戸のデータ活用塾!KDL Data Blog

 

 

 

物体検出モデル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)

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

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