コンクリートひび割れ画像の分類(SDNET2018)

画像処理の学習のため、コンクリートひび割れ画像の分類をしてみました。SDNET2018というデータセットを使っています。**95.8%**という高い平均適合率(Average Precision)が出せました！
ただ、これはGoogle Cloud AutoML Vision使っただけなので、難しいことを成し遂げた感はまるでないです・・・

# サマリ

- 使用データセット: SDNET2018のひび割れ1000枚とひび割れなし2000枚
- 使ったツール：Google Cloud AutoML Vision
- 平均適合率：95.8%
- 適合率：90.637%
- 再現率：90.637%

※「適合率」などの評価指標については、別記事[「【入門者向け】機械学習の分類問題評価指標解説(正解率・適合率・再現率など)」](https://qiita.com/FukuharaYohei/items/be89a99c53586fa4e2e4)を参照ください。

#使用したSDNETのデータセット
コンクリートのひび割れ画像データセットであるSDNET2018を使いました。ひび割れ1000枚("CD"フォルダ)とひび割れなし2000枚("UD"フォルダ)のみを使ったのですが、実際にはもっと画像枚数あります。
[SDNET2018: An annotated image dataset for non-contact concrete crack detection using deep convolutional neural networks](https://www.sciencedirect.com/science/article/pii/S2352340918314082)

> Images are organized into three sub-directories: P for pavements, W for walls, and D for bridge decks. Each subfolder is further organized into sub-sub-directories with the prefix C for cracked and U for uncracked (e.g.,:/D/CD for images of bridge decks with cracks). 

#手順
基本的に記事[「Google Cloud AutoML Visionを使ってみてた」](https://qiita.com/FukuharaYohei/items/672d908c76c59da801a1)の手順どおりです。

#結果の考察
混合行列(実際のAutoML VisionのUIと縦横を逆にしています)は、下記のようになっておりFN(実際はひび割れがあるのにないと予測した誤り)が22.2%と多いです。

||実際がPositive<br>(ひび割れ)|実際がNegative<br>(ひび割れなし)|
|:-:|:-:|:-:|
|予測がPositive<br>(ひび割れ)|TP<br>77.8%|FP<br>1.8%|
|予測がNegative<br>(ひび割れなし)|FN<br>22.2%|TN<br>98.2%|

FNの画像を何枚か見てみます。人間が見てもひび割れがあるか判断に迷いますね・・・。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/134273/7f877850-c4bd-e299-d61e-6f5bb2151991.png)
![image.png](https://qiita-image-store.s3.amazonaws.com/0/134273/5758c2c5-cd38-b3a5-35cb-579bcce69e24.png)
![image.png](https://qiita-image-store.s3.amazonaws.com/0/134273/ba853762-4651-bafd-2d23-d89b954969e0.png)
![image.png](https://qiita-image-store.s3.amazonaws.com/0/134273/97418b64-121f-bdac-c374-60d54082947d.png)


# おまけ：前処理を追加
もっと結果がよくならないか、といくつかOpenCVで前処理をしてみました。しかし、逆に悪くなってしまいました・・・
以下の3つを試しています。結論から言うと、何かするたびに結果が悪くなっていっています:angel:
[GitHub](https://github.com/YoheiFukuhara/sdnet_image)に使った画像、CSV、Pythonコードがあります。

1. 白黒化
2. 白黒化して二値化
3. 白黒化、ラプラシアンフィルタ適用後に膨張

## 結果比較

|No.|前処理|平均適合率|適合率|再現率|TP|FN|FP|TN|
|:-:|:---|:-:|:-:|:-:|:-:|:-:|:-:|:-:|
|0|なし|95.8%|90.6%|90.6%|77.8%|22.2%|1.8%|98.2%|
|1|白黒化|94.2%|90.2%|90.2%|77.3%|22.7%|3.2%|96.8%|
|2|白黒化して二値化|91.1%|84.5%|84.5%|62.1%|37.9%|5.6%|94.4%|
|3|白黒化、ラプラシアンフィルタ適用後に膨張|90.9%|86.3%|86.3%|57.7%|42.3%|0.9%|99.1%|

##1. 白黒化
グレースケールに画像変換しています。人間の見た目にはあまり変わりません。意外とカラー部分に重要な情報あるんでしょうね。
[*OpenCVのcvtColor関数*](http://labs.eecs.tottori-u.ac.jp/sd/Member/oyamada/OpenCV/html/py_tutorials/py_imgproc/py_colorspaces/py_colorspaces.html?highlight=cvtcolor)を使って[ツール](https://github.com/YoheiFukuhara/sdnet_image/blob/master/01.gray.py)を作りました。


##2. 白黒化して二値化
グレースケールにしてから大津の二値化しています。二値化でごっそり情報削ったのものあって一気に分類精度悪くなっていますね。
[*OpenCVのthreshold関数*](http://labs.eecs.tottori-u.ac.jp/sd/Member/oyamada/OpenCV/html/py_tutorials/py_imgproc/py_thresholding/py_thresholding.html?highlight=threshold)を使って[ツール](https://github.com/YoheiFukuhara/sdnet_image/blob/master/02.thresh.py)を作りました。


##3. 白黒化、ラプラシアンフィルタ適用後に膨張
グレースケールにしてからラプラシアンフィルタ適用して、膨張をしています。[ラプラシアンフィルタ](http://labs.eecs.tottori-u.ac.jp/sd/Member/oyamada/OpenCV/html/py_tutorials/py_imgproc/py_gradients/py_gradients.html#laplacian)は負の勾配も考慮しています。膨張をさせたのは、膨張しないと全然見えなかったので強調させたかったからです。
情報が消失してしまっている画像もあります。
OpenCVの[*filter2D*](http://labs.eecs.tottori-u.ac.jp/sd/Member/oyamada/OpenCV/html/py_tutorials/py_imgproc/py_filtering/py_filtering.html?highlight=filter2d)と[*dilate関数*](http://labs.eecs.tottori-u.ac.jp/sd/Member/oyamada/OpenCV/html/py_tutorials/py_imgproc/py_morphological_ops/py_morphological_ops.html?highlight=dilate#dilation)を使って[ツール](https://github.com/YoheiFukuhara/sdnet_image/blob/master/03.laplacian.py)を作りました。


##画像一覧
各画像は前処理でこんなになっています。全部、[GitHub](https://github.com/YoheiFukuhara/sdnet_image/tree/master/images/output)に入れています。

|No.|前処理|ひび割れありサンプル|ひび割れなしサンプル|
|:-:|:---|:-:|:-:|
|0|なし|![7001-2.jpg](https://qiita-image-store.s3.amazonaws.com/0/134273/87ae6284-29e6-3f6a-9fa9-0216fd60f70c.jpeg)|![7001-35.jpg](https://qiita-image-store.s3.amazonaws.com/0/134273/a03f7857-7472-11d4-1de6-845316ce4e39.jpeg)|
|1|白黒化|![image.png](https://qiita-image-store.s3.amazonaws.com/0/134273/45f7d864-7073-6eca-6bfe-24fd8a1c9d8d.png)|![image.png](https://qiita-image-store.s3.amazonaws.com/0/134273/38868d0a-39c7-2f86-c78f-4c02d9da6f3e.png)|
|2|白黒化して二値化|![image.png](https://qiita-image-store.s3.amazonaws.com/0/134273/2cc04fb2-811f-bb35-48a8-44dfe71060d4.png)|![image.png](https://qiita-image-store.s3.amazonaws.com/0/134273/8855d93d-5826-811e-e4a3-a7a25cf3b4c4.png)|
|3|白黒化、ラプラシアンフィルタ適用後に膨張|![image.png](https://qiita-image-store.s3.amazonaws.com/0/134273/d0d6c7a2-7e2d-da87-01b3-0c544173e4a4.png)|![image.png](https://qiita-image-store.s3.amazonaws.com/0/134273/5cef8024-7a1f-15f7-7b81-9c9de32414b7.png)|