現在OpenCV2.1を用いた上で顔検出にチャレンジしています。
学習等については問題なく行うことができ、顔の検出を行おうと思っているのですが、検出の段階で設定するパラメータの"minNeighbors"と"scaleFactor"の各値について疑問がわきました.
・minNeighborsについて
物体候補領域が何個以上重なっていたらそれを一つの物体として検出するといったイメージだと思ったのですが、実際にどの程度候補領域が重なっていたら重なりと定義されているのかという点が分かりません。またその重なりの程度のパラメータ等もございましたらそのパラメータ設定の場所も含めお教えいただければと思います。
・scaleFactorについて
色々とインターネットを見たのですが,「各画像スケールにおける縮小量」とだけ書かれておりよく意味が理解できませんでしたので、その意味について教えて頂きたいです。
以上となります。どなたかご存知の方、ご教授頂ければとおもいます。宜しくお願い致します。
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
回答1件
0
ベストアンサー
まず、それぞれの言葉の意味について回答します。
- minNeighborsについて
『物体候補領域が何個以上重なっていたらそれを一つの物体として検出する』というイメージで大体あっていると思います。その重なり具合を指定するパラメータは存在します。詳しくは後述します。
- scaleFactorについて
OpenCVのカスケード分類器は、Sliding Windowという技法を使って候補となる矩形を検出しています。この動画は、われらがマドンナ・レナ姐さんの画像にSliding Windowを適用しているものです。文字通り、窓を滑らせて片端から候補を見つけ出しているんですが、一巡毎にこの窓枠は縮小します。この縮小率がscaleFactorです。(たまにscaleFactorを1.0にして困っている人を見ます。)
次に、「どの程度候補領域が重なっていたら重なりと定義されているか」という点について考えていきたいと思います。私もちょっと気になったもので、今回調べてみました。
- detectMultiScale(コード)が、Sliding Windowとカスケード分類で候補となる矩形のvectorを作る。
- 上記によって得られたvectorが、groupRectangle(コード)に
rectList
として渡される。また、minNeighbors
は、同時にgroupThreshold
として渡される。 - groupRectangleは、内部でpartition(コード)を呼び出す。partitionはクラスタリングを行うOpenCVの汎用関数で、第一引数にクラスタリング対象となるvectorを渡すと、第二引数にクラス番号のvectorを代入してくれる。もちろん、第一引数には
rectList
が渡される。
ここで、partitionがむにゃむにゃとクラスタリングを行って、その結果を返すことがわかりましたね。その結果をもとに、groupThreshold
ことminNeighbors
を用いて、**『充分な回数検出されている領域か?』**という判別が出来ます。
さて、次の問題は、partitionがどうクラスタリングを行っているかどうかですね。コードを見てみると、どうやら矩形の全通りを比較しているようです。比較して、**『どうやら同じクラスらしい』**と判別するための基準は、partitionの第三引数として与えられるようです。
partitionは、groupRectangle内から、次のように呼び出されます。
C++
1partition(rectList, labels, SimilarRects(eps));
と、いうわけで、SimilarRects(コード)に矩形の同一性の判断が任されていることがわかります。それでは、SimilarRectsのコードを見てみましょう。
C++
1class CV_EXPORTS SimilarRects 2{ 3public: 4 SimilarRects(double _eps) : eps(_eps) {} 5 inline bool operator()(const Rect& r1, const Rect& r2) const 6 { 7 double delta = eps * ((std::min)(r1.width, r2.width) + (std::min)(r1.height, r2.height)) * 0.5; 8 return std::abs(r1.x - r2.x) <= delta && 9 std::abs(r1.y - r2.y) <= delta && 10 std::abs(r1.x + r1.width - r2.x - r2.width) <= delta && 11 std::abs(r1.y + r1.height - r2.y - r2.height) <= delta; 12 } 13 double eps; 14};
まさにoperator()
の部分が、二つの矩形を引数にとって、それらの同一性を判断しているんですね。たった二文しかないですし、さっそくコードを読み解いてみましょう。
一文目: eps
の値を基準に、判断指標delta
を決定しています。
二文目: 全ての辺の距離がdelta
より小さいとき、同一としてtrueを返します。
さて、最後の話題です。
またその重なりの程度のパラメータ等もございましたらそのパラメータ設定の場所も含めお教えいただければと思います。
partition内で判断基準として用いられたdelta
は、第三引数eps
に比例して決定されました。また、この値は、もともとgroupRactangleの第三引数eps
として与えられたもので、次のように、デフォルト値は0.2となっています。
C++
1void groupRectangles(vector<Rect>& rectList, int groupThreshold, double eps=0.2);
ですので、groupRectanglesを自ら呼び出すようなコードを書けば、パラメータeps
を指定できることになります。次のようにして、実際に実行することが出来ました。(ただし、再現環境はOpenCV3)
C++
1cascade.detectMultiScale(smallImg, faces, 2 1.1, // scaleFactor 3 0, // minNeighbors(仮) 4 CV_HAAR_SCALE_IMAGE, 5 cv::Size(30, 30)); 6// 以下の値は自由 7int groupThreshold = 3; 8double eps = 0.5; 9cv::groupRectangles(faces, gourpThreshold, eps);
Python
1facerect = cascade.detectMultiScale(image_gray, scaleFactor=1.04, minNeighbors=0, minSize=(80, 80), maxSize=(200, 200)) 2facerect, _ = cv2.groupRectangles(np.array(facerect).tolist(), groupThreshold=3, eps=0.5)
こちらを参考にしました。事前にimport numpy as np
するのを忘れずに。
Githubのコードを舐め回して、ようやくここまでわかりました... 私自身もいい勉強になりました。
投稿2017/07/19 17:56
編集2017/07/21 04:34総合スコア35660
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
退会済みユーザー
2017/07/20 08:07
2017/07/20 08:09
2017/07/20 08:09
退会済みユーザー
2017/08/18 10:08 編集
退会済みユーザー
2017/08/18 10:01 編集
2017/07/20 08:54
2017/07/20 08:54
2017/07/20 09:12
退会済みユーザー
2017/08/18 10:07 編集
退会済みユーザー
2017/08/18 10:02 編集
2017/07/20 09:22
2017/07/20 09:24
退会済みユーザー
2017/08/18 10:07 編集
2017/07/20 09:37
2017/07/20 09:45
2017/07/20 09:47
退会済みユーザー
2017/07/20 09:58
2017/07/20 10:02
退会済みユーザー
2017/07/20 10:14
退会済みユーザー
2017/08/18 10:07 編集
退会済みユーザー
2017/07/20 10:16
2017/07/20 10:29
退会済みユーザー
2017/08/18 10:07 編集
退会済みユーザー
2017/07/20 10:38
2017/07/20 10:43
2017/07/20 10:49
2017/07/20 10:55
退会済みユーザー
2017/07/20 10:56
退会済みユーザー
2017/08/18 10:07 編集
2017/07/20 11:01
退会済みユーザー
2017/07/20 11:04
退会済みユーザー
2017/07/20 11:04
2017/07/20 11:07
退会済みユーザー
2017/07/20 11:11
退会済みユーザー
2017/07/21 01:50
退会済みユーザー
2017/08/18 10:08 編集
2017/07/21 04:33
退会済みユーザー
2017/07/21 05:51
2017/09/03 17:54