OpenCV, dlibなどでのカスケード分類器まとめ

## 概要



ライブラリ**face_recognition**　https://github.com/ageitgey/face_recognition
はipython notebook でのexample を用意しており、
https://beta.deepnote.com/project/96864ee5-2990-45ad-b44b-22ddc971fe43#%2Fexample.ipynb
ここからさわれる。
この例ではテスト画像としてObamaとBidenが隣どうしに写っている以下の画像が使われている。
![Screen Shot 2020-05-24 at 11.36.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/519792/b8ffd174-1513-4a94-a22d-c6fadb953008.png)


これらのモデルでは、後述のいくつかの機械学習モデルによって顔を検出したのち、
対象範囲の局所特徴量（後述）を抽出、学習データで個人ごとに抽出されている局所特徴量との
距離を判定することによって、テスト画像の中の顔が、「誰の」顔なのかを判定している。

コードを少し確認していたところ、
内部では**dlib**というC++のライブラリが実装している
**CNNモデル**、及び**深層学習ではないカスケード分類器**を使用していた。

そこで画像特徴抽出にOpenCVや今回のdlibで実装されている色々な特徴抽出方法
**カスケード分類器について今一度まとめてみた**。
深層学習モデルの方で扱われているモデルについては言及していないが、
基本的に顔の検出をする特徴量抽出を行うモデルと、検出された範囲を識別するモデルが連なっている場合が多い。

参考：
- https://www.slideshare.net/takashiabe338/fast-rcnnfaster-rcnn
- https://qiita.com/mdo4nt6n/items/68dcda71e90321574a2b   

## カスケード分類器　vs 深層学習モデル

ここ最近では、より精度の出る**深層学習であるCNNモデルなどがカスケード分類器にとって変わっている**。
しかしながら、CNNが学習しているのも、カスケード分類器が学習する画像の「着目したい特徴量」であるため、
カスケード分類器についても基礎として知っておいた方がいいだろう。

例えば以下は先述のdlib機械学習ライブラリを用いて、
対象画像の中の顔を検出する２つのモデルを試している。

- カスケード分類器の１つであるHOG特徴量抽出ーー＞SVMに流し込み顔かどうかの判定
- CNNベースで顔の検出をしたもの

の結果を比べている。


####dlibで実装されているカスケード分類器による顔検出の例。

![Screen Shot 2020-05-24 at 11.31.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/519792/9682c9ff-0f11-552d-c799-3d86433f0553.png)

####CNNモデルを用いた深層学習モデルによる顔検出の例。


![Screen Shot 2020-05-24 at 11.31.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/519792/42da04d9-445c-0255-9bd5-4f435c8848cf.png)

深層学習の方が基本的にはより精度の高い画像認識を行える。

>https://blog.chowagiken.co.jp/entry/2019/06/28/OpenCV%E3%81%A8dlib%E3%81%AE%E9%A1%94%E6%A4%9C%E5%87%BA%E6%A9%9F%E8%83%BD%E3%81%AE%E6%AF%94%E8%BC%83


## カスケード分類器

深層学習とは違い、予め決められた大量のパターンを色々なスケール学習画像に対して当てはめたり、
画像の輝度変化などを特徴として抽出する手法がある。



たとえばOpenCVではこの3種類から学習する特徴量を選択できる。

- **Haar-Like特徴量**
物体の局所的な**明暗差**の組み合わせにより、画像を判別する

- **LBP（Local Binary Pattern）特徴量**
物体の局所的な**輝度**の分布の組み合わせにより、画像を判別する

- **HOG（Histogram of Oriented Gradients）特徴量**
物体の局所的な**輝度の勾配方向**の分布の組み合わせにより、画像を判別する


## Haar-Like

**Haar-Like特徴**
は、**画像の明暗差により特徴を捉える**。

画像の一部分を切り出し、局所的な明暗差を算出する。
この局所的な特徴をいくつも組み合わせることで、物体を判別できるようになる。


