4

画像の凸包を計算するために OpenCV 2.4 を使用しています。

また、画像からノイズを除去するための処理も行っていますが、これは質問にはあまり関係ありません。

凸包を計算するコードは次のとおりです。

...
cv::Mat sourceImage; // assume something is already here please
cv::vector<cv::Vec4i> hierarchy;    
std::vector<std::vector<cv::Point> > contours;

cv::findContours( sourceImage, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE,cv::Point(0, 0));

// Find the convex hull object for each contour
vector<cv::vector<cv::Point> >hull( contours.size() );

for (int i = 0; i < contours.size(); i++)
{
    convexHull( contours[i], hull[i], false );
}
...

凸包と輪郭の両方を持っているので、船体の凸性欠陥を計算したいと思います。これは、opencv のドキュメントを見て、次のようになると思いました。

cv::Vec4i defects;  
convexityDefects(cv::Mat(contours),  hull, defects);

これを行うと、次のエラーが発生します。

OpenCV Error: Assertion failed (ptnum > 3) in convexityDefects, file ./opencv/opencv/modules/imgproc/src/contours.cpp, line 1969

凸性欠陥を使用するときに私が間違っていることについてのアイデアはありますか?

Opencv凸性欠陥のドキュメント

前もって感謝します。

アップデート

Innuendo の回答のおかげで、メイン ループ コードを次のように更新しました。

std::vector<Vec4i> defects; 
vector<cv::vector<cv::Point> >hull( contours.size() );

for (int i = 0; i < contours.size(); i++)
{  
    convexHull( contours[i], hull[i], false );
    convexityDefects(contours[i], hull[i], defects[i]);
}

これを使用すると、私が今得るエラーは次のとおりです。

OpenCV Error: Assertion failed (hull.checkVector(1, CV_32S) > 2) in convexityDefects
4

4 に答える 4

4

コメントを読んでいない、または見ていなかった場合の解決策は次のとおりです。

vector<cv::vector<int> >hull;

次の代わりに船体を作成します。

vector<cv::vector<Point> >hull;

凸性欠陥は、一連のポイントではなく、一連のインデックスとして格納されたハルでのみ機能するためです。

悲しいことに、drawContours は一連のインデックスとしてではなく、一連のポイントとして格納された輪郭のみを描画するため、別の問題が発生します。したがって、後の段階で船体を描画する場合は、船体を見つけるときに 2 つのストアを作成することをお勧めします。1 つは描画用、もう 1 つは欠陥の検出用です。次の作品のラインに沿った何か:

  // create storage space
  vector<vector<int> > hullsI(contours.size());
  vector<vector<Point> > hullsP(contours.size());
  vector<vector<Vec4i> > defects(contours.size());

  for(int i = 0; i <contours.size(); ++i){
     //find the hulls
     convexHull(contours[i], hullsI[i], true);
     convexHull(contours[i], hullsP[i], true);
     //find the defects  
     convexityDefects(contours[i], hullsI[i], defects[i]);
     }

船体を 2 回計算するよりも、別の方法で船体を描画する方が効率的かもしれませんが、これは私が見た中で最もエレガントな方法でした。

また、私はまだ C/C++ のコツをつかんでいます (Java のやつです) がusing namespace cv、コードの先頭に追加すると、コード全体で cv:: を使用する必要がなくなると思います。

私がつま先を踏みつけていないことを願っています。

于 2012-07-06T16:21:15.413 に答える
4

openCV wiki から:

輪郭の凸欠陥を見つけます。

したがって、ループに含める必要があります。

std::vector<Vec4i> defects; 
vector<cv::vector<int> >hull( contours.size() );

for (int i = 0; i < contours.size(); i++)
{  
    convexHull( contours[i], hull[i], false );
    convexityDefects(contours[i], hull[i], defects[i]);
}

また、あなたが言及したように、wikiには次のように書かれています:

hull – 凸包を出力します。これは、インデックスの整数ベクトルまたは点のベクトルのいずれかです。最初のケースでは、凸包要素は元の配列内の凸包ポイントの 0 ベースのインデックスです (凸包ポイントのセットは元のポイント セットのサブセットであるため)。2 番目のケースでは、ハル要素は凸包ポイントそのものです。

于 2012-05-17T05:11:53.710 に答える
3

上記のような問題がありましたが、ついに正しいものを書きました:)

vector<vector<Point>> hull( contours.size() );
vector<vector<int> > hullsI(contours.size());
vector<vector<Vec4i>> convdefect(contours.size());

for( int i = 0; i < contours.size(); i++ )
{ 
    convexHull( Mat(contours[i]), hull[i], false);
    convexHull( Mat(contours[i]), hullsI[i], false);        
    if(hullsI[i].size() > 3 )
        convexityDefects(contours[i],hullsI[i],convdefect[i]);
}
/// Draw contours + hull results
Mat drawing = Mat::zeros( threshold_output.size(), CV_8UC3 );
for( int i = 0; i< contours.size(); i++ )
{
    size_t count = contours[i].size();
    if( count <300 )
        continue;

    //Scalar color = Scalar( rng.uniform(0, 255), rng.uniform(0,255), rng.uniform(0,255));
    drawContours( drawing, contours, i, Scalar(255,0,0), 1, 8, vector<Vec4i>(), 0, Point());
    drawContours( drawing, hull, i, Scalar(0,0,255), 1, 8, vector<Vec4i>(), 0, Point());
}

/// Draw convexityDefects
for( int i = 0; i< contours.size(); i++ )
{
    size_t count = contours[i].size();
    if( count <300 )
        continue;

    vector<Vec4i>::iterator d=convdefect[i].begin();
    while( d!=convdefect[i].end() ) {
        Vec4i& v=(*d);
        int startidx=v[0]; Point ptStart( contours[i][startidx] );
        int endidx=v[1]; Point ptEnd( contours[i][endidx] );
        int faridx=v[2]; Point ptFar( contours[i][faridx] );
        float depth = v[3] / 256;

        line( drawing, ptStart, ptEnd, Scalar(0,255,0), 1 );
        line( drawing, ptStart, ptFar, Scalar(0,255,0), 1 );
        line( drawing, ptEnd, ptFar, Scalar(0,255,0), 1 );
        circle( drawing, ptFar,   4, Scalar(0,255,0), 2 );
        d++;
    }
}
于 2013-01-03T10:37:36.323 に答える
2

解決策が提示されるまで、しばらくの間同じエラーが発生しました。contours[i]凸性欠陥を呼び出す前にサイズを確認してください

/// Find the convex hull object for each contour
vector<vector<int> > hullsI(contours.size());
vector<vector<Point> > hullsP(contours.size());
vector<vector<Vec4i> > defects(contours.size());

for(int i = 0; i <contours.size(); ++i){
    //find the hulls
    convexHull(contours[i], hullsI[i], false, false);
    convexHull(contours[i], hullsP[i], false, true);
    //find the defects
    if (contours[i].size() >3 )
    {
        convexityDefects(contours[i], hullsI[i], defects[i]);            
    }

}

それが役に立てば幸い :)

于 2012-09-11T12:36:24.340 に答える