cv:findContours の輪郭の階層構造を扱う

"I am your father." --- Anakin Skywalker

OpenCV の findContours はオプションを指定することで輪郭の階層構造を返してくれる。 外輪郭と内輪郭で色を変えて塗りたいときとか、これを使ってどうやるかを考えてみた。 以下のリンク先とほぼ一緒なのだけど、リンク先は C++ ではなく C の API を使っているので、C++ で書いてみた。

ここから書いたやつ。

void ProcessRecursive(int contour_id, const std::vector<std::vector<cv::Point>>& contours, const std::vector<cv::Vec4i>& hierarchy, int &counter, int level){
    int next_id = hierarchy[contour_id][0];
    int previous_id = hierarchy[contour_id][1];
    int child_id = hierarchy[contour_id][2];
    int parent_id = hierarchy[contour_id][3];
    ++counter;

    std::cout << "I am contour #" << contour_id
        << " in level " << level
        << ", child of #" << parent_id
        << ". Previous ID = " << previous_id
        << ", Next ID = " << next_id
        << ", child_id = " << child_id
        << ", counter = " << counter
        << std::endl;

    if (child_id != -1) {
        ProcessRecursive(child_id, contours, hierarchy, counter, level+1);
    }
    if (parent_id != -1 && next_id != -1) {
        ProcessRecursive(next_id, contours, hierarchy, counter, level);
    }
}

counter は輪郭の数え漏れがないか確認するために入れた*1

drawContour() を Fill するオプションで外側の輪郭から順番に使っていけばきれいに塗れる。そのうち画像の例を用意するかも。

*1:会社に contour を「カウンター」と読む人がいるので、このコードを見せて混乱させてあげたい。