10

バイナリ イメージの向きを見つけようとしています (ここで、向きは最小慣性モーメントの軸、つまり最小断面二次モーメントの軸として定義されます)。ここで参照として見つけることができるロボット ビジョンに関するホーン博士の本 (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); 

入力と出力の例を次に示します。

ここに画像の説明を入力 ここに画像の説明を入力

(縦長になると思います)

ここに画像の説明を入力 ここに画像の説明を入力

(横向きだと思います)

4

1 に答える 1

7

私はオリエンテーションを時々戻し、次のようにコーディングしました。オブジェクトの正確な向きを返します。maximum_contour は、検出された形状です。

CvMoments moments1,cenmoments1;
           double M00, M01, M10;

           cvMoments(largest_contour,&moments1);
           M00 = cvGetSpatialMoment(&moments1,0,0);
           M10 = cvGetSpatialMoment(&moments1,1,0);
           M01 = cvGetSpatialMoment(&moments1,0,1);
           posX_Yellow = (int)(M10/M00);
           posY_Yellow = (int)(M01/M00);

          double theta = 0.5 * atan(
                    (2 * cvGetCentralMoment(&moments1, 1, 1)) /
                    (cvGetCentralMoment(&moments1, 2, 0) -  cvGetCentralMoment(&moments1, 0, 2)));
                theta = (theta / PI) * 180;

                // fit an ellipse (and draw it)

                if (largest_contour->total >= 6) // can only do an ellipse fit
                                                 // if we have > 6 points
                {
                    CvBox2D box = cvFitEllipse2(largest_contour);
                    if ((box.size.width < imgYellowThresh->width) &&  (box.size.height < imgYellowThresh->height))
                    {

                        cvEllipseBox(imgYellowThresh, box, CV_RGB(255, 255 ,255), 3, 8, 0 );
                    }
                }
于 2013-02-06T02:56:23.877 に答える