2値画像の領域を違う色で塗り分ける
【概要】
二値画像から連結成分を検出し、連結成分ごとに異なるランダムな色で塗り分けて表示するプログラムである。OpenCV 5 を前提とする。連結成分の検出には cv::connectedComponentsWithStats を用いる。ラベリングによって各画素に直接ラベル番号が割り当てられるため、輪郭抽出と階層をたどった塗りつぶし描画を組み合わせる方法よりも単純な処理で塗り分けができる。
【目次】
【関連する外部ページ】
- OpenCV の公式ページ: https://opencv.org
- GitHub の OpenCV のページ: https://github.com/opencv/opencv/releases
【サイト内の関連情報】
- OpenCV について [PDF] , [パワーポイント]
- OpenCV のインストール,画像表示を行う C++ プログラムの実行手順: 別ページ »で説明
- OpenCVとPythonを活用した画像・ビデオ処理プログラム: 別ページ »にまとめ
- OpenCV 4 の C/C++ プログラム: 別ページ »にまとめている.
ソースコード
コマンドライン引数の1番目に、二値画像(白黒画像)のファイル名を与えて実行する。以下の内容で drawcontours.cpp という名前のファイルを作成する。
#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>
using namespace cv;
using namespace std;
int main(int argc, char** argv)
{
// コマンドライン引数の 1 番目に 2 値画像(白黒)
// のファイル名を与えてください.
if (argc != 2)
return -1;
Mat src = imread(argv[1], IMREAD_GRAYSCALE);
if (src.empty())
return -1;
src = src > 1;
imshow("Source", src);
// 連結成分のラベリング
Mat labels, stats, centroids;
int nLabels = connectedComponentsWithStats(src, labels, stats, centroids, 8, CV_32S);
// ラベル 0 は背景.ラベル 1 以上の各連結成分にランダムな色を割り当てます.
RNG rng(12345);
vector colors(nLabels);
colors[0] = Vec3b(0, 0, 0);
for (int i = 1; i < nLabels; i++)
colors[i] = Vec3b(rng.uniform(0, 256), rng.uniform(0, 256), rng.uniform(0, 256));
Mat dst = Mat::zeros(src.rows, src.cols, CV_8UC3);
for (int y = 0; y < dst.rows; y++)
for (int x = 0; x < dst.cols; x++)
dst.at(y, x) = colors[labels.at(y, x)];
imshow("Components", dst);
waitKey(0);
return 0;
}
コンパイル方法
以下のコマンドでコンパイルする。ソースファイル名は drawcontours.cpp とする。pkg-config でOpenCVのインクルードパスとライブラリを解決する。OpenCV 5 は C++17 を要求するため、-std=c++17 を指定する。
g++ -std=c++17 -o a.out drawcontours.cpp $(pkg-config --cflags --libs opencv4)