株式会社インデペンデンスシステムズ横浜

システム開発エンジニアの西田五郎が運営しております。Raspberry Pi や Arduino その他新規開発案件のご依頼をお待ちしております。

OpenCV

OpenCV2 cv::Matクラスの基礎

投稿日:2014年6月8日 更新日:

0001OpenCV2のcv::Matクラスの基礎についてです。OpenCV 2.0からはC++のインターフェースが追加されました。cv::MatクラスはそのC++インターフェースで画像を扱うクラスです。まずこのクラスの基礎を理解してみようと思います。Matという名前である通り、このMatクラスは行列でもあります。つまり、行列で画像を表現して管理しているということです。このあたりをプログラムで確認してみます。ここでのスクリーンショットはこのcv::Matクラスで生成した単色の画像です。

ここでのバージョンは、OpenCV 2.4.8で、開発環境は、Microsoft Visual Studio Express 2013 for Windows Desktopです。OpenCVの導入はNuGetを使っています。(以下参照)
NuGetでOpenCVを導入する

今回の内容についてより詳細が必要な場合は以下等を参照して下さい。
cv::Matの基本処理 OpenCV-CookBook
OpenCV 2.x の入門 画像の簡単操作

それでは本題です。以下、コンソールアプリケーションでのプログラムです。まずは、行列としてMatを使ってみます。3×3の要素を持つ行列を定義して簡単な演算を実行しています。

#include "stdafx.h"

#include <iostream>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>

using namespace cv;
using namespace std;

/*-----------------------------------------
	行列演算テスト関数
------------------------------------------*/
void  matTest1()
{
	//行列 mat1 を生成
	unsigned char data1[] = { 3, 2, 1, 4, 5, 6, 1, 2, 3 };
	Mat mat1(3, 3, CV_8U, data1);

	//行列 mat2 を生成
	unsigned char data2[] = { 2, 1, 3, 6, 4, 7, 8, 9, 10 };
	Mat mat2(3, 3, CV_8U, data2);

	//関数名表示
	cout << "-- matTest1() -- " << endl;

	// mat1とmat2をそれぞれ表示
	cout << "mat1 =" << mat1 << endl << endl;
	cout << "mat2 =" << mat2 << endl << endl;

	// mat1 + mat2 と mat1 * mat2 を表示
	cout << "mat1+mat2 =" << mat1 + mat2 << endl << endl;
	cout << "mat1*mat2 =" << mat1.mul(mat2) << endl << endl;

	return;
}

これを別途 main()関数から実行すると、以下のような出力になります。
0003

ここで確認したいことは、確かに行列を扱うことが出来るということだけです。これを踏まえて次のプログラムで簡単な画像を生成してその画像の情報を表示してみます。(ラベンダー色というのは適当です。RGBそれぞれの要素に適当な値が入る色だったという程度です。)

#include "stdafx.h"

#include <iostream>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>

using namespace cv;
using namespace std;

/*---------------------------------------
Matでの単純画像生成とその情報表示
-----------------------------------------*/
void matImage1()
{
	 //関数名表示
	 cout << "-- matImage1() -- " << endl;

	 //ラベンダー色系の画像生成
	 Mat lavender(Size(320, 240), CV_8UC3, Scalar(184, 101, 204));

	 //この画像の情報を表示
	 cout << "行数 = " << lavender.rows << endl;
	 cout << "列数 = " << lavender.cols << endl;
	 cout << "次元数 = " << lavender.dims << endl;

	 cout << "チャンネル数 = " << lavender.channels() << endl;
	 cout << "1画素のバイト数 = " << lavender.elemSize() << endl;

	 cout << "タイプ CV_8UC3 = " << CV_8UC3 << endl;
	 cout << "タイプ(ID) = " << lavender.type() << endl;
	 cout << "タイプ CV_8U = " << CV_8U << endl;
	 cout << "画像の深さ = " << lavender.depth() << endl;

	 //表示
	 imshow("labender", lavender);

	 //キー入力待ち
	 waitKey(0);

	return;
}

これを実行すると、コンソールには以下の情報が出力されます。画像は冒頭のスクリーンショットが表示されます。

— matImage1() —
行数 = 240
列数 = 320
次元数 = 2
チャンネル数 = 3
1画素のバイト数 = 3
タイプ CV_8UC3 = 16
タイプ(ID) = 16
タイプ CV_8U = 0
画像の深さ = 0

(プログラムでの出力は以上です。)

間違いなく Mat lavender()で指定した値が入っているのですが、これを順に見ていきます。

行数:240、列数:320でこれが画像のx、yのサイズです。
次元数は、x、yの2次元です。

チャンネル数は、RGBの3チャンネルです。
1画素のバイト数は、3バイトでRGBそれぞれ1バイトです。

タイプは、CV_8UC3でdefineされている値で、3個のCV_8Uで表現するカラー画像の画素値です。
画像の深さのCV_8Uは、符号なしの8ビット整数で、C言語では、unsigned charで表現される型です。
(確かに RGBそれぞれunsigned charの範囲で表現しています。Scalarクラスは、4要素の要素ベクトルを表現できるクラスでここでは3要素を使っています。詳細は以下を参照して下さい。)
Scalarクラス

ここで今回のポイントです。画像のデータがどのようにMatクラスで表現されているかを理解すれば、Matクラスを画像として使いこなしていけるのではということです。

今回はここまでです。

行列の演算部分は以下の書籍の「Chapter.3 リファレンス編 cv::Matの基本処理、画像処理」を見ながら書きました。もちろん値や書き方は変えています。

AdSense

AdSense

-OpenCV

執筆者:

関連記事

OpenCVをWin32ベースで利用する(その5)GUIコントロールの追加

OpenCVをWin32ベースで利用するの5回目です。前回の4回目で一度終了したのですが、画面上の入出力用のコントロール、つまり、ラベル、エディット、コンボ等のコントロールがなかったので追加してみまし …

NuGetでOpenCVを導入する

Visual Studio Express 2013 for Windows Desktopの開発環境でNuGetを使ってOpenCVを導入してみました。その方法についてです。 まずは、OpenCV( …

Visual Studio Community 2013のVisual C++でOpenCVを使う

Visual Studio Community 2013のVisual C++でOpenCVを使う方法についてです。Visual Studio Community 2013については前回書きましたが、 …

OpenCVでのORBによる特徴点抽出とマッチング(その2)GUIの利用

OpenCVでのORBアルゴリズムによる特徴点抽出とマッチングの処理についての2回目です。前回はVisual Studio Community 2013のVisual C++コンソールアプリでORBに …

OpenCVで輪郭抽出から隣接領域の切り出し(その1)輪郭抽出まで

OpenCVで画像内の輪郭抽出からその輪郭の隣接領域(四角形)を求めてその領域を切り出すという処理を作ってみました。以下の画像がその結果の例です。(※実画像サイズは大きめです。) ここでの処理結果画像 …