バイナリ イメージの向きを見つけようとしています (ここで、向きは最小慣性モーメントの軸、つまり最小断面二次モーメントの軸として定義されます)。ここで参照として見つけることができるロボット ビジョンに関するホーン博士の本 (MIT) を使用しています。
ここで、a、b、および c は、上記の pdf の 15 ページ (テキストの 60 ページ) にある面積の 2 番目のモーメントです。
Point3d findCenterAndOrientation(const Mat& src)
{
Moments m = cv::moments(src, true);
double cen_x = m.m10/m.m00; //Centers are right
double cen_y = m.m01/m.m00;
double a = m.m20-m.m00*cen_x*cen_x;
double b = 2*m.m11-m.m00*(cen_x*cen_x+cen_y*cen_y);
double c = m.m02-m.m00*cen_y*cen_y;
double theta = a==c?0:atan2(b, a-c)/2.0;
return Point3d(cen_x, cen_y, theta);
}
OpenCV は原点 (0,0) の周りの 2 番目のモーメントを計算するので、平行軸定理を使用して軸を形状の中心 mr^2 に移動する必要があります。
コールするとセンターが正しく見える
Point3d p = findCenterAndOrientation(src);
rectangle(src, Point(p.x-1,p.y-1), Point(p.x+1, p.y+1), Scalar(0.25), 1);
しかし、この関数を使用して慣性モーメントが最小の軸を描画しようとすると、完全に間違っているように見えます。
line(src, (Point(p.x,p.y)-Point(100*cos(p.z), 100*sin(p.z))), (Point(p.x, p.y)+Point(100*cos(p.z), 100*sin(p.z))), Scalar(0.5), 1);
入力と出力の例を次に示します。
(縦長になると思います)
(横向きだと思います)