MISTのコンテナの使い方 - mist-team/mist GitHub Wiki
まず,一口に画像といっても「2値画像」「グレースケール画像」「カラー画像」と何種類もあります. それに対し,画像処理のフィルタなどでは,どんな画像に対する処理でも「平滑化フィルタ」「差分フィルタ」等と呼ばれています. このような機能を実現するために,MISTではテンプレートの機能をふんだんに利用しています.
「2値画像」「グレースケール画像」「カラー画像」といっても,要素が異なるだけで,どれも画像という意味では同じです. そこで,画像という入れ物を用意し,中身にいろんな要素(2値,グレースケール,カラー)を入れられるようにします. また,画像に対するアルゴリズムには,汎用的(どのような要素でも動作する)なものと特殊(特定の要素でのみ動作する)なものがあります. そこで,C++の「多重定義」の機能を使って,同じ名前で複数の要素に対するアルゴリズムを準備しています.
画像や音声などは,基本的には1・2・3次元の信号の並びであると考えることができます.それを利用して,MISTでは音声・画像・行列はそれを構成する要素の1・2・3次元の並びであるとして処理を行っています.
MISTのコンテナ(画像や音声を扱う)には,主に次のようなものがあります.
- array … STLに準拠したメモリ上で連続となる1次元配列であり,音声・画像・行列の全てのデータの基底クラス
- array1 … 音声を扱うための1次元配列
- array2 … 2次元画像を扱うための画像クラス
- array3 … 3次元画像を扱うための画像クラス
- matrix … 任意の行列を扱うためのクラス(Expression template を利用した高速な演算が可能)
- vector … N次元ベクトルを扱うクラス
これに加えて,補助的なクラスとして次のようなものもあります.
- marray … 1・2・3次元画像の縁にマージンを持った画像を扱うクラス
- buffered_array … 画像の一辺が2の指数乗となる画像を扱うクラス
- set … 要素の集合を扱うクラス
また,コンテナの要素として次のようなものがあります.
- rgb … カラー画素を扱うクラス
- binary … 2値画素を扱うクラス
- stereo … ステレオ音声を扱うクラス
- quaternion … 四元数を扱うクラス
- integer … 多倍長整数を扱うクラス
- decimal … 多倍長浮動小数を扱うクラス
- vector2 … 2次元ベクトルを扱うクラス
- vector3 … 3次元ベクトルを扱うクラス
前置きはこれくらいにしておいて,画像を確保することからはじめてみましょう. MISTを利用するためには,必ず mist/mist.h ヘッダファイルを必ずインクルードします.
#include <mist/mist.h>
こんな感じで,利用したい場所の先頭に必ずインクルードしてください. また,MISTはC++を利用しているので,iostream をインクルードする必要があります.
#include <iostream>
#include <mist/mist.h>
この2つのヘッダを必要なところに書いてください.
次に,MISTでは,音声や画像の要素が何であるかをまず決めることから始めます.すでにSTLなどを利用されている方であれば,コンテナの要素と同じと考えていただければ分かりやすいと思います.例えば,グレースケールの画像であれば,要素はunsigned char
を利用できるし,カラー画像であれば,mist::rgb< unsigned char >
というものも画像の要素になります.
2次元画像を利用する場合は,mist::array2
を利用して次のように書きます.
mist::array2< unsigned char > image( 500, 500 );
こう書くことで,各要素がunsigned char
の2次元画像を利用することができます.また,カラー画像ならこんな感じに書きます.
mist::array2< mist::rgb< unsigned char > > image( 500, 500 );
また,この例では初期化時点で500×500の画像を用意しています. ここで,unsigned char
でなくてdouble
に置き換えてもなんら問題はありません. そこが,MISTのいいところです. また,アロケータという概念も利用できるのですが,ここでは割愛します(詳しく知りたい人はSTLを勉強してください).
そして,MISTのコンテナ内の各要素は,画像確保時に初期値(通常はデフォルトコンストラクタ,算術型では 0 )で初期化されるようになっています.
画像を確保しただけでは何にもうれしくありません. それぞれの要素にアクセスできて,はじめて意味があるわけです. MISTでは,各要素へのアクセスは括弧演算子というものを利用します. 具体的には次のような画像を確保したとします.
mist::array2< mist::rgb< unsigned char > > image( 500, 500 );
この image の (100, 50) の要素に 1 を代入するならこう書けばOKです.
image( 100, 50 ) = 1;
要素の値をとってくる場合でも同じように書けばOKです. ただし,ここで指定した (100, 50) の要素が存在することが条件です. つまり,100×100で確保した画像の (200, 50) の要素を取得・設定することはできないということです. 非常に簡単ですが,これだけできれば音声・画像を自由にアクセスすることができるようになります.
また,C/C++言語の配列と同じように,MISTの画像も要素の開始インデックスは 0 から始まります. 要するに幅100の画像を確保した場合のインデックスの範囲は 0 ~ 99 になるので注意してください!!
画像の各要素を何らかの値で初期化したいことがよくあります. そんなときは, fill 関数を利用します. MISTではSTLと同じ処理内容の関数があれば,同じ名前を採用するようにしています. なので,STLに存在している fill 関数と同じ名前となっています. 使い方はいたって簡単で,コンテナ内の全要素を初期値(通常はデフォルトコンストラクタ,算術型では 0 )で初期化する場合には,
image.fill( );
と書けばOKですし,値を指定して要素を初期化したい場合は,
image.fill( 255 );
と書きます.
もう使用しなくなった画像が利用しているメモリを,明示的に開放したい場合は次のように書きます.
image.clear( );
こう書くことで,要素数0の画像となります. また,MISTの画像コンテナは,画像オブジェクトのスコープが外れた時点(デストラクタの呼び出し時)で自動的にメモリを開放してくれるので,通常は clear 関数を呼び出す必要はありません.
ある画像のサイズを変更したい場合は,リサイズ関数を利用します.
image.resize( 100, 200 );
こう書くことで,100×200の画像に変更されます. ただし,リサイズ関数を呼び出しても,画像内の各要素が初期化されるとは限りません. MISTでは,必要なメモリ量が変わったときにのみ全要素を初期化します. そのため,必ずリサイズ後に全要素を初期化したい場合は,前述の fill 関数を利用してください.