顔向き推定について調査中

Intel のデバイスを使う範囲だと、次の記事が紹介しているようにOpenVinoで顔向き推定ができます。

### qiita [AIを始めよう！OpenVINOで使うモデルを整備する](https://qiita.com/ammo0613/items/d9463d11741f1bc5d2e2)

head-pos-estimation-adas-0001.xml のモデルデータを利用する。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/83761/6b82ab29-cf29-607e-d63b-78d4ff43ff9b.png)


### github  opencv /open_model_zoo [head-pose-estimation-adas-0001](https://github.com/opencv/open_model_zoo/blob/master/models/intel/head-pose-estimation-adas-0001/description/head-pose-estimation-adas-0001.md)

私見：顔向き推定は、顔の検出位置の正規化・顔ランドマークの検出に依存します。
ですから、よく使われる顔検出の正規化・顔ランドマークの検出にしたがった、顔向き推定を用いることです。
顔の属性推定や顔照合も、同様です。同一の枠組みを使うことが、全体としての処理のパフォーマンスを上げることにつながります。


---

dlibのlandmark を使うなどで、顔向き推定をしている記事やweb上のソースコードについて調査中です。
顔向き推定には、Perspective-n-Point algorithmのものとConvolutional Neural Networksによるものとを見つけています。

自分の目的に利用するためには、
顔向き推定がクラスベースの実装のなるようになどして、関連する処理が１つのクラスにまとめるのがよいと思います。


## 実装例１：回転行列を使う顔向き推定（使用するライブラリ、OpenCV, dlib）

