プロが教えるわが家の防犯対策術!

MATLABのrbboxについての質問です。
MATLABである画像の領域内の情報を取得できるようにしたいのですが、調べてみると、rbboxという関数を使って出来るらしいです。実際にMATLABのHPにあったソースコードを動かしてみると、画像にマウスでドラッグした領域の枠が描かれるのですが、その画像の領域をどうやって処理を行えるように出来るのかがわかりません。出来れば教えてほしいです。rbboxのソースコードを下に示します。宜しくお願いします。

figure;
pcolor(peaks);
k = waitforbuttonpress;
point1 = get(gca,'CurrentPoint'); % ボタンダウンの検出
finalRect = rbbox; % figure単位の出力
point2 = get(gca,'CurrentPoint'); % ボタンアップの検出
point1 = point1(1,1:2); % x と y の抽出
point2 = point2(1,1:2);
p1 = min(point1,point2); % 位置と大きさの計算
offset = abs(point1-point2); %
x = [p1(1) p1(1)+offset(1) p1(1)+offset(1) p1(1) p1(1)];
y = [p1(2) p1(2) p1(2)+offset(2) p1(2)+offset(2) p1(2)];
hold on
axis manual
plot(x,y,'r','linewidth',5) % ボックスの回りに選択した領域の描画

A 回答 (2件)

ANo.1のKulesです。


ん~まあ先に切り出す先の行列を用意しといて
2重のforループで1個ずつ取り出してもいいんですが、
そんなことしなくても行列を行列として扱えて
表現がすっきり☆するのがMatlabのいいトコロ(?)なので
それを利用しましょう。
答えを書いちゃうと1行で終了なんですが(笑)、
それだと何をしているのかさっぱりだと思うんで
簡単な解説を付けておきます。

・[]内の行列表現において、,(カンマ)は横連結、;(セミコロン)は縦連結を表す
例えばA=[1,2,3]と書けばAは横ベクトル、A=[1;2;3]と書けばAは縦ベクトルになります。
,はスペースで代用できますが、迂闊にスペースを使うと混乱するので私は,を使うようにしています。
;も改行で代用できますが、これもやっぱり混乱を招くので;を使った方がいいでしょう。
,と;を使えば行列は作れますが、各列での要素数、各行の要素数が一致していないと
(要はちゃんとした長方形の行列になってないと)当然エラーになります。

・:(コロン)は大きく2つの使い方がある。(1)単調数列を作る(2)ワイルドカードとして使う
(1)(初項):(増分):(末項)で単調数列が作れます。ただし、初項と増分の値によっては末項にならないことがあるので、
その場合末項を超えない最大の値が末項になります。(1:2:10とした場合、末項は9)
増分は負の値も取れます。また、1の場合は省略することもできます(その場合:は1つでよい)
これを使ったベクトルは、基本的に横ベクトルです。
(2)基本的に「全部」を表します。説明はもう少し後に書きます。

・'(シングルコーテーション)は転置を表す
まあ行列から値取り出したりするだけなら使わないと思いますが。

・ベクトルから要素を取り出すには()を使う。()内では行列も使える。
A=1:10;とした時、例えば3つ目の要素を取り出すにはA(3)とします。
3つ目と5つ目の要素を取り出したければA([3,5])とします。
この時、A([3;5])としても結果は同じです。縦ベクトルか横ベクトルかは
Aがどちらであるかに依存します。
A([1,3,5])とする時と、A(1:2:5)とする時は同じ結果が出ます。
最後の要素(今回は10)を指定する代わりに、endを使うこともできます。
さらに、A([3,5;4,6])とした場合、()の中が行列の形になってるので、出てくる結果も行列になります。
この時の行列のサイズは、()内に書いた行列のサイズに一致します。

・行列から要素を取り出すには、(行,列)の順に指定。それぞれに行列を使用できる。
A=magic(10)とすることで10×10の行列ができますが、この中の上から3行目、左から2行目を取り出すには
A(3,2)とします。上から3行目、左から2列目と4列目を取り出すには
A(3,[2,4])とします。上から3行目と5行目、左から2列目と4列目を取り出すには
A([3,5],[2,4])とします。(合計4つの値が取り出され、2×2の行列になります)
上から3行目を全部取りだしたい時は、A(3,:)とします。ここの:が上に書いた「ワイルドカード」の意味です。
行、列にそれぞれ行列を指定することはできますが、取り出され方が複雑になるのであまりオススメしません。
(どうなるかは自分で確かめてみると面白いかも知れません)

と、ここまでの話を理解いただけると、
>RectLeft列からRectRight列までで、RectTop行からRectBottom行までのデータをどうすれば切り出すことができるのか
というのが、イメージデータをCdataとした時、
Cdata(RectTop:RectBottom,RectLeft:RectRight)となることはわかると思います。
(これでもまだいくらかの話はすっ飛ばしてますが)

長文失礼しました。参考になれば幸いです。
    • good
    • 0

先の質問で知らぬ間に昔私の回答したFigureTrimのプログラムを引用されてたKulesです。


あの関数あまりエラーに強くないんですよね…あの段階では。
あの後さらに個人的に作りなおしたやつはいい感じなんですが。

さて、このプログラム上においてのポイントは、
finalRectにはfigure内での[左端 下端 幅 高さ]の値がピクセル値で出ており、
point1,point2にはaxes内での座標が出ているということです。
で、欲しいのは画像内のデータということなので、
「point1,point2が画像データ(xdata、ydata、zdata、Cdata)においてどの範囲なのか」
を考えればよいことになります。
まあ普通にpcolorとかで絵を描けばxdata、ydataは整数値の座標で、Cdataもそれに対応した
各ピクセルの色を出しているかと思います。ですので、
point1、point2の座標をroundか何かで整数値に直してやり、Cdataを切り取るインデックスを
作ればいいのではないかと思います。
具体的には、

RectTop=min([point1(2),point2(2)]);←ボタンを押したところと離したところのうち、y座標が大きい方
RectBottom=max([point1(2),point2(2)]);
RectLeft=min([point1(1),point2(1)]);
RectRight=max([point1(1),point2(1)]);

としてやれば、RectLeft列からRectRight列までで、RectTop行からRectBottom行までの
データを切り出せばよい、ということになります。

まあこの辺りは先の質問で引用されていたFigureTrimの中で、Cutという関数の中を見てもらえれば
よいかと思われます。
コメントをほとんど書いていないため、何をしているかわからないところに関しては補足していただければと思います。

結論からすると今回の用途においてrbboxは要らないですね(笑)使って書けなくもないと思いますが。

以上、参考になれば幸いです。

この回答への補足

ご丁寧に回答ありがとうございます。
しかしながら、RectLeft列からRectRight列までで、RectTop行からRectBottom行までのデータをどうすれば切り出すことができるのかがわかりませんでした。出来れば教えていただけませんか。

補足日時:2010/07/30 16:31
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!