Raspberry Piを用いたメラノーマのリアルタイム診断

#はじめに

先日kaggleのメラノーマコンペに参加し、精度の高さに驚きました。せっかくなので作成したモデルをラズパイに組み込んでみようと思います。すでに、コンペ一位の方がコンペのモデルで自己の黒子に対する診断が行えるようにソースコードを開示してくていました。しかしながら、画像を撮影してからPCにアップする必要があるので少々手間かもしれません。参考：https://www.kaggle.com/haqishen/1st-place-soluiton-best-model-infer
そこで、手軽に診断できることを目標に、ラズパイに取り付けたカメラからリアルタイムに判別が可能か検証してみようと思います。

今回の試みは、あくまで実験レベルのものとお考え下さい。結果も参考程度という位置付けになります。
病院では、きちんとした手順でメラノーマ（悪性黒色腫）の確定診断を行っていますので、正確な診断を希望する場合は病院へ行くことを強くおすすめします。
悪性黒色腫と診断するには、本来以下の手順を踏む必要があります。
まず肉眼やダーモスコピー*による観察を行います。そして確定診断や、腫瘍の厚さを調べるために、病変を切除して採取した組織を顕微鏡で調べる生検が行われます。ただ、診断が明らかな場合は、生検が行われない場合もあるそうです。確定診断に至った場合、他の部位への転移の有無を調べるための画像検査（CT、MRI、PETペット、X線検査、超音波検査など）や、心機能、肺機能、腎機能などを調べる検査等も行われるそうです。
*ダーモスコピーとは、エコージェルや偏光レンズ＊で光の乱反射を抑え、強い光線を照射することにより皮膚病変を10～30倍に拡大して観察する機器（ダーモスコープ）を使った診断法
参考：https://p.ono-oncology.jp/cancers/mela/04_inspection/01.html

また、モデルの重みは守秘義務の観点から開示しておりません。
kaggle上には公開されているモデルがいくつかありますので、自身で作成した後、自己責任にてご使用頂くようお願いします。


#実験の目的
メラノーマ予測モデルをRaspberry Piに組み込み、カメラからリアルタイムに判別可能か検証する。


#実験条件・方法
今回は、コンペで使用したモデルとは別のモデルを使用して、画像に写っている病変を判別します。一応、AUCは0.9以上あります。
判別する画像データはネット上で拾ってきたもの及び、自分の黒子を使用しました。

なぜか、Raspberry pi では学習したモデルをそのまま読み込むことはできませんでした。
調べたところ、Functional APIモデルは重みでしか読み込めないようです。
そこで、Sequentialモデルで作成し直したのですが、やはりモデルをそのまま読み込むことはできませんでした。

そのため、ラズパイ側でもう一度モデルを構築してから、学習したモデルの重みを読み込むようにしました。
使用したSequentialモデルは以下になります。

\#model building
import tensorflow as tf
import efficientnet.tfkeras as efn
IMAGE_SIZE = [384,384] 

model = tf.keras.Sequential([
    efn.EfficientNetB5(
        input_shape=(*IMAGE_SIZE, 3),
        weights='imagenet',
        include_top=False
    ),
    L.GlobalAveragePooling2D(),
    L.Dense(1024, activation = 'relu'), 
    L.Dropout(0.3), 
    L.Dense(512, activation= 'relu'), 
    L.Dropout(0.2), 
    L.Dense(256, activation='relu'), 
    L.Dropout(0.2), 
    L.Dense(128, activation='relu'), 
    L.Dropout(0.1), 
    L.Dense(1, activation='sigmoid')
])  


ラズパイとカメラは以下のものを使用しました。
ラズパイ：Raspberry Pi 3 model b+
カメラ：Logicool C270
![1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/701901/560b39b8-4395-1e7f-8304-3fdfba27c02d.jpeg)



ラズパイに書き込んだ全体コードは以下になります。
https://github.com/tacotacorice/melanoma/blob/master/prediction.py

また、ラズパイの環境構築は以下の記事を参考にしました。
https://karaage.hatenadiary.jp/entry/2017/08/09/073000


#実験結果
プログラムを実行することで、ラズパイに取り付けたカメラが起動します。
![2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/701901/85c93e03-e158-eacb-92d9-7769b38b1749.jpeg)
なんか、いっぱい警告出てますが無視します（笑）

その後、患所が映っているところで　"p"　を押すと撮影されます。
撮影した後、予測結果の出力に5秒ほどかかってしまいました。
予測結果は以下になります。



良性の画像
![a1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/701901/394ea33c-1563-1bf0-f228-d9036af2be4a.jpeg)
結果
![a2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/701901/de36f645-d90e-24e9-53fd-cfc1e93fd1ae.jpeg)
Benign（良性）と正しく診断してくれました。



続けて、
悪性の画像
![b1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/701901/40857255-a242-8789-0d3a-261f5797bb16.jpeg)
結果
![b2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/701901/17d8c3e0-d2a8-442c-91c3-2dfec3543563.jpeg)
こちらもMalignant（悪性）と正しく診断してくれました。
（まだ警告でてますね、、）



最後に私の黒子画像
![cc1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/701901/960d2bd2-8ad3-6e62-1682-d8ec4d27e8ed.jpeg)
結果
![cc2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/701901/8d1729e0-410c-be9c-894a-e9a79317baf9.jpeg)
おお！良性です！！安心しました（泣）
画像をスクショし忘れたので２回診断してますが、どちらも良性でした。予測値も低めですね！
（正常なのかわかりませんが警告も消えてくれました）


#実験結果
メラノーマ予測モデルをRaspberry Piに組み込み、カメラからリアルタイムに判別可能かどうか検証しました。
検証の結果、画像から良性悪性をきちんと判別してくれました。
私の黒子もどうやら悪性の可能性は低いようです。





#課題
・コンペ上位者の精度の高いモデルの組み込み
・精度の保証
・写真の映り方で精度が変わってしまう
・悪性良性の適切な閾値の設定方法
・カメラのピントが合わず、患所に近づけた場合撮影した画像が粗くなる
・ラズパイでは予測に時間がかかるのでJetson等を用いて予測時間を短縮する




#まとめ
今回ラズパイを用いて簡易メラノーマ診断キットを作成しました。
予測には少し時間がかかりますが、きちんと判別ができているようです。
現場で使えるようにするためには、精度の保証と速度の向上が必要になりそうです。
今回作成したプログラムを少し変えるだけで、他の学習モデルのリアルタイム予測も可能だと思いますので色々試してみてください。