はじめに
OpenCV C++を利用して、ROIサイズ、位置をGUI上で指定し、ROI平均画素値を出力する。
ROIサイズの変更はトラックバーで、ROI位置はマウスイベントで指定する。
使用環境
- Visual Studio 2022 Community
- OpenCV Ver. 4.5.4
参考サイト、本
- C++版OpenCVでcreateTrackbar第6引数userdataを使ってコールバック関数に参照させてみた
- 実践OpenCV3 for C++ 画像映像情報処理、永田雅人、豊沢聡、(株)カットシステム
- 解析画像は次のサイトのものを使用。The Cell Image Library
プログラムの実行結果
- 画像内でROIの平均画素値を表示。
- マウスクリックした位置にROIを設定。
- トラックバーでROIサイズを変更する。
プログラムの概要
矩形ROIの指定はRect関数を使用。
cv::Rect roi (int x, int y, int width, int height); //長方形の左上x座標、y座標、幅、高さを指定。戻り値はRect型
cv::Mat roi_img = srcimg(roi);
とすることで、画像srcimgのROIのみ抽出した画像roi_imgが生成。
cv::mean(roi_img);
とすることで、ROIの平均画素値(BGRAの各要素)が出力される。
長方形を描画するcv::rectangle関数を利用して、指定したROIを画像に描画する。
長方形の左上の座標をマウスクリックで指定。幅、高さは同一(正方形)として、トラックバーで指定。これらのパラメータをまとめたいため、クラス化しておく。上記の参考サイト1がとても参考になった。
class ROI_Parameter {
public:
cv::Mat image; //解析対象の画像用のMat
int length = 30; //ROIのサイズ
int c_center[2] = { 250, 200 }; //ROIの基準座標
double average_rROI_value = 0.0; //ROI平均画素値
char text_head_pxvalue[100] = "ROI Average Pixel Value = ";//画像上に表示するROI平均画素値の定型文
char insert_text_pxvalue[100] = "NULL"; //画像上に表示するROI平均画素値
};
main内において、以下のように、cv::createTrackbarにてトラックバーを生成し、引数にクラス化したパラメータ(roi_param)、トラックバーの呼び出し関数(ROI_size_trackbar)を指定。トラックバーを変更すると、ROI_size_trackbar関数が呼ばれ、パラメータのroi_paramが渡される。
//画像読み込み
cv::Mat src = cv::imread("imagename.jpg");
//定義したクラスの変数を定義
ROI_Parameter roi_param;
roi_param.image = src.clone(); //ROIパラメータのクラスに読み込んだ画像をコピー
int roi_length_max = 100; //矩形ROIの長さの最大値
//トラックバー生成
cv::createTrackbar("ROI Length", "Window Name", &roi_param.length, roi_length_max, ROI_size_trackbar, (void*)(&roi_param));
//トラックバー呼び出し関数
ROI_size_trackbar(50, (void*)(&roi_param)); //第1引数はスライダの初期値
ROI位置を変更するため、マウスクリック(イベント)に対するコールバック関数をmain内で以下のように記述。マウスクリックすると、setRectangle関数が呼ばれ、パラメータのroi_paramを渡される。
//マウスイベントに対するコールバック関数の登録
setMouseCallback("Window Name", setRectangle, (void*)(&roi_param));
ソースコード全文は以下のようになる。
- #include <iostream>
- #include <opencv2/opencv.hpp>
- #ifdef _DEBUG
- #pragma comment(lib, “opencv_world454d.lib”)
- #else
- #pragma comment(lib, “opencv_world454.lib”)
- #endif
- using namespace std;
- using namespace cv;
- const char* src_windowName = “Source_Image, :close -> q”;
- //ROI用の各パラメータをクラスとして定義
- class ROI_Parameter {
- public:
- cv::Mat image; //解析対象の画像用のMat
- int length = 30; //ROIのサイズ
- int c_center[2] = { 250, 200 }; //ROIの基準座標
- double average_rROI_value = 0.0; //ROI平均画素値
- char text_head_pxvalue[100] = “ROI Average Pixel Value = “; //画像上に表示するROI平均画素値の定型文
- char insert_text_pxvalue[100] = “NULL”; //画像上に表示するROI平均画素値
- };
- //ROIサイズをトラックバーで変更。ROIを描画し平均画素値を表示。
- void ROI_size_trackbar(int length_trackbar, void* userdata)
- {
- ROI_Parameter* roi_param;
- roi_param = (ROI_Parameter*)(userdata);
- cv::Mat srcimg = roi_param->image;
- cv::Mat rect_img = srcimg.clone(); //矩形ROIの位置、画素値情報を重畳した画像データ
- //cout << length_trackbar << endl;
- //ROI幅0のときのエラー回避のため
- if (length_trackbar < 1) {
- roi_param->length = 1;
- }
- //矩形処理領域を設定
- cv::Rect roi(roi_param->c_center[0], roi_param->c_center[1], roi_param->length, roi_param->length);
- cv::Mat s_roi = srcimg(roi); //矩形ROIのみ抽出した画像データ
- //ROI領域を描画
- cv::rectangle(rect_img, roi, cv::Scalar(0, 255, 0), 1);
- //矩形ROI画素値を画像にテキスト表示
- sprintf_s(roi_param->text_head_pxvalue, “ROI Average Pixel Value = “); //テキストを初期化。値が追記されないように
- roi_param->average_rROI_value = mean(s_roi)[0];//RGBのB成分のみ画像に表示
- sprintf_s(roi_param->insert_text_pxvalue, ” %.0f”, roi_param->average_rROI_value);
- strcat_s(roi_param->text_head_pxvalue, roi_param->insert_text_pxvalue);
- putText(rect_img, roi_param->text_head_pxvalue, Point(10, 50), FONT_HERSHEY_SIMPLEX, 0.5, Scalar(0, 255, 0), 0, 2);
- //矩形ROI重畳画像をそれぞれ表示
- cv::imshow(src_windowName, rect_img);
- }
- // ROIの位置をマウスクリックで変更。ROIを描画し平均画素値を表示。
- void setRectangle(int event, int x, int y, int flags, void* userdata) {
- ROI_Parameter* roi_param;
- roi_param = (ROI_Parameter*)(userdata);
- cv::Mat srcimg = roi_param->image;
- cv::Mat rect_img = srcimg.clone(); //矩形ROIの位置、画素値情報を重畳した画像データ
- switch (event) {
- case EVENT_LBUTTONDOWN:
- if (0 < x && x < srcimg.cols – roi_param->length && 0 < y && y < srcimg.rows – roi_param->length) {
- roi_param->c_center[0] = x, roi_param->c_center[1] = y;
- //矩形処理領域を設定
- cv::Rect roi(roi_param->c_center[0], roi_param->c_center[1], roi_param->length, roi_param->length);
- cv::Mat s_roi = srcimg(roi); //矩形ROIのみ抽出した画像データ
- //ROI領域を描画
- cv::rectangle(rect_img, roi, cv::Scalar(0, 255, 0), 1);
- //矩形ROI画素値を画像にテキスト表示
- sprintf_s(roi_param->text_head_pxvalue, “ROI Average Pixel Value = “); //テキストを初期化。値が追記されないように
- roi_param->average_rROI_value = mean(s_roi)[0];//RGBのB成分のみ画像に表示
- sprintf_s(roi_param->insert_text_pxvalue, ” %.0f”, roi_param->average_rROI_value);
- strcat_s(roi_param->text_head_pxvalue, roi_param->insert_text_pxvalue);
- putText(rect_img, roi_param->text_head_pxvalue, Point(10, 50), FONT_HERSHEY_SIMPLEX, 0.5, Scalar(0, 255, 0), 0, 2);
- //矩形ROI重畳画像をそれぞれ表示
- cv::imshow(src_windowName, rect_img);
- //矩形ROIサイズと平均画素値をコンソールに表示
- cout << “ROI size = “ << roi_param->length;
- cout << std::fixed << std::setprecision(0) << “\t” << “rectROI value = “ << mean(s_roi) << endl; //小数点以下の桁数を0で表示
- }
- break;
- }
- }
- int main(int argc, const char* argv[]) {
- //読み込む画像データ
- string source_img = “36_512v(green).jpg”;
- cv::Mat src = cv::imread(source_img);
- ROI_Parameter roi_param;
- roi_param.image = src.clone(); //ROIパラメータのクラスに読み込んだ画像をコピー
- int roi_length_max = 100; //矩形ROIの長さの最大値
- if (src.empty()) {
- std::cout << “read error.\n”;
- return -1;
- }
- cv::namedWindow(src_windowName, cv::WINDOW_AUTOSIZE);
- //トラックバー生成
- cv::createTrackbar(“ROI Length”, src_windowName, &roi_param.length, roi_length_max, ROI_size_trackbar, (void*)(&roi_param));
- //トラックバー呼び出し関数
- ROI_size_trackbar(50, (void*)(&roi_param)); //第1引数はスライダの初期値
- //マウスイベントに対するコールバック関数の登録
- setMouseCallback(src_windowName, setRectangle, (void*)(&roi_param));
- cv::waitKey(0);
- src.release();
- cv::destroyAllWindows();
- return 0;
- }