web-dev-qa-db-ja.com

OpenCVのfindContours()で階層を使用していますか?

等高線を見つけるときに、CV_RETR_CCOMP引数を使用しました。これは、2つのレベルの階層を作成することになっています。最初のレベルは外部輪郭用で、2番目のレベルは穴の境界用です。ただし、これまで階層を使用したことがないため、これについてはよく知りません。

誰かが穴の境界にのみアクセスする方法を教えてもらえますか?外側の輪郭を無視して、穴の境界のみを描きたい。コード例は高く評価されます。私はCではなくC++インターフェイスを使用しているので、C関数を提案しないでください(つまり、cvFindContours()の代わりにfindContours()を使用してください)。

32
fdh

findContoursによって返される階層の形式は次のとおりです:hierarchy[idx][{0,1,2,3}]={next contour (same level), previous contour (same level), child contour, parent contour}

CV_RETR_CCOMP、外側の輪郭と穴の階層を返します。つまり、hierarchy[idx]の要素2と3は、-1と等しくないこれらの要素を1つだけ持っています。つまり、各要素には、親も子もないか、親は子がないか、子は親がないのです。

親はあるが子はない要素は、穴の境界になります。

つまり、基本的にはhierarchy[idx]を実行し、hierarchy[idx][3]>-1で何かを描画します。

次のようなもの(Pythonでは動作しますが、C++はテストしていません。アイデアは問題ありません。):

findContours( image, contours, hierarchy, CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE );

if ( !contours.empty() && !hierarchy.empty() ) {

    // loop through the contours/hierarchy
    for ( int i=0; i<contours.size(); i++ ) {

        // look for hierarchy[i][3]!=-1, ie hole boundaries
        if ( hierarchy[i][3] != -1 ) {
            // random colour
            Scalar colour( (Rand()&255), (Rand()&255), (Rand()&255) );
            drawContours( outImage, contours, i, colour );
        }
    }
}
41

AFAIKはCV_RETR_CCOMPを使用する場合、すべての穴が同じレベルにあります。

int firstHoleIndex = hierarchy[0][2];
for (int i = firstHoleIndex; i >= 0 ; i = hierarchy[i][0])
// contours.at(i) is a hole. Do something with it.
4
Shmuel Fine