2012/11/11

知っておきたいMatのゴリ知識

OpenCVの重要な型 Mat

OpenCVでは画像をMat型として扱う。
Matの扱い方がわかれば、画像を自由に操れる。
ここでは、「知っておくと得するMat豆知識」をご紹介しよう。
なお、この投稿では輝度画像のみを対象とする。

Matの要素を取得

Mat image(Size(100, 200), CV_8U, Scalar::all(0));
uchar pixel = image.at<uchar>(100, 50);
素朴なプログラムでは各要素にアクセスすることが多くなる。
at<データ型>(y, x) だ。データ型を指定する必要があるってことと、x, yの順番が逆なことに注意だ。
どうして(x, y)じゃないのか?
それは行列だから。(行、列)の順に指定するのだ。
(ちなみにメモリ上でも行ごとにまとまっている。 のちのち重要になってくる知識)

このatはデバッグモードだと非常に遅い。リリースモードだとそれなりに高速に動く。
全要素にアクセスする際は速度も気になる。
高速にピクセルにアクセスする方法も用意されている。
しかし、それよりも本当に全要素にアクセスする必要があるか、考察しよう。

Matのデータ型を変換する

CV_8Uでは0から255の整数しか扱えず、負値や255を超える値、小数点が扱えない。
そういうときはデータ型を変更しよう。
Mat image(Size(100, 200), CV_8U, Scalar::all(0));
Mat tmp;
image.convertTo(tmp, CV_32F, 1.0/255);
第3引数を1.0/255としたのは、スケールを変えるため。
CV_8Uでは画像は0から255までの整数で表現される。
CV_32F、つまりfloat型にしたときには255という数字に特別な意味はなく、0から1の実数値で扱いたい。
そこですべての値に1.0/255を掛けたのだ。

Matをコピーする

Mat image(Size(100, 200), CV_8U, Scalar::all(0));
// 完全なコピー
Mat tmp1 = image.clone();
// 画像のサイズとデータ型のみコピー
Mat tmp2(image.size(), image.type(), Scalar::all(127));
コピーはクローン関数で行う。
同じ大きさ、同じデータ型のMatを作成する機会は多いので、合わせて覚えておこう。

Matの一部を選択する

Mat image(Size(100, 200), CV_8U, Scalar::all(0));
// 矩形領域(x, y, width, height)を選択
Mat regionOfImage(image, Rect(x, y, width, height));
// 第x列選択
Mat colOfImage = image.col(x);
// 第y行選択
Mat rowOfImage = image.row(y);
選択してもコピーされるわけではない。
選択したMatの一部に対してのみ、処理を行うことができる。
GaussianBlur(regionOfImage, regionOfImage, Size(5, 5), 1.0);

0 件のコメント:

Related Posts Plugin for WordPress, Blogger...