- [Head Pose Estimation using OpenCV and Dlib](https://www.learnopencv.com/head-pose-estimation-using-opencv-and-dlib/)
    - ![head-pose-example-1024x576](https://www.learnopencv.com/wp-content/uploads/2016/09/head-pose-example-1024x576.jpg)
    - ソースコードは"Download Code (C++ / Python)" を選択して、作者のページからメールを受け取ります。
    - dlib のlandmark [OpenCVで顔向き推定を行う](https://qiita.com/TaroYamada/items/e3f3d0ea4ecc0a832fac)
    - この記事は上記の記事に対する解説記事です。pitch, yaw, roll の角度を求める部分の追加実装のしかたを書いてあります。
    - この実装は顔器官点の座標を元に回転行列の値を推定することで顔の向きを推定するものです。
    - web記事そのものの中では、顔器官点の２Ｄの座標を求める部分が書かれていません。dlibを使って顔器官点を求めるように書きなおす必要があります。以下の記事が参考になります。
        - https://www.pyimagesearch.com/2017/04/17/real-time-facial-landmark-detection-opencv-python-dlib/
        - 68点のlandmark は次のような点です。
        - https://www.pyimagesearch.com/2017/04/03/facial-landmarks-dlib-opencv-python/
    - 用いられている数学については以下のOpenCVのチュートリアルが参考になります。 http://labs.eecs.tottori-u.ac.jp/sd/Member/oyamada/OpenCV/html/py_tutorials/py_calib3d/py_pose/py_pose.html
    - http://planning.cs.uiuc.edu/node102.html
    - http://planning.cs.uiuc.edu/node103.html

## 実装例：回転行列に基づく方法（使用するライブラリ、OpenCV, dlib）
- [attention-tracker](https://github.com/chili-epfl/attention-tracker)

```
$ cmake -DDLIB_PATH=<path to dlib> ..
```
を入力する際の`<path to dlib>`には`git clone https://github.com/davisking/dlib.git` で作成されたディレクトリを指定すればcmake, make が実行できました。

```
$ ./head_pose_test ../share/shape_predictor_68_face_landmarks.dat
```
とすればよいようです。入力はUSBカメラが使われます。



```
$ ./head_pose_single_frame ../share/shape_predictor_68_face_landmarks.dat input.jpg
```

こちらは静止画を入力とするものです。

いずれもC++のライブラリを使うプログラムになっています。




- [gazr](https://github.com/severin-lemaignan/gazr)
 これも顔器官点から回転行列を求めて、顔向き推定をするものです。


## 実装例  (使用するライブラリ、OpenCV and dlib)
[https://github.com/lincolnhard/head-pose-estimationn](https://github.com/lincolnhard/head-pose-estimation)
![](https://cloud.githubusercontent.com/assets/16308037/24230147/79bf1c68-0fb8-11e7-859b-8482f9b559a5.gif)

これもdlibの顔器官点を使って、回転行列を求めている実装です。
solvepnp
 

## 実装例２：顔器官点を元にSVMで学習する顔向き推定（使用するライブラリ、OpenCV, dlib, scikit-learn）

- [機械学習で顔の向きを取得する【scikit-learn】 ](https://sukohi.blogspot.jp/2017/03/scikit-learn-head-pose-estimation.html)

顔器官点のデータを使ってSVMで学習しています。
SVMはscikit-learnを使っています。

```
 clf = svm.SVC()  
 clf.fit(train_angles, train_labels) # 取得したデータで機械学習する  
```

## 実装例３：顔器官点を元にDNNで学習する顔向き推定（使用するライブラリ, dlib, caffe)

- [https://github.com/guozhongluo/head-pose-estimation-and-face-landmark](https://github.com/guozhongluo/head-pose-estimation-and-face-landmark)


![guozhongluo](https://raw.githubusercontent.com/guozhongluo/head-pose-estimation-and-face-landmark/master/result/1.png)

- 本家のリポジトリにforked_versionからPRが反映されています。
- python2.x　を想定したものになっています。
- たとえばprintは関数ではなくて文になっています。
- requirement.txt　の記載がないので、インストールが若干面倒です。

- forked version: https://github.com/KatsunoriWa/head-pose-estimation-and-face-landmark
    - dlib の顔検出、深層学習を利用して顔向きを推定。
    - model ファイルをダウンロードする。　68point_dlib_with_pose.caffemodel  VGG_mean.binaryproto
    - 以下のコマンドを実行。
    - $ python landmarkPredict.py predictImage testList.txt
    - $ python python landmarkPredict_video.py 0
    - FacePosePredictor class を導入して、再利用性を向上している。


オリジナルのguozhongluoのgit版で以下のエラーがでるときには、リストの添字が整数になるように修正を加えてください。

```
Traceback (most recent call last):
  File "landmarkPredict.py", line 239, in <module>
    func(*sys.argv[2:])
  File "landmarkPredict.py", line 208, in predictImage
    colorface = getRGBTestPart(bbox,M_left,M_right,M_top,M_bottom,colorImage,vgg_height,vgg_width)
  File "landmarkPredict.py", line 83, in getRGBTestPart
    face=img[retiBBox[2]:retiBBox[3],retiBBox[0]:retiBBox[1],:]
TypeError: slice indices must be integers or None or have an __index__ method
```

というエラーが出るときには、

```
    # cv2.waitKey(0)
+    retiBBox = [int(round(x)) for x in retiBBox]
    face=img[retiBBox[2]:retiBBox[3],retiBBox[0]:retiBBox[1],:]
```

の行を追加してみてください。


## 実装例：顔器官点を元にDNNで学習する顔向き推定（使用するライブラリ, TensorFlow 1.4, OpenCV 3.3, Python 3)
これもDNNベースの顔向き推定。

https://github.com/yinguobing/head-pose-estimation

![yinguobing](https://raw.githubusercontent.com/yinguobing/head-pose-estimation/master/demo.gif)

```
$ python estimate_head_pose.py
```



## 実装例：3種類の実装（OpenCV, tensorflow, dlib）

- https://github.com/mpatacchiola/deepgaze
    - https://github.com/mpatacchiola/deepgaze/blob/master/examples/ex_dlib_pnp_head_pose_estimation_video.py
    - YouTube [Head Pose Estimation in-the-wild with OpenCV and dlib (Python)](https://www.youtube.com/watch?v=xurEs0G9ARs)
    - 上記のコードの実行結果の例


```
$ python examples/ex_pnp_head_pose_estimation_webcam.py 
```

接続されたカメラから顔を検出し、head pose を３本の矢印で表示します。
その矢印の示す向きがいまいち安定していないような感じでした。
顔特徴点の抽出が安定していないのかもしれません。



また、ライブラリが書かれたときとOpenCVのpythonバインディングの実装が変化していたりするので、
   fourcc = cv2.cv.CV_FOURCC(*'XVID')
AttributeError: 'module' object has no attribute 'cv'
といったエラーを生じるかもしれません。
その場合には、次のように変更すると動作します。

```
-            fourcc = cv2.cv.CV_FOURCC(*'XVID')
+            fourcc = cv2.VideoWriter_fourcc(*'XVID')
```


```
$ python examples/ex_dlib_pnp_head_pose_estimation_video.py
You have to pass as argument the path to a video file and the path to the output file to produce, for example: 
 python ex_pnp_pose_estimation_video.py /home/video.mpg ./output.avi
$ 

$ python ex_cnn_head_pose_estimation_images.py
[DEEPGAZE] head_pose_estimation.py: the dlib library is installed.
Processing image ..... 1.jpg
Estimated [roll, pitch, yaw] ..... [-8.12711,-6.83478,7.2062]

Processing image ..... 2.jpg
Estimated [roll, pitch, yaw] ..... [-1.76577,-1.88228,54.2908]

Processing image ..... 3.jpg
Estimated [roll, pitch, yaw] ..... [-1.35001,-23.0703,-21.7094]

Processing image ..... 4.jpg
Estimated [roll, pitch, yaw] ..... [-3.89467,-12.0814,-53.7645]

Processing image ..... 5.jpg
Estimated [roll, pitch, yaw] ..... [0.411899,-1.7321,43.6103]

Processing image ..... 6.jpg
Estimated [roll, pitch, yaw] ..... [0.585647,-11.2426,-42.9941]

Processing image ..... 7.jpg
Estimated [roll, pitch, yaw] ..... [0.693526,-7.47962,-46.7058]

Processing image ..... 8.jpg
Estimated [roll, pitch, yaw] ..... [-1.19849,-8.18166,-24.7768]

$
```


## StackOverflow [How to get 3D coordinate Axes of head pose estimation in Dlib C++](https://stackoverflow.com/questions/36590516/how-to-get-3d-coordinate-axes-of-head-pose-estimation-in-dlib-c)


顔向きによって検出器の性能がどのように違ってくるのかは
次のデータベースを使うことができます。

さらには、同一人物として照合可能な範囲がどの顔向きの範囲なのかを知るのに用いることもできるでしょう。

[Head Pose Image Database](http://www-prima.inrialpes.fr/perso/Gourier/Faces/HPDatabase.html)

![Head Pose Image Database](http://www-prima.inrialpes.fr/perso/Gourier/Faces/sampleLabels.jpg)

------
### [OpenFace](https://github.com/TadasBaltrusaitis/OpenFace)
C++による実装
これもdlibの顔器官点を使っているようだ。
以下の記事の中では、顔向き推定を持つライブラリの比較が引用されている。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/83761/981b0fd1-6ce7-36b0-9944-52609b8546b0.png)

[OpenFace](https://github.com/TadasBaltrusaitis/OpenFace)中のリンクをたどると、動作例のYoutube動画にたどり着く。

- Qiita [OpenFace について調査中](https://qiita.com/nonbiri15/items/d9be1bd4baeaa2e8ab61)


商用の場合は、コンタクトをとること。
innovation@cmu.edu

----
付記：
ここに示している実装の多くは、検出された顔に対して、次のステップで顔向き推定をするものになっています。
Deep Learning では１つのネットワークで、顔検出と同時に顔向き推定が可能であるとのことです。
その利点は、計算量の増加を抑えることができることが期待されます。


最近では、顔検出の商用ライブラリでもDeep Learning ベースの顔検出が増えてきていると聞いています。



## 追加
### MATLABによる実装

https://team.inria.fr/perception/research/head-pose/

https://github.com/TadasBaltrusaitis/OpenFace/tree/master/matlab_version

https://github.com/TadasBaltrusaitis/CLM-framework/tree/master/matlab_runners/Head%20Pose%20Experiments


### Head detector
http://www.robots.ox.ac.uk/~vgg/software/headmview/

顔向きの推定を欲しがっている人は、その顔の人物がカメラ側を見ているのかどうか知りたくなることでしょう。
次の記事は有益でしょう。

[OpenFace+機械学習で視線検知](https://qiita.com/29Takuya/items/5c95b2a1fa42975305c9)

----
## 付記 mediapipe による実装
mediapipeは、以下のdemoをweb上で動作させることができます。
顔検出だけではなく、顔のlandmark の検出もできます。

https://mediapipe-studio.webapps.google.com/home

それだけできるのだから、head　poseも出してもらえるとうれしいのに

### [Real Time Driver State Detection](https://github.com/e-candeloro/Driver-State-Detection)
Mediapipe を用いた顔向き推定も含むReal Time Driver State Detectionです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/83761/95c3c54b-dedd-d231-52bb-561522d08e91.png)

リンク先のリポジトリに動画がありますので、それを見ると実装されている内容がわかります。

----
未調査
https://github.com/nullbyte91/head-pose-estimation


# 追記
## 市販ライブラリの場合には、既に顔向き推定も含まれていることが多い。
- [FaceMe 顔向き推定あり](https://jp.cyberlink.com/faceme/sdk/overview)
- [PUX FaceU 顔ライブラリ　顔向き推定あり](https://www.pux.co.jp/%E3%83%86%E3%82%AF%E3%83%8E%E3%83%AD%E3%82%B8%E3%83%BC/)