2

OpenCV 2.3.1 で輪郭の Delaunay 三角形分割をうまく実装しました。

cvPointPolygonTest を使用すると、凸包内のすべての三角形を取得できます。次に、三角形の重心に対して別の cvPointPolygonTest を実行して、それらが主な輪郭にあるかどうかを確認しようとしたため、輪郭の三角形分割を制限できます。

しかし、一部の三角形は (たとえば、2 本の足を離して歩いている人では)穴の上にあるため、うまく機能しません。

制約付き三角形分割を実行する方法を知っている人はいますか? 私は凸性欠陥について考えましたが、これから始める方法を理解することができません。

前もって感謝します !

ベン


実際、これは凸包欠陥の問題ではなく、三角測量の問題です。この画像はあなたの問題を示します:

特に三角形分割されたハルの下部では、OpenCV が凸包を三角形分割しているため、三角形分割が輪郭の内側と外側にあることがわかります。輪郭自体を三角測量する方法を見つけたいと思います。

輪郭自体に Steiner Points を追加することについていくつかのアイデアを見つけましたが、OpenCV をどこから始めればよいかわかりません。

私の考えは次のとおりでした:

  • 三角形が輪郭の内側と外側にあるかどうかをテストします。
  • true の場合: 交点を取得します。
  • cvSubdiv2D に追加します。

私はこれで正しいですか?

あなたの忍耐とあなたの答えに感謝します!

4

2 に答える 2

2

最後に、プログラムにpoly2triライブラリを実装しました。

結果は次のとおりです(OpenCVで輪郭を取得し、poly2triで三角測量を実行します):

// -------------------- poly2tri --------------------


NSMutableArray* temp = [[NSMutableArray alloc] init];

vector<p2t::Triangle*> triangles;
vector< vector<p2t::Point*> > polylines;
vector<p2t::Point*> polyline;

for(int i = 0; i < contour32->total; i++ ) {
    CvPoint2D32f* pt32 = CV_GET_SEQ_ELEM(CvPoint2D32f, contour32, i);
    polyline.push_back(new p2t::Point((double)pt32->x, (double)pt32->y));
}

polylines.push_back(polyline);


p2t::CDT* cdt = new p2t::CDT(polyline);



// TODO -> holes with CV_RETR_TREE

// Triangulation !
cdt->Triangulate();

// On exporte nos triangles
triangles = cdt->GetTriangles();

for (int i = 0; i < triangles.size(); i++) {

    p2t::Triangle& t = *triangles[i];
    p2t::Point& a = *t.GetPoint(0);
    p2t::Point& b = *t.GetPoint(1);
    p2t::Point& c = *t.GetPoint(2);

    double x1 = (width / rWidth * (double)a.x) - (width / 2.f);
    double y1 = (height / rHeight * (double)a.y) - (height / 2.f);                   
    double x2 = (width / rWidth * (double)b.x) - (width / 2.f);
    double y2 = (height / rHeight * (double)b.y) - (height / 2.f);
    double x3 = (width / rWidth * (double)c.x) - (width / 2.f);
    double y3 = (height / rHeight * (double)c.y) - (height / 2.f);

    [temp addObject:[[NSArray arrayWithObjects:
                      [NSArray arrayWithObjects:
                       [NSNumber numberWithDouble:x1],
                       [NSNumber numberWithDouble:y1],
                       [NSNumber numberWithDouble:0.],
                       nil], 
                      [NSArray arrayWithObjects:
                       [NSNumber numberWithDouble:x2],
                       [NSNumber numberWithDouble:y2],
                       [NSNumber numberWithDouble:0.],
                       nil], 
                      [NSArray arrayWithObjects:
                       [NSNumber numberWithDouble:x3],
                       [NSNumber numberWithDouble:y3],
                       [NSNumber numberWithDouble:0.],
                       nil], 
                      nil] autorelease]];

}

[outDelaunay addObject:temp];                       

ここで、contour32は、cvFindContoursで検出されてfloat32に変換されたOpenCV輪郭です。

于 2011-11-30T13:32:35.427 に答える
1

以下を使用する必要があります。

    CvSeq* cvConvexityDefects(
const CvArr* contour,
const CvArr* convexhull,
CvMemStorage* storage = NULL
);

CvConvexityDefectこれは、CvPoint や、おそらく慣れている CvSeq のようなものではなく、シーケンス (CvSeq) を返します。

次のように、ループ内の欠陥を調べることができます。

CvSeq* defects =  cvConvexityDefects(.....);
for (i = 0; i < defects->total; i++)
{
CvConvexityDefect* def = (CvConvexityDefect*)cvGetSeqElem(defects, i);
//do something with them
}

欠陥には次の構造があります。

    typedef struct CvConvexityDefect {
// point of the contour where the defect begins
CvPoint* start;
// point of the contour where the defect ends
CvPoint* end;
// point within the defect farthest from the convex hull
CvPoint* depth_point;
// distance between the farthest point and the convex hull
float depth;
} CvConvexityDefect;

したがって、各欠陥を取得した後、それらからポイントの CvSeq を構築しcvPointPolygonTest、三角形の重心で使用して、それらがそれらの内部にあるかどうかを確認できます。それらが欠陥の内側にある場合、それはそれらが主輪郭の外側にあることを意味します。

これが必要なものであり、役立つことを願っています。

于 2011-11-23T13:50:18.803 に答える