質問: Point2f( mu.m10/mu.m00 , mu.m01/mu.m00 ); ``` を使ったと考えているのですが、正直以上のような解釈であっているかわかりません。 実行は出来ましたがちゃんとプログラムを理解したいと思い質問しました。 間違っていましたらどうかご指導お願いいたします。 載せましたプログラムで重心を求めた結果の画像を載せます。 一枚目はボールペンです。 ![イメージ説明](https://teratail-v2.storage.googleapis.com/uploads/contributed_images/532c924a5588c63622d890e0b5e75798.png) 二枚目はペットボトルです。 ![イメージ説明](https://teratail-v2.storage.googleapis.com/uploads/contributed_images/11c6127d9da67904565ac5f0429bbe08.png) 画像からの重心を求めたので正しいかどうかはわかりませんが、ボールペンに関してはあながち間違ってないように思えます。(実験しました。) 編集 処理を読んでいてもなぜ重心が求まるのか理解できません。 直球に言いますと、なぜ、あのプログラムから重心が得られるのか原理が知りたいです。 三角形や円なら数式を使えば重心を簡単に求められますが、歪なものなどは数式が立てにくく常に一定の形の物の重心を求める訳ではありません。 そのため、数式を使わずに、載せたプログラムだけで様々な形の物の重心が求まる理由が知りたいと思いました。
回答: > > contoursは検出した輪郭を保存する変数 > > > 若干複雑ですが間違いではありません。 `vector > contours;` ですので、`Point`型の可変長配列の可変長配列になります。 可変長配列ですので、それが何バイトの領域なのかは計算してみないと分かりませんし すべてが連続した領域という訳でもありません。(C言語での**ポインタの配列**みたいな感じ) ちなみに、findContoursのマニュアルによると、OutputArrayOfArrays型となっています。 cv::Matやstd::vector等をコンストラクタで変換する事で同様に扱えるようにしているらしいです。 > > 計算結果の値を代入して > > > まず、**代入**という用語について ある**特定の名前(ここではXとおく)を持つ**変数に値(とりあえず**Y**とする)を設定(もしくは変更)するときに, 「**X**に**Y**を**代入**する」と言います。 ご提示のソースでは、`contours`への設定ないしは変更は発生していないため、`contours`への代入は行われていません。 ``` for(int i=0; imax_size){ max_size=contours[i].size(); max_id=i; } } ``` ここで行われているのは、最大の頂点数を持つ輪郭がどれかを探しています。 結果、最大の頂点数を持つ輪郭は`contours[max_id]`になります。 > > 関数Momentsを使った。 > > > まず使う関数はmoments、小文字の方です。 それぞれのドットの輝度を**重さ**とみなし (グレイスケールなので1・・・らしい、適切な文献見つからず検証不十分) モーメント#.E7.94.BB.E5.83.8F.E3.81.AE.E3.83.A2.E3.83.BC.E3.83.A1.E3.83.B3.E3.83.88)を計算します。 高校物理の力のモーメントを抽象化した概念になります。 それぞれの点の**重さ**の総和がm00です。(重さが1ならば点の数になり、更に点が連続的であるならば面積になります。) それぞれの点の**重さ**にx座標を掛けた値の総和がm10 それぞれの点の**重さ**にy座標を掛けた値の総和がm01 になります。 モーメントを用いた重心の計算方法は公式化されていて それが、 `Xg = m10 / m00` `Yg = m01 / m00` なわけです。