OpenCV 3.0に果敢に挑戦し続けてみる

個人的な趣味の一環として、OpenCV 3.0がらみの情報をまとめてみる。「引用はいぃんよー、無断転載はあかんよー」ということで。

イントロダクション:Fixed Pixel Types. Limited Use of Templates

 Fixed Pixel Types. Limited Use of Templates

 

Templatesは、データ構造とアルゴリズムに関して、便利で効果的でそのうえ安全な実装を実現する、C++の非常に素晴らしい機能である。しかし、Templatesを大々的に用いた時のコストはコードサイズの実行時間を増加させてしまう。一方で、templateを排他的に用いた場合にはインタフェイスと実装を分離する事が難しくなる。これは基本的なアルゴリズムについて問題ないが、1つのアルゴリズムが数千行のコードに及ぶコンピュータビジョンのライブラリでは宜しくない。このため、そして、またTemplateを完全に持たない、あるいは持っていても制約があるような、Python, Java, Matlab等の他の言語bindingでの開発をシンプルにするために、現在のOpenCV実装はポリモーフィズムとtemplatesを通した動的ディスパッチングを基にしている。動的ディスパッチングを用いている個所(例えば画素を制御する演算子)は非常に遅くなる箇所において、(訳者メモ:実用上において)不可能な部分(一般的な Ptr<> 実装)あるいはとても不便な部分(saturate_cast<>())に対して、現状の実装では小さなtemplate class、methodや関数を導入している。現状のOpenCV versionではその他の個所ではtemplatesの利用に制限を課している。

  

その結果、ライブラリが処理するプリミティブなデータタイプの制約付きの集合が固定化されている。これは、以下のタイプのいずれかの配列のエレメントである。

  • 8-bit unsigned integer (uchar)
  • 8-bit signed integer (schar)
  • 16-bit unsigned integer (ushort)
  • 16-bit signed integer (short)
  • 32-bit signed integer (int)
  • 32-bit floating-point number (float)
  • 64-bit floating-point number (double)
  • (1つ以上の)全てが同じタイプとなるような複数のエレメントの組。そのような組のエレメントによる配列は、複数チャンネルの配列と呼ばれる、その一方でシングルチャネルの配列はそのエレメントがスカラー値である。チャンネルの最大数はCV_CN_MAXで定数として決められており、現状では512である。

この基本タイプに対して、下記enum値が与えられている

enum { CV_8U=0, CV_8S=1, CV_16U=2, CV_16S=3, CV_32S=4, CV_32F=5, CV_64F=6 };

複数チャンネル(n-channel)タイプは、下記のオプションを用いて定義される。

  • CV_8UC1 ... CV_64FC4 :定数 (チャンネル数は1から4)
  • CV_8UC(n) ... CV_64FC(n) or CV_MAKETYPE(CV_8U, n) ... CV_MAKETYPE(CV_64F, n)マクロは、4よりも大きいあるいはコンパイル時に決定できない場合に用いる。

Note

 

CV_32FC1 == CV_32FCV_32FC2 == CV_32FC(2) == CV_MAKETYPE(CV_32F, 2), and CV_MAKETYPE(depth, n) == ( (x&7)<<3) + (n-1). これは、depthから形成された定数タイプは、下位3bitに保持され、そしてチャンネル数から1を引いた値が次のlog2(CV_CN_MAX) bitに格納される。

 

Examples:

Mat mtx(3, 3, CV_32F); // make a 3x3 floating-point matrix
Mat cmtx(10, 1, CV_64FC2); // make a 10x1 2-channel floating-point
                           // matrix (10-element complex vector)
Mat img(Size(1920, 1080), CV_8UC3); // make a 3-channel (color) image
                                    // of 1920 columns and 1080 rows.
Mat grayscale(image.size(), CV_MAKETYPE(image.depth(), 1)); // make a 1-channel image of
                                                            // the same size and same
                                                            // channel type as img

OpenCVを利用している場合、複数のエレメントを組み合わせた配列は生成する事も処理する事も出来ない。更に、いくつかの関数やmethodは、可能なすべての配列タイプのサブセットだけを扱う事が出来る。一般的に、複雑なアルゴリズムではサポートしているフォーマットのサブセットは小さくなる。一般的な制限の例を以下に示す。

  • 顔検出アルゴリズムは、8bit grayscaleもしくはcolor imageに対してのみ動作する。
  • 線形台数命令と多くの機械学習アルゴリズムは、浮動小数配列に対してのみ動作する
  • cv::addのような基本的な命令は、全てのタイプをサポートする
  • 色空間変換関数は、8bit unsigned, 16bit unsigned 32 bit floating point typeをサポートする

それぞれの関数でサポートされているタイプのサブセットは、経験から必要となったものが定義され、そして、ユーザからの要求に基づいて将来的に必要になるであろう拡張されている。