1

質問に回答しました。質問の最後にある解決策を参照してください。その他のコメント/回答は引き続き歓迎します。

だから私はすべての要素を1つのメモリストアに入れるのに苦労しています。

私は主に Java プログラマーなので、おそらく C の同等の用語の代わりにいくつかの Java 用語を使用し、C オブジェクトを参照するときに間違った型について言及する可能性があるので、事前にこれを承認します (そして、ポインターから始めないでください)。 )。

最終的に私がやろうとしているのは、画像内のすべての Convexity Defects を取得し、それらを 1 つの連続したスペースに格納してから、JNI 経由で Java に戻すことです。ストアのタイプは重要ではありません。この段階では、それが機能する必要があり、先に進めば最適化に取り組むことができますが、スタック、キュー、リスト、ベクターなどでうまくいくと思います。現在、CvSeq オブジェクトのグループを 1 つの大きな CvSeq に追加するループ ラウンドを試みています。コードを投稿して、投稿後に説明します。

 CvSeq *allDefects;
allDefects = cvCreateSeq(0, sizeof (CvSeq), sizeof (CvConvexityDefect), mem_storage4);

CvContourScanner scanner3 = cvStartFindContours(img_bin, mem_storage3);
while ((c2 = cvFindNextContour(scanner3)) != NULL) {
    if (threshold != 0 && cvContourPerimeter(c2) < threshold) {
        cvSubstituteContour(scanner3, NULL);
    } else { // otherwise create the hull
        CvSeq* c_new;
        c_new = cvConvexHull2(c2, mem_storage5, CV_CLOCKWISE, 0);
        CvMemStorage* storage;
        storage = cvCreateMemStorage(0);
        defects = cvConvexityDefects(c2, c_new, storage);
        allDefects = defects;
        //            for (int i = 0;  i < defects->total; i++){
        //            cvSeqPush(allDefects, CV_GET_SEQ_ELEM(CvSeq, defects, i));
        //            }
    }
}

そのため、スキャナーを作成し、輪郭を見つけながらそれを行い、それが特定のしきい値よりも大きいことを確認します。それを想定して、その周りに船体を作成し、船体と船体の間の欠陥を見つけます。これは、ループするたびにallDefectsに追加したい複数のオブジェクトを欠陥に含めることができることを意味しますが、それを実現する唯一の方法は、allDefectsを欠陥と等しくすることです。つまり、ループごとに上書きされます。スタックのようにプッシュしようとすると、コメント付きのコードが少し表示されますが、これは次のエラーでクラッシュします。

アサーションに失敗しました: sizeof(((defects))->first[0]) == sizeof(CvSeqBlock) && ((defects))->elem_size == sizeof(CvSeq)、ファイル vtoolsModified.cpp、行 1407

ドキュメント「cvConvexityDefects() ルーチンは、CvConvexityDefect 構造のシーケンスを返します」に従って、CvConvexityDefectでいっぱいのCvSeqになります。それが助けになる場合の cvConvexityDefects の署名は次のとおりです。

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

つまり、私がやろうとしていることを要約すると、輪郭を見つけ、その船体を見つけ、それらの間の欠陥を見つけ、これらすべての欠陥を 1 つの大きなストアに追加し、輪郭がなくなるまで繰り返し、すべての欠陥を含む大きなストアを Java に返します。 . 私が助けを求めているのは太字の部分です。

できるソースの方向に私を助けたり、指摘したりできる人はいますか? (私はこの特定の問題に約2週間取り組んできたので、多くのリソースにアクセスしました。はい、自分で効果的に単純なループであるべきものを理解できなかったのは本当に馬鹿げていると感じています。)

ありがとう

編集 - コメントの結果として詳細が追加されました。

EDIT 2 - 質問に回答しました。結果の固定コードは以下のとおりです

私の C の理解不足が根本的な問題だったようです。CvConvexityDefect を使用すべき場所で CvSeq を使用する必要があると想定していました。修正されたコードは次のとおりです。

CvSeq *defects;
CvSeq *allDefects;
allDefects = cvCreateSeq(0, sizeof(CvSeq), sizeof(CvConvexityDefect), mem_storage4);

CvContourScanner scanner3 = cvStartFindContours(img_bin, mem_storage3);
while ((c2 = cvFindNextContour(scanner3)) != NULL) {
    if (threshold != 0 && cvContourPerimeter(c2) < threshold) {
        cvSubstituteContour(scanner3, NULL);
    } else { // otherwise create the hull
        CvSeq* c_new;
        c_new = cvConvexHull2(c2, mem_storage5, CV_CLOCKWISE, 0);
        CvMemStorage* storage;
        storage = cvCreateMemStorage(0);
        defects = cvConvexityDefects(c2, c_new, storage);
        //            allDefects = defects;
        if (defects->total < 100) {
         for (int i = 0; i < defects->total; i++) {
          CvConvexityDefect* element = CV_GET_SEQ_ELEM(CvConvexityDefect, defects, i);
           if (element != 0){      
               cvSeqPush(allDefects, element);                    }
            }
        }
    }
}

また、返される欠陥が 100 未満であること (システムを壊すのは数百万の場合もあります) を確認CV_GET_SEQ_ELEMし、null を返さないことも確認しています (nullを返すことができるかどうかはわかりませんが、念のためチェック。

4

1 に答える 1

1

私の推測では、あなたのループには次の行に誤りがあると思います:

CV_GET_SEQ_ELEM(CvSeq, defects, i)

その定義を見ると:

#define CV_GET_SEQ_ELEM( elem_type, seq, index ) CV_SEQ_ELEM( (seq), elem_type, (index) )

最初のパラメーターは、シーケンスのタイプ (CvSeq) ではなく、要素のタイプ (cvFindContours は通常、CvPoint のシーケンスを作成します) でなければならないことがわかります。

シーケンスを保存できる他の方法は、使用することです

    void* cvCvtSeqToArray(const CvSeq* seq,
                          void* elements,
                          CvSlice slice = CV_WHOLE_SEQ
                         );

配列をリストに保存して、オブジェクトごとに欠陥を分離します。必要なものに応じて、さらに多くのオプションがあります。

EDIT2:

わかりましたので、cvConvexityDefects を確認したところ、CvPoint ではなく一連の構造が返されることがわかりました。allDefects はカスタムメイドの CvSeq である必要があり、次のようにコードを変更します。

cvSeqPush(allDefects, CV_GET_SEQ_ELEM(CvConvexityDefect, defects, i));
于 2011-11-18T07:24:58.350 に答える