OpenCVで画像を作るにあたって,サンプルコードでは様々なクラス/構造体を使っている.その歴史も合わせてちょこちょこ書いてく

IplImage

  • オーソドックスな「画像」を保持する構造体
  • OpenCV 1.1時代は盛んに使われていた.
  • 今でもCvMatやcv::Matなどと互換性はちゃんとある
  • 通常はポインタで宣言して,cvCreateImageで実体をallocする
  • 歴史
    • IPLはもともとIntel IPP(Intel Integrated Performance Primitives)*1内の画像処理ライブラリ(Image Processing Library)*2
    • OpenCVの前身というと言い過ぎだけれど,もともとOpenCVはIntelの技術者たちが開発していた
    • その名残りでIPLの名を冠する
  • ヘッダとデータ部からなる
  • ヘッダ部
    • 幅,高さ,チャンネル数,1画素のバイト数などの基本的な情報を保持する
    • 1画素のバイト数はIPL_DEPTH_8UやIPL_DEPTH_64Fなどで指定する
    • IPP時代の名残で様々なメンバ変数が存続してるが,あまり使われてないのが現実
    • メンバ変数の1つ,imageDataがデータ部を指すポインタになっている
  • データ部
    • unsigned char*型の配列
    • ヘッダによれば,charの配列だが,これを信じると痛い目を見る(泣)
    • ラスタスキャンで2次元画像が配列に保存されている
    • なお,imageDataOriginはalloc時の番地を保持しているので,通常は
      imageData == imageDataOrigin
    • であるが,imageDataポインタを別の番地に振り替えても,imageDataOriginが番地を保持しているのでメモリリークは起きない*3

CvMat

  • オーソドックスな行列を保持する構造体
  • IplImageと同様,ヘッダ部とデータ部からなる
  • 通常はポインタで宣言して,cvCreateMatで実体をallocする
  • ヘッダ部
    • 幅,高さ,チャンネル数,1画素のバイト数などの基本的な情報を保持する
    • 1画素のバイトはCV_8UとかCV_32Fなどで指定する
    • チャンネル数も同様にCV_8UC1とかCV_8UC3とかC?で指定する
    • チャンネル数を省略した場合は1チャンネル(画像でいうところの濃淡画像)になる
    • dataというunionのポインタがデータ部を指すポインタになっている
    • IplImageと違い,配列はデータに応じてdoubleやfloatでもよい.
    • data.ptr内の変数をそれぞれ使ってデータ部にアクセスする
  • データ部
    • ラスタスキャンで行列が配列に保存されている

CvArr

  • 実体はvoid
  • 関数の引数が大体の場合CvArr*になっていて,多分初心者は大体躓く.
  • CvMatとIplImageを同列に扱うためにvoidのポインタで宣言されている
  • これを引数として扱う関数は,内部で渡されたポインタが
    • IplImageのポインタか
    • CvMatのポインタか
  • 判断するようにできている

cv::Mat

  • OpenCV 2.0から登場したC++版の画像クラス*4
  • C++版では画像も行列も一様に扱う
  • クラスなので,大量のメンバ関数やoperatorが実装されている
  • 行列同士の掛け算や動的な配列再確保が実装されていて超便利
  • 個人的には,CvMatやIplImageなどの配列に戻る必要性を感じない
  • キャストやcvarrToMatでIplImageやCvMatに変換できる
    1. CvMat *oldMatrix  = cvCreateMat(3, 3, CV_32FC1);
    2. cv::Mat matrix    = cv::cvarrToMat(oldMatrix);
    3. CvMat _stub       = (CvMat)matrix;
    4. CvMat *oldMatrix2 = &(_stub);
  • 個人的には行列の演算を通常の四則演算の用に書けるのが嬉しい
    1. cv::Mat A(3, 3, CV_32F);
    2. cv::Mat B(3, 3, CV_32F);
    3. cv::Mat C(3, 3, CV_32F);
    4. C = A - B;
    5. C = A + B;
    6. C = A * B;

cv::InputArray

  • Revision 4885*5 から導入されたInputArray
  • proxy type とChangeLogに書かれている
  • OpenCV 2.3以降に相当する
  • 変換関数やキャストせずに,どんな配列も受け取る為の型
  • Matはもちろん,Point,Point3やVecなどのデータも同じようにやり取りできる
  • C++版のCvArr*に近い存在
  • 基本的にInputArrayはMat&と読み替えて構わない.
  • 以下がtypedef文(OpenCV 2.4.1)
    1. typedef const _InputArray& InputArray;
    2. typedef InputArray InputArrayOfArrays;
    3. typedef const _OutputArray& OutputArray;
    4. typedef OutputArray OutputArrayOfArrays;
    5. typedef OutputArray InputOutputArray;
    6. typedef OutputArray InputOutputArrayOfArrays;
  • InputArrayとInputArrayOfArraysは _InputArray& で Mat&と読み替えられる
  • OutputArrayとOutputArrayOfArraysとInputOutputArrayとInputOutputArrayOfArraysは _OutputArray& で Mat&と読み替えられる

ジャンル:OpenCV:OpenCV 1.0:OpenCV 1.1:OpenCV 2.0:OpenCV 2.1:OpenCV 2.2:OpenCV 2.3:OpenCV 2.4準拠 *6 *7


*1  Integrated Performance Primitives - Wikipedia
*2  Intel Performance Libraly
*3  dandelion's log » cvReleaseImageの挙動について
*4  Changeset 1611 - OpenCV
*5  Changeset 4885 - OpenCV
*6  OpenCV - Wikipedia (日本語)
*7  OpenCV - Wikipedia (English)

トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2012-07-04 (水) 14:12:10 (1969d)