About BBS

初期化

作成者: 怡土順一, 最終変更者: 怡土順一, 最終変更リビジョン: 353, 最終変更日時: 2007-11-27 02:58:30 +0900 (火, 27 11月 2007)
This is a local copy taken at 2010/09/20. CLICK HERE to the original page at opencv.jp.

■ ROI

画像に対して ROI(Region Of Interest)を設定すると,その部分画像が,画像全体と同一に扱われる. つまり,部分画像に対して処理を行う場合,それが部分画像であることを考慮する必要なく扱うことができる. ただし,処理結果として座標や領域を得て,それを再び画像全体に戻す処理 (例えば,画像全体に対して描画するなど)を行う場合は,座標にオフセット (ROIの位置,幅など)を加えるなどの追加処理が必要なので注意すること.

サンプル


部分画像のシャッフル cvSetImageROI, cvResetImageROI

ROIを利用して,部分画像同士を入れ換える

サンプルコード

#include <cv.h> #include <highgui.h> #include <time.h> /* 分割数の定義 */ #define DIVX (4) #define DIVY (4) #define DIVXY (DIVX*DIVY) int main (int argc, char **argv) { int w, h, i, j; IplImage *src_img, *dst_img, *tmp_img[2]; CvRect roi[DIVXY]; CvRNG rng = cvRNG (time (NULL)); // (1)画像を読み込む if (argc != 2 || (src_img = cvLoadImage (argv[1], CV_LOAD_IMAGE_ANYDEPTH | CV_LOAD_IMAGE_ANYCOLOR)) == 0) return -1; w = src_img->width - src_img->width % DIVX + DIVX; h = src_img->height - src_img->height % DIVY + DIVY; dst_img = cvCreateImage (cvSize (w, h), src_img->depth, src_img->nChannels); tmp_img[0] = cvCreateImage (cvSize (w / DIVX, h / DIVY), src_img->depth, src_img->nChannels); tmp_img[1] = cvCreateImage (cvSize (w / DIVX, h / DIVY), src_img->depth, src_img->nChannels); cvResize (src_img, dst_img); // (2)画像を分割するための矩形を設定 for (i = 0; i < DIVX; i++) { for (j = 0; j < DIVY; j++) { roi[DIVX * j + i].x = w / DIVX * i; roi[DIVX * j + i].y = h / DIVY * j; roi[DIVX * j + i].width = w / DIVX; roi[DIVX * j + i].height = h / DIVY; } } // (3)ROIを利用して部分画像を入れ換える for (i = 0; i < DIVXY * 2; i++) { int p1 = cvRandInt (&rng) % DIVXY; int p2 = cvRandInt (&rng) % DIVXY; cvSetImageROI (dst_img, roi[p1]); cvCopy (dst_img, tmp_img[0]); cvSetImageROI (dst_img, roi[p2]); cvCopy (dst_img, tmp_img[1]); cvCopy (tmp_img[0], dst_img); cvSetImageROI (dst_img, roi[p1]); cvCopy (tmp_img[1], dst_img); } cvResetImageROI (dst_img); cvResize (dst_img, src_img); // (4)画像の表示 cvNamedWindow ("Image", CV_WINDOW_AUTOSIZE); cvShowImage ("Image", src_img); cvWaitKey (0); cvDestroyWindow ("Image"); cvReleaseImage (&src_img); cvReleaseImage (&dst_img); cvReleaseImage (&tmp_img[0]); cvReleaseImage (&tmp_img[1]); return 0; }

// (1)画像を読み込む
コマンド引数で指定されたファイル名の画像(入力画像)をオープンし,関数 cvLoadImage()で読み込む.2番目の引数にCV_LOAD_IMAGE_ANYDEPTH | CV_LOAD_IMAGE_ANYCOLORを指定することで,元画像のデプス,チャンネルを変 更せずに読み込む. 読み込まれた画像は,指定された分割数で等分可能なように,関数cvResize()によりサイズを調整する. この際に,補間方法を指定しない場合は,デフォルト値のCV_INTER_LINEARが利用される.

