はじめに
以前の記事ではライブラリを一切使わない生のC++のみでプログラムを書きました。
今回はOpenCVを用いることで、より簡単なコードで画像の二値化を行うと共に、制約がほとんど無くなりました(OpenCVが対応する画像に対応)。
プログラムの手順
基本的なプログラムの手順は以前の記事で作成したプログラムと変わりません。
今回は通常のカラー画像についても処理ができるため、途中のグレースケール画像についても出力するようにされています。
- 画像データをグレースケール画像として読み込み
- 画像データ(グレースケール化後)の出力
- 閾値によって二値化
- 画像データ(二値化後)の出力
また、画像データを格納するためのオブジェクトや二値化をする関数などが予め用意されているため、格段にコードは簡潔になります。
ソースコード
#include <iostream> #include <opencv2/opencv.hpp> int main(){ cv::Mat gray, binary; //画像格納用のオブジェクト宣言 gray = cv::imread("input.jpg",0); //画像データの読み込み if (gray.empty()) { //エラー処理 std::cout << "error" << std::endl; return 0; } cv::imwrite("gray.jpg", gray); //グレースケール画像の保存 std::cout << "閾値を入力してください" << std::endl; int tsd_v; std::cin >> tsd_v; cv::threshold(gray,binary,tsd_v,255,cv::THRESH_BINARY); //二値化 cv::imwrite("binary.jpg", binary); //二値化画像の保存 gray.release(); binary.release(); return 0; }
ソースコードの説明
画像データ用のオブジェクトの定義
cv::Mat gray, binary;
画像データはMatクラスを用いると簡単に格納することができます。Matクラスについては詳しく説明すると長くなるので省略しますが、画像を扱うのに便利なクラスだということです。
ここでは「gray」と「binary」という二つのオブジェクトを生成しています。
画像データの読み込み
gray = cv::imread("input.jpg",0);
「imread」はファイルから画像を読み込み、読み込んだデータを返す関数で、次のようにして使います。
cv::imread(ファイル名,フラグ);
ファイル名は絶対パスもしくは相対パスで記述します。
フラグは次のルールに従って記述します。
- 「0」:グレースケール画像として読み込み
- 「1」:RGBカラー画像として読み込み
- 「-1」:そのままの画像として読み込み
ここではグレースケール画像として読み込んで、返り値をオブジェクト「gray」に格納しています。
読み込みのエラー判定
gray.empty()
「empty」はMatクラスのオブジェクトに何も入っていない場合(行列ポインタがnullの場合)に「true」を返す「bool型」の関数です。
ここではオブジェクト「gray」が空であるかを判断しています。
画像の書き出し
cv::imwrite("gray.jpg", gray);
「imwrite」はMatクラスのオブジェクトから指定したファイルに画像データを保存する関数で、次のようにして使います。
cv::imwrite(ファイル名, Matクラスオブジェクト);
ファイル名は絶対パスもしくは相対パスで記述します。
尚、画像フォーマットは指定したファイルの拡張子によって自動で決まります。
ここでは「gray」の画像データを「gray.jpg」に保存しています。
画像データの二値化
cv::threshold(gray,binary,tsd_v,255,cv::THRESH_BINARY);
「threshold」は画像の1チャンネルに閾値処理をすることができる関数で、次のようにして使います。
cv::threshold(入力画像,出力画像,閾値,最大値の値,閾値処理の種類);
入力画像、出力画像にはMatクラスオブジェクトを与えます。
最大値の値は閾値処理の一部で利用します。
閾値処理の種類とアルゴリズムは次のようになります。
- THRESH_BINARY
- 最大値:E > 閾値
- 0:上記以外
- THRESH_BINARY_INV
- 0:E > 閾値
- 最大値:上記以外
- THRESH_TRUNC
- 閾値:E > 閾値
- E:それ以外
- THRESH_TOZERO
- E:E > 閾値
- 0:それ以外
- THRESH_TOZERO_INV
- 0:E > 閾値
- E:それ以外
注)Eは各画素の輝度値
画像データの解放
Matオブジェクト.release();
Matオブジェクトの中にある行列を解放します。
通常はプログラムが勝手に解放するので要らないですが、気分的には書いておきたいです。
実際に実行する
次の画像に対してプログラムを実行し、閾値は120を入力した。
結果として次の二つの画像が出力された。
グレースケール化画像。
二値化画像。
最後に
最近の自分の研究に画像処理を使っているので、しばらく画像処理系のことをつらつらと書いていくかもしれないです。
コメント