dポイントプレゼントキャンペーン実施中!

MATLABのGUIについて教えていただけないでしょうか。
今、128x128pixelの画像が40枚でセットになっているデータ(人間の脳みそのMRI画像なんですが)がmatファイルに保存されています(変数tempA. size(A) = 128x128x40)。これをGUIで読み込んでスライドバーで次々に切り替えて表示したいのですが、うまくいきません。(つまり40枚のうちの1枚が表示された状態でスライドバーを動かすと残りの39枚が順番につぎつぎ表示される状態にしたい)
GUIDEを使ってuiloadでmatファイルを読み込んで表示するところまではいいのですが、スライドバーのCallback内に slider1=findobj('tag','slider1');slice=round(get(slider1,'value'));image(tempA(:,:,slice));
と記述すると、tempAは定義されていないとエラーが返ってしまいます。同じMファイル内で一度は使われている変数なのに??
どなたか解決策を教えていただけないでしょうか。
UICONTROLのvalueを表示された画像にリアルタイムに反映するにはどのような方法がありますか?
よろしくお願いいたします。

A 回答 (2件)

再びKulesです。



>「set(H.image,'Cdata',H.tempA(:,:,SliceNum));」
>の部分で「??? サブスクリプトインデックスは正の実数整数, またはロジカルである必要があります」
>というエラーになるのですが…

このエラーは実は回答してからすぐに気づいたのですが、まあスライダをドラッグしたりしなければ問題ないかな…と思って放置してました(笑)

その1行上の
SliceNum=(get(H.slider,'Value'));

SliceNum=round(get(H.slider,'Value'));
に変えて下さい。このプログラム自体はこれで動くと思います。

>これ以外にどんな変数でも好きに格納できる便利なハンドルを作れる、ということなのでしょうか?
変数を格納するハンドルを作る…というよりはguidataは変数を直接figureに格納する関数です。ちょっと実験してみましょう。
figure;
a=guidata(gcf);
b=3;
guidata(gcf,b);
clear all;
c=guidata(gcf);
上の6行をコマンドウィンドウから1行ずつ実行してみてください。
2行目の結果はa=[]、つまり空行列になると思います。
で、4行目で現在のfigureにbの値を格納したことになります。
5行目でワークスペース上には変数がなくなりますが、
6行目でcに先ほど格納した値が入っていることが確認できます。
また、上の例からもわかるように、変数を格納する時と取りだす時で変数名が違っていてもかまいません。なんだったら4行目をguidata(gcf,3)としてもfigureに3という値が格納されます。

今回の場合、どんな変数を保存すればいいかという話ですが、「じゃあ今回の操作をする場合何の値が必要?」を考える必要があります。
実のところを言えば、今回絶対に保存しないといけないのは画像データtempAだけです。それ以外のハンドルとかはguihandleやfindobjで探してやっても構いません。
ただ、いちいち探すのはめんどくさいということで今回は
・各種ハンドル(figure、スライダ、イメージ、軸)
・tempA(画像データ)
を構造体Hとして宣言し、guidata(gcf,H)でfigureの中に格納してます。
先ほどの例でいうと、
H.○○=△△;
となっているのが変数の宣言部(構造体はまだ存在しないメンバ名を宣言すれば勝手に追加されていきます)、guidata(H.figure,H);となっているのが変数を保存している部分、H=guidata(○○);が変数を取り出している部分となります。

ここからは私の勝手な感想ですが…
Matlabはホントに初心者に不親切な言語だなあ…と思います。私自身Matlabに初めて触ってからまだ2年経ってませんが、始めたころは大学の研究室にあった本を読んでもさっぱりでした。
ということで、ヘルプを読んでもネットを読んでもよくわからない~という状態は気にしなくていいと思います。ネット上の情報に関しては、「わかる人にしかわからない」度合は相当高いんじゃないかと個人的には思っているので(笑)
と言ってもじゃあわかんなくていいということではないので、とりあえず私が去年買って勉強に使った本を紹介します。
秀和システム「MATLABハンドブック 第三版」小林一行
ひょっとしたらもう次の版が出てるかも。
400ページぐらいある分厚い本ですが、当面必要なのはChapter 1,(2),5ぐらいです。特にhandleの扱いに関してはChapter5を読み込んでやりましょう。

この本を読んでhandleの扱い方が何となくわかったら、後はMatlabヘルプデスクの、
関数:アルファベット順
http://www.mathworks.co.jp/access/helpdesk_ja_JP …
の中に「~プロパティ」という項目があるので、それをじっくり読んでいくとそれぞれのプロパティの扱いがわかると思います。

