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

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

*

OpenCV2 cv::Matクラスの基礎

      2015/04/23

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の基本処理、画像処理」を見ながら書きました。もちろん値や書き方は変えています。

 - OpenCV

AdSense

AdSense

  関連記事

NuGetでOpenCVを導入する

Visual Studio Express 2013 for Windows D …

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

OpenCVで画像内の輪郭抽出からその輪郭の隣接領域(四角形)を求めてその領域を …

OpenCVをWin32ベースで利用する(その1)ダイアログベースアプリ

OpenCVをWin32ベースのアプリケーションで利用してみます。今回はまず、W …

OpenCVでのORBによる特徴点抽出とマッチング(その1)基本的な使い方

OpenCVでのORBアルゴリズムによる特徴点抽出とマッチングの処理についてです …

Tesseract-OCRの導入(その3)OpenCVの出力を認識する

Tesseract-OCRの導入の3回目です。前回はvc++のコンソールアプリか …

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

OpenCVでのORBアルゴリズムによる特徴点抽出とマッチングの処理についての2 …

OpenCVで輪郭抽出から隣接領域の切り出し(その2)輪郭の直線近似と切り出し

OpenCVで画像内の輪郭抽出からその輪郭の隣接領域(四角形)を求めてその領域を …

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

OpenCVをWin32ベースで利用するの5回目です。前回の4回目で一度終了した …

OpenCVで輪郭抽出から隣接領域の切り出し(その3)凸包の取得

OpenCVで画像内の輪郭抽出からその輪郭の隣接領域(四角形)を求めてその領域を …

OpenCVで背景差分とテスト的な動体検知

OpenCVで背景差分を試してみました。あとテスト的な動体検知も試してみました。 …