Skip to content

OpenCVを使ったラベリング

atinfinity edited this page Oct 6, 2017 · 42 revisions

OpenCVを使ったラベリング

はじめに

OpenCV 3.0からimgprocモジュールにてラベリング専用API(connectedComponentsconnectedComponentsWithStats)が提供されるようになりました.そのため,これらのAPIを使うことで簡単にラベリングを行うことができるようになります.

簡易版ラベリング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を表している点に注意が必要です.

詳細な情報(面積,重心,幅,高さ etc...)を取得できるラベリングAPI

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メソッドを使って自前実装

  • もともとラベリング専用の関数ではないので使い勝手はイマイチ(ユーティリティ関数も自作する必要あり).

Menu

Computer Vision

GPGPU

AR

ROS

Docker

Jetson

ARM

プログラミング言語

開発環境

勉強会

Clone this wiki locally