OpenCVやDlibを使ってみて、人の顔の動画を処理することをやっています。
ここでは、これまでに失敗した点を、いくつか残しておきます。Qiitaをはじめ、画像処理関係でいろいろ検索すると、OpenCVのこれこれが使えるよという投稿が多いです。が、実際に使い込んでみたら結局使えなかったという情報も、役立つと思うので。
-
顔の特徴点を得るのに、DlibのLandmark68が有名ですが、これは顔の上半分が全然使えません。DlibのLandmarkは、西洋人のデータでTrainingされていて、東洋人の目周辺のLandmarkの質が低いです(2018.10.30更新->東洋人のデータも使ってTrainingするかとDlibの作者のDavid Kingが書いてました、そのうち解決される)。また、眼鏡をかけていると、目と眼鏡をよく取り違える。目回りのFeature Point検出は、自力で書くか、自分でDlibでTrainingしなおすかです。ちなみに、OpenCVのHaarカスケードの目検出は精度が高く枠が安定してとれますが、点はわからない。
-
DlibのLandmarkは、フレームごとに揺れます。安定した位置を得たいときは、Kalmanフィルターを通すなどの工夫が必要です。特徴点を中心としたTracking Boxを使う方法でもいいのですが、Tracking Boxは遅い。スカラー値のKalmanフィルターは高速です。【揺れる値をおとなしくさせるには、カルマンフィルターが便利で高速】に、スカラー値のカルマンフィルターのコードを載せておきます。
-
顔向きを得る方法の紹介が何個も出ています。顔のLandmarkから、SolvePnPRansacなどで、顔座標系とカメラの座標系とのTranslation/Rotation関係であるFacePoseが得られます。ここで、FacePoseの計算には、顔3Dモデルが必要です。しかし、公開されている顔モデルのSampleはそのままでは使い物になりません。FacePoseはピクセル単位の計算であるため、人の顔モデルが実際の被写体のそれと数ピクセルでも異なれば、大きな狂いが生じたり、FacePose方向ベクトルが激しく揺れます。まず、被写体の顔の3Dモデルの獲得が前提です。そこをクリアしないと、FacePoseは活用できません。【顔モデルの取得の処理概要をここに残しておきます。】
-
OpenCVのCannyやHoughCircle等が物体のEdge形状の検出に使えるという記事が山ほどあります。が、これらは人工物にあるような幾何的な形状だと機能しますが、人の顔のパーツなど自然の物体には、使いものになりません。自分は、これらが何とか使えないか、試行錯誤にずいぶん時間を浪費してしまった。みなさんは、時間を節約してください。
-
光の条件に左右されない画像処理という検索で、引っかかるのはEdgeを使え系が多いです。また引っかかるものはAcademic Paperが多く、現場の実用的な場面ではどういう工夫をしているのかわかりません。きっと、高価な光学センサーを使うとかしてしまうのでしょうか。安価なカメラでやりたいとき、光の条件に左右されにくいように、grayに対して、OpenCVで身近にあるcv2.equalizeHistしてから、EdgeをとるとかBinarizeするとかしたくなります。が、これらはあまりうまくいきません。まず、cv2.equalizeHistはGradientを壊します。そのため、画像が汚くなります。また、光の条件の影響をもろに受けるBinarizeでなく、Edgeで攻めようとしても、結局Edgeも明暗環境に多分に左右され、結果が安定しません。しかし、ヒストグラムをstretchし(Intensityのmin/maxを0と255に広げるように変換する)Blurすると、全体的な明暗に関係なく、きれいな画像が得られます。そのあとでEdgeやGradientをとるのがいいです。min、maxを適当に設定しなおしたり、Intensityの変換式のところでSQRTを3回かければ暗いほうがより詳細化されますし、POW3回かければ明るい方がと、Damageを小さくしていろいろ加工できます。【暗い画像を鮮明にするStretch】に、コードを置いておきます。