おぺんcv

画像処理エンジニアのブログ

3次元のcv::Matを作る

はじめに

小ネタです
cv::Matが多次元に対応しているのを知ったのでメモ

作り方

多次元Matのコンストラクタがこちら(mat.hppより抜粋)
ndimsで次元数を、sizesで各次元の長さを、typeで要素の型を指定します

    /** @overload
    @param ndims Array dimensionality.
    @param sizes Array of integers specifying an n-dimensional array shape.
    @param type Array type. Use CV_8UC1, ..., CV_64FC4 to create 1-4 channel matrices, or
    CV_8UC(n), ..., CV_64FC(n) to create multi-channel (up to CV_CN_MAX channels) matrices.
    */
    Mat(int ndims, const int* sizes, int type);

サンプル

2×3×4のint行列を作ってみました

#include <opencv2/opencv.hpp>
#include <iostream>

int main()
{
	const int ni = 2, nj = 3, nk = 4;
	const int ndims = 3;
	const int sizes[ndims] = { ni, nj, nk };

	cv::Mat m(ndims, sizes, CV_32S);
	
	for (int i = 0; i < ni; i++)
		for (int j = 0; j < nj; j++)
			for (int k = 0; k < nk; k++)
				m.at<int>(i, j, k) = i + j + k;

	for (int i = 0; i < ni; i++)
		for (int j = 0; j < nj; j++)
			for (int k = 0; k < nk; k++)
				std::cout << i << "+" << j << "+" << k << " = " << m.at<int>(i, j, k) << std::endl;

	// std::cout << m << std::endl; // OpenCV Error: Assertion failed (m.dims <= 2)

	return 0;
}

(i, j, k)で要素にアクセスできるのが素晴らしいです
ちなみに、coutで表示しようとしたらassertに引っかかりました
dims <= 2までしか表示できないようです

おわりに

今までcv::Matは2次元しか対応してないと勝手に思っていて
3次元のデータを扱う際はcv::Matではなく生ポインタつかってました
早く気付いていれば良かったと思う今日この頃…