### 例
ここからOpenCVがHaar-Like特徴を使って顔を検出する動画をみることができる。
https://vimeo.com/12774628


https://www.slideshare.net/MPRG_Chubu_University/ss-32258845
このスライドシェアの20ページ目くらいまでをみると非常に分かりやすい。

![Screen Shot 2020-05-24 at 11.47.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/519792/d9951dad-62e9-74ec-e4b4-45c85b48e6c5.png)
![Screen Shot 2020-05-24 at 11.48.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/519792/b9a8ad74-3b01-7cad-370c-e60a596b7a7b.png)
![Screen Shot 2020-05-24 at 11.48.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/519792/4adc3e9f-4492-d365-f018-952b32866c2c.png)
![Screen Shot 2020-05-24 at 11.48.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/519792/dec3d33b-2366-fc58-5932-0cc61fa549ff.png)


### アルゴリズム
アルゴリズムは以下となる。
①Haar-like特徴に用いるパターンを複数用意する。


②入力画像の任意の位置に探索窓を配置する。

③探索窓の任意の位置に矩形領域を配置する。

④矩形領域に任意のパターンを設定する。

⑤パターンの黒領域、白領域それぞれの画素値の和の平均A_1, A_2を求める。
そして、それらの差の特徴量Hを求める。

⑥矩形領域の位置・サイズ・パターンを変えて⑤の計算を繰り返す。

⑦検索窓の位置を変えて②～⑥を繰り返す。

つまり、考えられるパターンをたくさん用意し、たくさんの検索窓で所望の局所特徴量が抽出できるかをたくさん試している。

> https://algorithm.joho.info/image-processing/haar-like-feature-value/


## LBP(Local Binary Pattern)

**LBP(Local Binary Pattern)**
は1994年に発表された画像特徴量で、
中心画素と周辺画素の画素値の関係性を元に算出される特徴量のこと。
LBPは，原理的にはスケーリングや回転などの幾何学的な変動に頑強ではないが，
輝度変動に頑強で高速に計算できる特徴量として広く引用されている。

さらに識別精度を改善するため，回転変動への対応や他の特徴量との組み合わせなどの工夫が多数提案されている。


ある注目画素に関し、周辺8画素が注目画素よりも輝度値が大きいか小さいかを元に0、1で示しす。この周辺8画素を使い、0 or 1が8bit分(1byte)で表現する。

>http://tecsingularity.com/opencv/lbp/

こちらが非常にわかりやすかった。
![Screen Shot 2020-05-24 at 11.18.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/519792/36410c4b-a59f-3e92-36ff-8514884d3d01.png)
![Screen Shot 2020-05-24 at 11.17.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/519792/7a49bbc4-5847-d399-7dc5-536f5a663b39.png)
![Screen Shot 2020-05-24 at 11.17.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/519792/a034573f-e268-3440-c8a2-f235e4a88dac.png)

>http://compsci.world.coocan.jp/OUJ/2012PR/pr_15_a.pdf



### 例
上記のように、対象画像のある範囲のなかで着目しているピクセルの周辺ピクセルが、
着目ピクセルの値より大きいか小さいかでバイナリをつくるのでとても単純である。

![Screen Shot 2020-05-24 at 10.53.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/519792/7b37620c-fefd-6d81-a3d5-0c3c7eca6871.png)

>https://www.pro-s.co.jp/blog/system/opencv/6256



## HOG（Histogram of Oriented Gradients）



**HOG（Histogram of Oriented Gradients）**
は2005年に発表されてから、人や車両などを検出するのに一定の精度が認められている。
グレイスケール画像における輝度の勾配を角度ごとにヒストグラム化したものであり，物体の形状を捉え
るのに有効な特徴量である．HOG 特徴量の取得には，まず入力画像をグレイスケール化し，各ピクセルの勾配方向と強度を算出する．その後，セル（5 × 5 ピクセル）ごとに輝度の勾配ヒストグラムを作成して，ブロック（2 ×2 セル） ごとに正規化する．これを順に連結したものを特徴量とする．