// (2)画像を分割するための矩形を設定
画像を分割するために,構造体CvRectを設定する.

// (3)ROIを利用して部分画像を入れ換える
設定された矩形 CvRect を利用して画像に ROI を設定し,その ROI 全体をコピーして,ランダムに入れ換える. このような処理は ROI を利用しなくても,MASKの利用や1ピクセルづつコピーする,実際に画像を分割するなどの手法により実現できるが, ROI を利用することで比較的単純な処理にできる. また,関数 cvRandShuffle() を用いると,繰り返し計算なしで画像をシャッフルすることが可能である. 入れ換え後は,ROIを解放し,サイズを元の大きさ(入力画像サイズ)に戻す. サイズを戻す際も同様に, 関数cvResize()を利用し,ここで補間方法を指定しない場合は,デフォルト値のCV_INTER_LINEARが利用される.

// (4)画像の表示
部分画像がシャッフルされた画像含むウィンドウを実際に表示し,何かキーが押されるまで待つ.

実行結果例

[左]入力画像 [右]処理結果


画像の連結 cvSetImageROI, cvResetImageROI

複数の画像を横方向に連結して1枚の画像にする

サンプルコード

#include <cv.h> #include <highgui.h> #include <stdlib.h> /* プロトタイプ宣言 */ IplImage *combine_image (int num, IplImage ** tmp); /* メイン関数 */ int main (int argc, char **argv) { int i, img_num; IplImage **img; IplImage *combined_img; // (1)コマンド引数で指定された画像を全て読み込む if (argc < 2) { return 1; } else { img_num = argc - 1; img = (IplImage **) cvAlloc (sizeof (IplImage *) * img_num); for (i = 0; i < img_num; i++) { img[i] = cvLoadImage (argv[i + 1], CV_LOAD_IMAGE_COLOR); if (img[i] == 0) return -1; } } // (2)画像を連結する combined_img = combine_image (img_num, img); cvNamedWindow ("Image", CV_WINDOW_AUTOSIZE); cvShowImage ("Image", combined_img); cvWaitKey (0); cvDestroyWindow ("Image"); cvReleaseImage (&combined_img); for (i = 0; i < img_num; i++) { cvReleaseImage (&img[i]); } cvFree (&img); return 0; } /* 画像を連結する関数 */ IplImage * combine_image (int num, IplImage ** tmp) { int i; int width = 0, height = 0; IplImage *cimg; CvRect roi = cvRect (0, 0, 0, 0); // (3)与えられた各画像から,連結後の幅と高さを求める for (i = 0; i < num; i++) { width += tmp[i]->width; height = height < tmp[i]->height ? tmp[i]->height : height; } cimg = cvCreateImage (cvSize (width, height), IPL_DEPTH_8U, 3); cvZero (cimg); // (4)ROIを利用して各画像をコピーする for (i = 0; i < num; i++) { roi.width = tmp[i]->width; roi.height = tmp[i]->height; cvSetImageROI (cimg, roi); cvCopy (tmp[i], cimg); roi.x += roi.width; } cvResetImageROI (cimg); return cimg; }

// (1)コマンド引数で指定された画像を全て読み込む
コマンド引数で指定された画像を全て,カラー画像として読み込む.そのなかに1つでも読み込めない画像がある場合には終了する.

// (2)画像を連結する
あらかめ定義した関数combined_img()を呼び出して,画像を横方向に連結する. この例では単純に画像の上辺を揃えて横方向に連結を行うだけであるが, 画像を折り返して連結したり,さらにいわゆる「矩形パッキング問題」をの解を求めることで無駄な領域が小さくなるように連結することもできる. また,このサンプルでは連結する関数combined_image()に画像のポインタの配列を渡しているが, 可変引数を利用(stdarg.h)して,combine_image()を次のように定義する方法もある.