長文失礼しました。やっぱりわからんというところがあれば補足欄にお願いします。
参考になれば幸いです。
    • good
    • 0
この回答へのお礼

Kulesさん
何度も教えてくださってありがとうございます。今回のご説明のおかげで、ようやくHandleと構造体の関係がわかりました。今まで何が理解できていなかったのかがようやくわかり、前進できそうです。今回書いていただいたスクリプトの中にはまだよくわからない(知らない)箇所もありますが、これをベースにもう少し勉強して理解してみたいと思います。
本当に助かりました。実はMATLABハンドブックは今回の質問にぶち当たってからWebでの評判を頼りに買ったのですが上記がわかっていなかったために、肝心の所を解決できずにいました。同じような立場の人のために今回のKulesさんの解説を書き加えたい…(^-^;
また後日に別の質問スレッドを立ててしまう可能性もありますが、たまたまお時間おありでしたらまた教えてください。ありがとうございました。

お礼日時:2010/08/06 22:54

CallBack中に変数を使いたい場合、


(1)引数として渡す
(2)どこかに保存しておいて、そこから呼びだす
の2通りが考えられると思います。私の場合、
(1)→(2)(予めmatfileとして保存し、その都度呼び出す)→(2)(guidataを使う)
の順にスタイルが変わっています。
guidataはfigure内に値をストックするための関数で、figure内のハンドルであればどれを使ってもストックした変数を呼び出せるので大変便利です。
ということでそれを使える関数を書いてみました。

function MakeSlider(String,varargin)
switch(lower(String));
case 'make';
InitSlider(varargin{1});
case 'imageslice';
MoveSlice;
otherwise;
error('関数MakeSliderの受け付ける動作は''Make''のみです')
end;
function InitSlider(Handle)
H=guidata(Handle);
H.slider=uicontrol(H.figure,'Style','Slider');
H.image=image(zeros(128,128));
H.axes=gca;
set(gca,'PlotBoxAspectRatio',[1,1,1]);
FigureSize=get(H.figure,'Position');
set(H.slider,'Position',[FigureSize(3)-30,10,25,FigureSize(4)-20]);
set(H.slider,'Min',1,'Max',40,'Value',1,'SliderStep',[1,5]/39);
set(H.slider,'CallBack','MakeSlider(''ImageSlice'');');
guidata(H.figure,H);
return;
function MoveSlice
H=guidata(gcbo);
SliceNum=(get(H.slider,'Value'));
set(H.image,'Cdata',H.tempA(:,:,SliceNum));
return;

「」の間を1つのmファイル(MakeSlider.m)として保存し、
H.figure=figure(1);
H.tempA=tempA;
guidata(H.figure,H);
MakeSlider('Make',gcf);
のようにするとfigureの右端にsliderがつき、上または下矢印を押すことで1枚ずつ画像が変わります。
また、スライダのトラフを押すと一度に5枚先に飛ぶようにしてあります。

この関数自体決め打ちで値を入れているところが多いため
他の設定にするには中の値をいじるか、設定が変わっても柔軟に対応できるようにさらに改良する必要があります。
コメントをほとんどつけていないので、何をしているのかわからない部分があれば補足欄にお願いします。

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

この回答への補足

早速のご回答ありがとうございます。
しかし、せっかくなのですが、うまく理解できませんでした。
guihandle、guidataを用いて変数をやりとりする、という意味はなんとなくわかるのですが、どんな変数をどうやって保存するのか理解できません。本当に初歩的な問題なのだと思うのですが、ヘルプを読んでもネットを検索してもよくわからないんです。
オブジェクト(axisとかPushbuttonとか)はあらかじめデフォルトのハンドルを持っていますよね。これ以外にどんな変数でも好きに格納できる便利なハンドルを作れる、ということなのでしょうか?そのハンドル名はどうやって宣言したらいいのでしょう??
教えていただいたスクリプトを実行してみましたが、
「set(H.image,'Cdata',H.tempA(:,:,SliceNum));」
の部分で「??? サブスクリプトインデックスは正の実数整数, またはロジカルである必要があります」
というエラーになるのですが…このような状況なのでせっかくのサンプルスクリプトをうまくかみ砕けませんでした。
おそらくかなりくだらないことを聞いているのだと思います。お忙しいようでしたら、もし、そんなこと質問する前にこの本を読むといいよ、というような本があれば教えていただけないでしょうか。門外漢な上に周囲に詳しい人もいないのでなかなか本を探すにも苦労しています。
いろいろ申し訳ありません。

補足日時:2010/08/06 01:27
    • good
    • 0
この回答へのお礼

お礼を書かないとベストアンサーがつけられない??試しに記入してみます。

お礼日時:2010/08/06 22:56

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