読者です 読者をやめる 読者になる 読者になる

OutputArrayOfArraysの使い方

c++ OpenCV

最近、OutputArrayOfArraysの使い方がなんとなくわかってきたので、メモ。

OpenCVには関数引数用の型として、InputArrayやOutputArrayがあります。
引数をこの型にすることで、cv::Matだけでなく、vectorの値も引数に取れるようになります。
使うと関数の汎用性があがります。OutputArrayOfArraysも関数引数用の型のひとつです。

OpenCVは2.4.9を使用。

OutputArrayOfArrays型

関数引数用の型の一つとして、OutputArrayOfArraysという型があります。
これはvectorvector>など、
OutputArrayの配列を意味する型です。

が、それはあくまで人間側の解釈であって、
プログラム的にはOutputArrayのイディオムです。

// <opencv2/core/core.hpp>より
typedef OutputArray OutputArrayOfArrays;

OutputArrayOfArraysの使い方

例えば、OutputArrayの値に対しては、copyToなどで値を格納することができます。
しかし、OutputArrayOfArraysの値に対しては、copyToで値を格納することはできません。

void func ( cv::OutputArrayOfArrays dst )
    std::vector<cv::Mat> mats;
    ...   // matsにデータを格納する処理
    cv::Mat( mats ).copyTo( dst ); // 実行時エラー
}

OutputArrayOfArraysの使い方として、
「メモリ確保のために、明示的にcreate関数を使用する」必要があります。*1
また、メモリ確保後、インデックスを指定してvectorの各要素ごとに値を格納する必要があります。

void func ( cv::OutputArrayOfArrays dst )
    std::vector<cv::Mat> mats;
    ...   // matsにデータを格納する処理
    dst.create( mats.size(), 1, cv::Mat( mats ).type() );
    for( int i = 0; i < dst.rows; ++i ) {
        dst.getMatRef(i) = mats[i];
    }
}

ちなみに、create関数の第3引数にあるcv::Mat( mats ).type()の値は7になります。
CV_USERTYPE1マクロが割り当たっていますが、マクロ名からして、将来的に修正があるかもしれないので、CV_USERTYPE1を直接使用することは避けています。

// <opencv2/core/types_c.h>よりMatrix type
#define CV_8U   0
#define CV_8S   1
#define CV_16U  2
#define CV_16S  3
#define CV_32S  4
#define CV_32F  5
#define CV_64F  6
#define CV_USRTYPE1 7

*1:あくまで現時点で試した限りの話。違う方法があるかも