IplImage*
combine_image(int num, ...)
{
  va_list list;
  int i;
  int width = 0, height = 0;
  IplImage *tmp[num];
  IplImage *cimg;
  CvRect roi = cvRect(0, 0, 0, 0);
	
  va_start(list, num);
  for(i=0; iwidth;
    height = height < tmp[i]->height ? tmp[i]->height : height;
  }
  va_end(list);
  cimg = cvCreateImage(cvSize(width, height), IPL_DEPTH_8U, 3);
  cvZero(cimg);

  for(i=0; iwidth;
    roi.height = tmp[i]->height;
    cvSetImageROI(cimg, roi);
    cvCopy(tmp[i], cimg);
    roi.x += roi.width;
  }
  cvResetImageROI(cimg);
  
  return cimg;
}

// (3)与えられた各画像から,連結後の幅と高さを求める
与えられた各画像の幅の合計値を連結後の画像幅(横方向に連結するので)とし, また,与えられた各画像の最大の高さを連結後の画像高さとして, 画像を作成する. 作成された画像を,関数cvZero()により初期化する.

// (4)ROIを利用して各画像をコピーする
各画像のサイズ(幅と高さ)に会わせてROIを設定し,各画像をcvCopy()によりコピーする. マスクは指定しないので,デフォルト値NULLが利用される. また,最後に関数cvResetImageROI()を利用して,設定したROIをリセットする事をを忘れないように注意.

実行結果例

OpenCV-1.0 リファレンス マニュアル
OpenCV-1.1pre リファレンス マニュアル
OpenCVサンプルコード


画素値の直接操作
部分画像のシャッフル
画像の連結
画像のコピー
画像形状の変形
タイリング
画像の反転
逆行列(擬似逆行列)の計算
色空間の写像
離散フーリエ変換
階層構造を持つ輪郭の座標取得
図形の描画
ポリゴンの描画
凸ポリゴンの描画
テキストの描画
IplImage構造体情報の保存
マップのシーケンスを保存
IplImage構造体情報の読み込み
マップのシーケンスを読み込む
K-means法によるクラスタリング
クラスタリングによる減色処理
エッジの検出
コーナーの検出
並進移動のためのピクセルサンプリング
回転移動のためのピクセルサンプリング
画像のサイズ変更
画像のアフィン変換(1)
画像のアフィン変換(2)
画像の透視投影変換
全方位画像の透視投影変換
モルフォロジー変換
平滑化
ユーザ定義フィルタ
境界線の作成
画像の二値化
画像の二値化(大津の手法)
画像ピラミッドの作成
画像ピラミッドを用いた画像の領域分割
平均値シフト法による画像のセグメント化
Watershedアルゴリズムによる画像の領域分割
輪郭の検出と描画
画像のモーメントを計算
ハフ変換による直線検出
ハフ変換による円検出
距離変換とその可視化
不要オブジェクトの除去
ヒストグラムの描画
ヒストグラム間の距離
二次元のヒストグラム
バックプロジェクションパッチ
ヒストグラムの均一化
テンプレートマッチング
形状のマッチング
点列を包含する矩形
輪郭領域の面積と輪郭の長さ
二つの矩形を包含する矩形
楕円のフィッティング
点列を包含する図形
動的背景更新による物体検出
snakeによる輪郭追跡(静止画)
オプティカルフロー1
オプティカルフロー2
オプティカルフロー3
Condensation
顔の検出
カメラキャリブレーション
歪み補正
マップを利用した歪み補正
サポートベクターマシン
画像の各ピクセル値を特徴ベクトルとしたSVMの学習
画像の各ピクセル値を特徴ベクトルとしたSVMによる物体検出
マウスイベントの取得
トラックバーの利用
カメラからの画像キャプチャ
動画としてファイルへ書き出す
ラベリング