OpenCVを使ったラベリング - atinfinity/lab GitHub Wiki
OpenCV 3.0からimgprocモジュールにてラベリング専用API(connectedComponents,connectedComponentsWithStats)が提供されるようになりました.そのため,これらのAPIを使うことで簡単にラベリングを行うことができるようになります.
int connectedComponents
(
    InputArray image, 
    OutputArray labels, 
    int connectivity=8, 
    int ltype=CV_32S
)| パラメータ | Input/Output | 意味 | 
|---|---|---|
| image | Input | 入力画像 | 
| labels | Output | ラベリング結果画像 | 
| connectivity | Input | 4 or 8を指定 | 
| ltype | Input | ラベリング結果画像の型 (CV_32SとCV_16Uがサポートされる) | 
詳細は公式APIドキュメントの説明を参照ください.また,公式ドキュメントにも記載されているように0番目のラベルはbackground labelを表している点に注意が必要です.
int connectedComponentsWithStats
(
    InputArray image, 
    OutputArray labels, 
    OutputArray stats, 
    OutputArray centroids, 
    int connectivity=8, 
    int ltype=CV_32S
)| パラメータ | Input/Output | 意味 | 
|---|---|---|
| image | Input | 入力画像 | 
| labels | Output | ラベリング結果画像 | 
| stats | Output | ラベル毎の属性値 (詳細はcv::ConnectedComponentsTypes)を参照 | 
| centroids | Output | 重心の座標値 | 
| connectivity | Input | 4 or 8を指定 | 
| ltype | Input | ラベリング結果画像の型 (CV_32SとCV_16Uがサポートされる) | 
詳細は公式APIドキュメントの説明を参照ください.また,公式ドキュメントにも記載されているように0番目のラベルはbackground labelを表している点に注意が必要です.
#include <opencv2/core.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/imgcodecs.hpp>
#include <opencv2/highgui.hpp>
#include <iostream>
#include <vector>
int main( int argc, const char** argv )
{
    // グレースケールで画像読み込み
    cv::Mat src = cv::imread("input.bmp", cv::IMREAD_GRAYSCALE);
    // 画像の読み込みに失敗したらエラー終了する
    if(src.empty())
    {
        std::cerr << "Failed to open image file." << std::endl;
        return -1; 
    }
    // 二値化
    cv::Mat bin;
    cv::threshold(src, bin, 0, 255, cv::THRESH_BINARY | cv::THRESH_OTSU);
    // ラベル用画像生成(※CV_32S or CV_16Uにする必要あり)
    cv::Mat labelImage(src.size(), CV_32S);
    // ラベリング実行.戻り値がラベル数.また,このサンプルでは8近傍でラベリングする.
    int nLabels = cv::connectedComponents(bin, labelImage, 8);
    // ラベリング結果の描画色を決定
    std::vector<cv::Vec3b> colors(nLabels);
    colors[0] = cv::Vec3b(0, 0, 0);
    for(int label = 1; label < nLabels; ++label)
    {
        colors[label] = cv::Vec3b((rand()&255), (rand()&255), (rand()&255));
    }
    // ラベリング結果の描画
    cv::Mat dst(src.size(), CV_8UC3);
    for(int y = 0; y < dst.rows; ++y)
    {
        for(int x = 0; x < dst.cols; ++x)
        {
            int label = labelImage.at<int>(y, x);
            cv::Vec3b &pixel = dst.at<cv::Vec3b>(y, x);
            pixel = colors[label];
        }
    }
    cv::namedWindow("Source", cv::WINDOW_AUTOSIZE );
    cv::imshow("Source", src );
    cv::namedWindow( "Connected Components", cv::WINDOW_AUTOSIZE );
    cv::imshow( "Connected Components", dst );
    cv::waitKey(0);
    return 0;
}|  | 
|---|
| 入力画像 | 
|  | 
|---|
| 出力画像 | 
- pthreadを用いて並列化されている.
- OpenCVとの親和性が高い.
- 2014年3月で更新が止まっている.
- ライセンスがGNU LGPL v3なので用途によってはネック.
- 便利なユーティリティ関数も用意されている.
- ライセンスも修正BSDなので使いやすい.
- ただし,OpenCVのMatを直接扱えない.
cv::findContoursメソッドを使って自前実装
- もともとラベリング専用の関数ではないので使い勝手はイマイチ(ユーティリティ関数も自作する必要あり).