>https://www.ieice.org/publications/conference-FIT-DVDs/FIT2017/data/pdf/H-032.pdf

画像からの人体・車両検出には、この特徴量をSVM(Support Vector Machine)で分類する手法がメジャーであった。
また、勾配を特徴量としているため、画像スケールに対してロバストであるという優れた特徴がある。






この図解が分かりやすい。


![Screen Shot 2020-05-24 at 11.12.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/519792/83dc3e02-4d8d-b57d-7dfd-d4a77f615b64.png)

> https://www.ite.or.jp/contents/keywords/FILE-20160413114344.pdf


### 例

![Screen Shot 2020-05-24 at 11.02.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/519792/889cbe72-8901-3fd2-40de-68362f76d4f9.png)
上の二枚の画像は実際に自動車の画像からHOG特徴量を取り出したもので、
一枚目の画像からHOG特徴量を計算し、二枚目に可視化している。うっすらとだが二枚目に車体の輪郭が確認できる。
また車体の塗装の境界に強く反応していることがわかる。

>http://96n.hatenablog.com/entry/2016/01/23/100311

### アルゴリズム
① 入力画像を複数のブロックに分割。
また、各ブロックをセルに分割する。

![Screen Shot 2020-05-24 at 10.57.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/519792/42d0faa1-decb-a741-04d7-b1f4804d0cc5.png)


② 入力画像Iを微分する。
![Screen Shot 2020-05-24 at 10.58.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/519792/a91c73e4-eb83-930e-e233-55f8f7d18e23.png)

③ 微分画像から勾配強度|I|と勾配方向thetaを求める。
![Screen Shot 2020-05-24 at 10.58.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/519792/7486c16b-07db-4478-a8f4-a8f2fba3d281.png)

④ 勾配方向を9方向（0～180度まで20度ずつ）に量子化する。

⑤ セル毎に強度で重みを付けて勾配方向ヒストグラムを計算する。

⑥ ブロック毎に正規化し、特徴量を計算する。
![Screen Shot 2020-05-24 at 10.58.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/519792/5c8c31dc-6c57-94d0-a45f-453ade2458cd.png)

h(n)はn番目の勾配方向ヒストグラム。
分母Hは1ブロックのHOG特徴量の総和で次式で計算する。
![Screen Shot 2020-05-24 at 10.58.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/519792/8abfa218-33b2-3e49-2288-b01a0ec91e7e.png)


>https://algorithm.joho.info/image-processing/hog-feature-value/



### まとめ

dlibやOpenCVが実装しているカスケード分類器とよばれる、

- **Haar-Like特徴量**
物体の局所的な**明暗差**の組み合わせにより、画像を判別する

- **LBP（Local Binary Pattern）特徴量**
物体の局所的な**輝度**の分布の組み合わせにより、画像を判別する

- **HOG（Histogram of Oriented Gradients）特徴量**
物体の局所的な**輝度の勾配方向**の分布の組み合わせにより、画像を判別する

上記の３つの特徴量について今一度調べてみた。





## 参考文献

#### Haar
https://www.slideshare.net/MPRG_Chubu_University/ss-32258845

#### LBP
http://compsci.world.coocan.jp/OUJ/2012PR/pr_15_a.pdf
https://global.pioneer/en/crdl_design/crdl/rd/pdf/2017-2.pdf

#### HOG
https://www.pro-s.co.jp/blog/system/opencv/6202
http://96n.hatenablog.com/entry/2016/01/23/100311
https://algorithm.joho.info/image-processing/hog-feature-value/
https://ikatakos.com/pot/programming/python/packages/scikit-image/hog
https://www.ite.or.jp/contents/keywords/FILE-20160413114344.pdf