OpenCVでROIサイズ、位置をGUI上で指定


はじめに

OpenCV C++を利用して、ROIサイズ、位置をGUI上で指定し、ROI平均画素値を出力する。

ROIサイズの変更はトラックバーで、ROI位置はマウスイベントで指定する。

使用環境

  • Visual Studio 2022 Community
  • OpenCV Ver. 4.5.4

参考サイト、本

  1. C++版OpenCVでcreateTrackbar第6引数userdataを使ってコールバック関数に参照させてみた
  2. 実践OpenCV3 for C++ 画像映像情報処理、永田雅人、豊沢聡、(株)カットシステム
  3. 解析画像は次のサイトのものを使用。The Cell Image Library

プログラムの実行結果

  • 画像内でROIの平均画素値を表示。
  • マウスクリックした位置にROIを設定。
  • トラックバーでROIサイズを変更する。
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));

ソースコード全文は以下のようになる。

  1.  
  2. #include <iostream>
  3.  
  4. #include <opencv2/opencv.hpp>
  5.  
  6. #ifdef _DEBUG
  7. #pragma comment(lib, “opencv_world454d.lib”)
  8. #else
  9. #pragma comment(lib, “opencv_world454.lib”)
  10. #endif
  11.  
  12. using namespace std;
  13. using namespace cv;
  14.  
  15. const char* src_windowName = “Source_Image, :close -> q”;
  16.  
  17. //ROI用の各パラメータをクラスとして定義
  18. class ROI_Parameter {
  19. public:
  20.     cv::Mat image;    //解析対象の画像用のMat
  21.     int length = 30;    //ROIのサイズ
  22.     int c_center[2] = { 250, 200 };    //ROIの基準座標
  23.     double average_rROI_value = 0.0;    //ROI平均画素値
  24.     char text_head_pxvalue[100] = “ROI Average Pixel Value = “;    //画像上に表示するROI平均画素値の定型文
  25.     char insert_text_pxvalue[100] = “NULL”;    //画像上に表示するROI平均画素値
  26. };
  27.  
  28. //ROIサイズをトラックバーで変更。ROIを描画し平均画素値を表示。
  29. void ROI_size_trackbar(int length_trackbar, void* userdata)
  30. {
  31.     ROI_Parameter* roi_param;
  32.     roi_param = (ROI_Parameter*)(userdata);
  33.     cv::Mat srcimg = roi_param->image;
  34.     cv::Mat rect_img = srcimg.clone(); //矩形ROIの位置、画素値情報を重畳した画像データ
  35.  
  36.     //cout << length_trackbar << endl;
  37.  
  38.     //ROI幅0のときのエラー回避のため
  39.     if (length_trackbar < 1) {
  40.         roi_param->length = 1;
  41.     }
  42.     //矩形処理領域を設定
  43.     cv::Rect roi(roi_param->c_center[0], roi_param->c_center[1], roi_param->length, roi_param->length);
  44.     cv::Mat s_roi = srcimg(roi); //矩形ROIのみ抽出した画像データ
  45.  
  46.      //ROI領域を描画
  47.     cv::rectangle(rect_img, roi, cv::Scalar(0, 255, 0), 1);
  48.  
  49.     //矩形ROI画素値を画像にテキスト表示
  50.     sprintf_s(roi_param->text_head_pxvalue, “ROI Average Pixel Value = “); //テキストを初期化。値が追記されないように
  51.     roi_param->average_rROI_value = mean(s_roi)[0];//RGBのB成分のみ画像に表示
  52.     sprintf_s(roi_param->insert_text_pxvalue, ” %.0f”, roi_param->average_rROI_value);
  53.     strcat_s(roi_param->text_head_pxvalue, roi_param->insert_text_pxvalue);
  54.     putText(rect_img, roi_param->text_head_pxvalue, Point(10, 50), FONT_HERSHEY_SIMPLEX, 0.5, Scalar(0, 255, 0), 0, 2);
  55.  
  56.     //矩形ROI重畳画像をそれぞれ表示
  57.     cv::imshow(src_windowName, rect_img);
  58.  
  59. }
  60.  
  61. // ROIの位置をマウスクリックで変更。ROIを描画し平均画素値を表示。
  62. void setRectangle(int event, int x, int y, int flags, void* userdata) {
  63.     ROI_Parameter* roi_param;
  64.     roi_param = (ROI_Parameter*)(userdata);
  65.     cv::Mat srcimg = roi_param->image;
  66.     cv::Mat rect_img = srcimg.clone(); //矩形ROIの位置、画素値情報を重畳した画像データ
  67.  
  68.  
  69.     switch (event) {
  70.     case EVENT_LBUTTONDOWN:
  71.         if (0 < x && x < srcimg.cols – roi_param->length && 0 < y && y < srcimg.rows – roi_param->length) {
  72.             roi_param->c_center[0] = x, roi_param->c_center[1] = y;
  73.             //矩形処理領域を設定
  74.             cv::Rect roi(roi_param->c_center[0], roi_param->c_center[1], roi_param->length, roi_param->length);
  75.             cv::Mat s_roi = srcimg(roi); //矩形ROIのみ抽出した画像データ
  76.  
  77.             //ROI領域を描画
  78.             cv::rectangle(rect_img, roi, cv::Scalar(0, 255, 0), 1);
  79.  
  80.             //矩形ROI画素値を画像にテキスト表示
  81.             sprintf_s(roi_param->text_head_pxvalue, “ROI Average Pixel Value = “); //テキストを初期化。値が追記されないように
  82.             roi_param->average_rROI_value = mean(s_roi)[0];//RGBのB成分のみ画像に表示
  83.             sprintf_s(roi_param->insert_text_pxvalue, ” %.0f”, roi_param->average_rROI_value);
  84.             strcat_s(roi_param->text_head_pxvalue, roi_param->insert_text_pxvalue);
  85.             putText(rect_img, roi_param->text_head_pxvalue, Point(10, 50), FONT_HERSHEY_SIMPLEX, 0.5, Scalar(0, 255, 0), 0, 2);
  86.  
  87.             //矩形ROI重畳画像をそれぞれ表示
  88.             cv::imshow(src_windowName, rect_img);
  89.  
  90.             //矩形ROIサイズと平均画素値をコンソールに表示
  91.             cout << “ROI size = “ << roi_param->length;
  92.             cout << std::fixed << std::setprecision(0) << “\t” << “rectROI value = “ << mean(s_roi) << endl; //小数点以下の桁数を0で表示
  93.         }
  94.         break;
  95.     }
  96.  
  97. }
  98.  
  99. int main(int argc, const char* argv[]) {
  100.  
  101.     //読み込む画像データ
  102.     string source_img = “36_512v(green).jpg”;
  103.     cv::Mat src = cv::imread(source_img);
  104.  
  105.     ROI_Parameter roi_param;
  106.     roi_param.image = src.clone();    //ROIパラメータのクラスに読み込んだ画像をコピー
  107.     int roi_length_max = 100; //矩形ROIの長さの最大値
  108.  
  109.     if (src.empty()) {
  110.         std::cout << “read error.\n”;
  111.         return -1;
  112.     }
  113.  
  114.     cv::namedWindow(src_windowName, cv::WINDOW_AUTOSIZE);
  115.  
  116.     //トラックバー生成
  117.     cv::createTrackbar(“ROI Length”, src_windowName, &roi_param.length, roi_length_max, ROI_size_trackbar, (void*)(&roi_param));
  118.     //トラックバー呼び出し関数
  119.     ROI_size_trackbar(50, (void*)(&roi_param)); //第1引数はスライダの初期値
  120.  
  121.     //マウスイベントに対するコールバック関数の登録
  122.     setMouseCallback(src_windowName, setRectangle, (void*)(&roi_param));
  123.  
  124.     cv::waitKey(0);
  125.     src.release();
  126.     cv::destroyAllWindows();
  127.  
  128.     return 0;
  129. }

コメントを残す