• ベストアンサー

MATLABのプログラミングについて

マウスのカーソルの移動距離を計測したいのですが、 MATLABでできますでしょうか。 プログラムでどう組み込めばよいのか分らないため質問させて頂きました。 MATLAB初心者のため、詳しい方ご教授のほどお願いします。 左クリック(開始)→マウスを動かす→左クリック(終了) のようにクリックからクリックまでの移動距離を計測したいのです。 できれば、マウスカーソルの軌跡も表示させたいです...。 丸投げで聞いてしまい申し訳ないのですが、 緊急で必要になったため、質問させていただきました。 以下の環境を使っています。  -Windows 7  -R2010b

質問者が選んだベストアンサー

  • ベストアンサー
  • Kules
  • ベストアンサー率47% (292/619)
回答No.3

三度Kulesです。 ん~仕様が簡単に変わってしまうてのもなかなか不信感なんですけどね。 そもそも 左クリック(開始)→マウスを動かす→左クリック(終了) と クリック→ドラッグ→ドロップ だとだいぶ操作感が違うと思うんですが… 最初の仕様の指定はどこから来たものなんですかね? まあとりあえずそれぞれの処理を書きますね。 とりあえず共通で使われる変数名を決めときます。 ax…軸のハンドル f…Figureのハンドル flg_Click…クリック中かを表すフラグ pos…カーソルの軌跡を格納する distanse…カーソルの移動距離を格納する tmp…最終的には必要ない変数。tmp1,tmp2などのように使う。 1)クリック時 function Click %軸の中にimageがあり、なおかつ軸の中にポインタがあり、 さらにflg_Clickがfalseの時だけ実行し、 %それ以外の時はそのままreturnする tmp1=get(ax,'Children'); if ~any(strcmpi(get(tmp1,'Type'),'image');return;end; tmp1=get(ax,'CurrentPoint'); tmp2=get(ax,'Xlim'); tmp3=get(ax,'Ylim'); if tmp1(1,1)<tmp2(1)||tmp(1,1)>tmp2(2)||tmp1(1,2)<tmp3(1)||tmp1(1,2)>tmp3(2);return;end; if flg_Click;return;end; flg_Click=true; pos=tmp1(1,1:2); distanse=0; 2)ドラッグ時 function Drag % flg_ClickがtrueでカーソルがAxes内にある時のみ処理をする if ~flg_Click;return;end; tmp1=get(ax,'CurrentPoint'); tmp2=get(ax,'Xlim'); tmp3=get(ax,'Ylim'); if tmp1(1,1)<tmp2(1)||tmp(1,1)>tmp2(2)||tmp1(1,2)<tmp3(1)||tmp1(1,2)>tmp3(2);return;end; tmp2=pos(end,:); tmp3=sqrt(sum((tmp1(1,1:2)-tmp2).^2)); pos=[pos;tmp1(1,1:2)]; distance=distance+tmp3; 3)ドロップ function Drop % flg_ClickがtrueでカーソルがAxes内にある時のみ処理をする if ~flg_Click;return;end; tmp1=get(ax,'CurrentPoint'); tmp2=get(ax,'Xlim'); tmp3=get(ax,'Ylim'); if tmp1(1,1)<tmp2(1)||tmp(1,1)>tmp2(2)||tmp1(1,2)<tmp3(1)||tmp1(1,2)>tmp3(2);return;end; flg_Click=false; set(ax,'NextPlot','Add'); plot(ax,pos(:,1),pos(:,2)); set(ax,'NextPlot','Replace'); fprintf('移動距離:%f\n',distanse); おまけ:それぞれの関数が思ったタイミングで動作するよう設定 set(f,'WindowButtonDownFcn',Click); set(f,'WindowButtonMotionFcn',Drag); set(f,'WindowButtonUpFcn',Drop); 以上です。関数名、変数名のスペルが怪しいのはご愛嬌ということで。 いくつか注意点を。 1.実際に実行してみるとわかると思いますが、このままでは全く動きません。 多分「axは未定義の関数です」とか何とかいうエラーが出ると思います。 …まあデータのやり取りについてはあなたの書いた処理には書かれていませんでしたしね。 私も「処理の一部」としてわざと書かなかったわけですし。 いじわるを言うようですが、一連の処理を書く時は ・データを読みだす ・処理をする ・データを書きこむ が必要です(もちろん必要がない時もあります) どのようにデータ(軸のハンドルや軌跡の座標など)を読み出し、保存するかを決めなければこの関数達は完成しません。 2.私の作ったものとはかなり違う形になっています。 データをどのようにやりとりするかも含めて1つの関数で全て解決するようにしたため、構成はかなり違うことになっています(構造が複雑になるので読みにくくなってます) 3.例外的な操作をした時想定外の動作をします(下手するとエラーが出ます)。 Axes内でクリック→Axes外までドラッグ→その場でボタンを離す→再びAxes内にカーソルを戻してクリック→Axes内でドラッグ→Axes内でボタンを離す とすると、軌跡は1回目のクリック以降のものからのトータルが示され、距離も最初のクリックからの合計になります。 これは多分望んだ動作ではないですよね?これを回避するためどのようにしますか? また、 Axes内でクリック→Axes外までドラッグ→再びAxes内に戻してからボタンを離す とすると、Axes外に出た点から戻ってきた点が線で結ばれますし、その距離も移動距離に加えられます。 これも多分望んだ動作ではないですよね?これを回避するためどのようにしますか? 失礼を承知できついことを書きますが、 3.が想定できていない時点でまだ仕様すらきちんと固まってないな、と思います。 仕様は基本的に課題などでは人から与えられるものですが、仕様がさらっと変わるところをみるとそういうわけではないんですよね? だとしたら、通常の動作以外にどのようなことが起こるのかを想定して、その時はどのような動作をさせるのかを考える必要があります。 前も書きましたが、仕様→処理を決めるのに必要なのは言語に対する知識ではなく、想像力(自分が考えている通りの動作以外の操作をした時、どのようなことが起こりうるかを考える力)です。 想像を働かせる→それを達成するためにどのような処理を加えるか考える→所望の処理をさせるためにどのようなコードを書けばよいか勉強する という流れでプログラムのスキルは上がっていくものだと思います(人から与えられた必要性ではなく、自分の内から出た必要性の方が、勉強する気も起りますよね) 参考になれば幸いです。

ak5081260
質問者

お礼

回答ありがとうございます。 厳しいお言葉もしっかり受け止め、 教えていただいたことを参考に勉強していこうと思います。 本当に丁寧に教えていただきありがとうございました!

その他の回答 (2)

  • Kules
  • ベストアンサー率47% (292/619)
回答No.2

再びKulesです。 ん~…(苦笑) 聞き方が悪かったですね。すみません。 プロに聞かれたら怒られるかも知れませんが、 何らかのプログラムを組む作業は、 ・仕様を決める(何をどうした時、どのようなことが起こるか) ・仕様を満たすために、どのような処理を行うか ・所望の処理を行うために、どのようなコードを書くか の3段階に分かれていると思います。 簡単な例で言うならば、 ・仕様…2つの整数M,Nを入力すると、50円のノートと80円のノートを合計M冊買うと合計金額がN円だった時の、それぞれの冊数を出力する ・処理…1:M,Nの入力を受け付ける 2:連立方程式X+Y=M;50X+80Y=N;を解く ・コード…省略します となります。 ただ、上の例で言うならば ・処理…1:M,Nの入力を受け付ける 2:鶴亀算方式でX,Yを求める でもいいわけですよね? 何が言いたいかといえば、 ・同じ仕様を、異なる処理で満足することができる。 ・仕様から処理を決めるまでの流れは、使う言語やツールに依存しない ということです。 で、あなたが書いた >左クリック(開始)→マウスを動かす→左クリック(終了) のようにクリックからクリックまでの移動距離を計測したいのです。 や >・カーソルを使い、画像上でなぞることができる > ・なぞった軌跡の距離を計測できる は「仕様」であって「処理」ではないと考えられます。 「処理」を考える上では、Matlabの知識は要りません。 もちろんあった方が「Matlabと相性のいい処理」を考える上では役に立つんですけどね。 実は私自身今日ちょっと試してみたら、あなたの言うような機能を満たす関数は割とすぐにできました。 ただ、これを作って思ったのは ・この関数を丸のまま渡しても初心者にはそのまま使うことしか出来ない→結局「脱初心者」とはいかない (人の書いた関数を読むというのは、特に最初のうちはとても困難です) ・私の書いた関数が、「ベストの処理」とは思えない→これを手本として渡すのはどうなん? (これをそのまま渡したところで、ちょっと目先を変えた課題には対応できない) ということでした。 以上を踏まえて、再度補足要求します。 ・仕様をより具体的に固めて下さい。 いつ(どんな時でも?Figureを選択している時のみ?ボタンか何かで制御?メニューバー(Figureの上欄にあるファイルとか表示とか並んでいるところです)に新たな項目を作る?その他?)どこ(fiugre上?Axes上(枠内)?その他?)をどうしたら(左クリック?右クリック?ホイール?ドラッグ?ダブルクリック?その他)どのような(線が描ける?移動距離が表示される(どこに?)?その他)動作をするのか。例外処理やエラーチェックはどうするか(例えば複数のFigureが重なっている時はどちらに対して処理を行うのか、など) ・その仕様を満足するために、どのような処理をするかを具体的に書いてください エラーチェックなどは最初は難しい(どのような例外が起きうるのか想像しにくいため)ので省略しても構いません。 一例として、私が書いた関数Fugaの仕様、処理の一部を書きます。 (実際に文書に書いたわけではありませんが、関数を書き始める前に考えたことです) ・仕様…メニューバーに新たな項目「Locus」を加え、その中に項目Memoryを作る。Memoryにチェックが入っている時のみ軌跡を描けるようにする。条件を満たしている時、クリック→ドラッグ→ドロップの動作で、クリックしてからドロップするまでの総移動距離をコマンドウィンドウに出力し、カーソルの動いた軌跡を青い線でプロットする。クリックするのはFigure内である必要がある。ドラッグ、ドロップではFigure外にカーソルがあってもよいが、Figure内で動いた方がいい(エラーチェックで問題なくできるが、とりあえず今は)。 ・処理 (1)クリックした時  Locus→Memoryにチェックが入っているか確かめる  クリック中かどうかを表すflag_Clickをtrueにする  クリックした点の、Axesにおける座標を取得する  移動距離を0にリセットする (2)ドラッグ(マウスポインタを移動した)時  Locus→Memoryにチェックが入っているか確かめる  flg_Clickがtrueになってるか確かめる  現在のマウスポインタの、Axesにおける座標を取得し、予めもっている座標の情報に新たに加える  前の最新の点から今回の点までの距離を測り、これまでに保持していた移動距離に足す (3)ドロップ(マウスの左ボタンを離した時)  Locus→Memoryにチェックが入っているか確かめる  flg_Clickがtrueになってるか確かめる  flg_Clickをfalseにする  これまでに保持した座標をAxesにプロットする  移動距離をコマンドウィンドウに表示する この他に、「Locus→Memoryにチェックを入れる処理」「Locus→Memoryを作る処理」などがあります。 どんな言語であったとしても、入門者から私のような「初心者に毛が生えたぐらいのレベル」場合によっては中級者にとって一番大切なのは、「自分がこのようにしたい、と思った処理ができるようなコードが書けること」だと思います。 まずは、「どのようなコードを書くか」ではなく (>プログラムでどう組み込めばよいのか分らないため質問させて頂きました。 を考えるのではなく) どのような処理を行えばよいのかしっかり考えることが肝要かと思います。 最後の方(というか全体にわたって)お小言みたいになってしまいすみません。 補足いただければ、「所望の処理を行うためのコード」を書くことができると思います。 参考になれば幸いです。

ak5081260
質問者

補足

全くの無知な私にこんなに詳しく教えていただいて...本当にありがとうございます。 正直、できるだけ簡単に仕様を満たすことのできるプログラムが知りたいという思いで質問いたしました。 しかし、Kulesさんのおっしゃる通りで、コードをもらうだけでは何も成長しませんよね。非常に反省致しました...。 私はプログラミングの経験はほとんどなく(座学でCをさらっと学んだ程度)、 詳しい処理方法をどう書けばよいのかがわからない状態です。 matlabの基礎の基礎からやらねばならないのは重々承知ですが、 そのような時間も取れず、話にならん!と言われるのも覚悟で焦って質問した次第でございます。 Kulesさんの仕様、処理は私の思い描いていたものにかなり当てはまっています。 あえて言うならば、Axes内にユーザのカーソルが存在するときに動作できればと思います。 ほぼ一緒ですが、一応載せます>< ------------------------- Figure Windowに画像を表示させ、Axes内にユーザのカーソルが存在するときのみ描けるようにする。 条件を満たしている時、クリック→ドラッグ→ドロップの動作で、クリックしてからドロップするまでの移動距離をコマンドウィンドウに出力し、カーソルの軌跡をプロットする。 1)クリック時  Axes内にユーザのカーソルが存在するか確かめる  クリック中かどうかを表すflag_Clickをtrueにする  Axes内のクリックした点の座標を取得する  移動距離を0にリセットする 2)ドラッグ時  Axes内にユーザのカーソルが存在するか確かめる  flag_Clickがtrueになっているか確かめる  Axes内のカーソルの座標を取得し、予めもっている座標の情報に加える  前の最新の点から現在の点までの距離を測る  その距離をこれまでに保持していた移動距離に足す 3)ドロップ  Axes内にユーザのカーソルが存在するか確かめる  flag_Clickがtrueになってるか確かめる  flag_Clickをfalseにする  これまでに保持した座標をAxesにプロットする  移動距離をコマンドウィンドウに表示する

  • Kules
  • ベストアンサー率47% (292/619)
回答No.1

ん~軌跡も表示させるってことなんで、 ・Axes上をクリックした時、その点の座標を出力 ってことでいいんですかね? (他にも、 ・Figure内をクリックした時、Figure内の位置を出力 とか、 ・Figure内をクリックした時、スクリーン内での位置を出力 などが考えられるので) p=get(gca,'CurrentPoint'); で、x,y,z座標(表と裏)の3×2の行列が出力されるので、 x座標、y座標を得たいのであれば、 x=p(1,1);y=p(1,2); とすればよいでしょう。 で、クリックした時に座標を出力したいのであれば、 set(gca,'ButtonDownFcn','Hoge'); としといて、関数Hoge(ファイル名Hoge.m)を別に作っておき、 その中でx,y座標を取るようにすればいいですね。 次に、x座標とy座標をどのように保存するか…ですが、ワークスペースを使っていいのであれば 関数Hogeを[x,y]=Hogeに変更して、 set(gca,'ButtonDownFcn','[x,y]=Hoge;'); とすれば実行した時点でx,yがワークスペースに出力されます。 それはダメなのであれば、 関数Hogeの中でguidata(gca,[x,y]); とすればFigureに値が保存されるので、後でp=guidata(gca);とすれば、 pにx座標、y座標が出力されるので後で使えます。 次に、「一度目のクリックから二度目のクリックまでの移動距離を求める」ということなので、クリックしたのが一度目か二度目かを判別する必要があります。これは…まあ関数内でpersistent変数flagを持たせるか、あるいはguidata(gca,[x,y,flag])でflagも保存しちゃうかですかね。 最後に、軌跡を描くということですが…直線で結ぶだけじゃなくて軌跡を描かないといけないんですかね? いずれにせよ「描く」の部分はplotでいいと思うのですが、軌跡を残すのは大変ですね。 まあset(gcf,'WindowButtonMotionFcn','Fuga'); として、関数Fuga内で ・p=guidata(gcf);でpにこれまでの軌跡を読み込む ・p0=get(gca,'CurrentPoint');=p=[p;p0(1,1:2)];としてpに新たな座標を追加 ・guidata(gcf,p)で新たな座標の組を保存 ですかね。ただこれだとfigure内でぐりぐりカーソル動かすとあっという間にpのサイズがエライことになってしまいますが。 こんな感じですかね… 具体的に「何を」「どうしたら」の部分の情報が足りてる気がするんで、このぐらいしか書けないです。 ましてや関数自体を書くことはできないですね。(書いてもその動作の説明でまた膨大な説明が必要になってしまいそうです) もう少しどのような動作をさせたいのか補足していただければ、もう少し有益な解答ができるかも知れません。 参考になれば幸いです。

ak5081260
質問者

補足

詳しく書いて頂き、本当にありがとうございます!! あいまいで申し訳ないです。 ずばりやりたいことというのは、 例えば△が描いてある画像を表示させて その△をマウスのカーソルでなぞって、そのなぞった軌跡の距離を計測したいのです。 ・カーソルを使い、画像上でなぞることができる ・なぞった軌跡の距離を計測できる 軌跡を残すのは難しいようなので、無くても問題ないです。 以上、加えた条件で教えて頂けることがございましたら、 是非宜しくお願いします。

関連するQ&A

  • MATLABのプログラミングについてご質問です(2)

    MATLAB初心者です。 現在、以下の環境を使っています。 ------------------------------- OS:Windows XP MATLABのバージョン:R2007a ------------------------------- 以下の内容をプログラムでどう組み込めばよいのか分らないため、質問させて頂きました。 詳しい方、ご教授のほどお願いします。 (1)例えば「512x512」サイズの画像を figure に表示させ、その画像の中点を表示させる方法  (画像の中点に「×」マークをつけるイメージです) (2)上記の画像からマウスを使って、座標の始点と終点をクリックしたら"□"(選択範囲)の枠が表示される方法  (マウスを使って画像サイズを小さくしたいのが目的です) (3)上記の画像からマウスを使って、クリックした場所の座標(x軸、y軸)を figure に表示させる方法   (4)uigetdir からディレクトリ選択画面を表示して、指定したディレクトリの絶対パスを取得する方法 (5)画像データを imwrite する時、指定したパス(ディレクトリ)に出力する方法 全てでなくても、判る範囲までのご回答でもかまいません。 よろしくお願いします。

  • MATLABでマハラノビスの距離から楕円を描く方法が分からず困ってます。

    MATLABでマハラノビスの距離から楕円を描く方法が分からず困ってます。 現在研究で移動物体の位置推定を行っています。 プログラムソフトはMATLABを使っています。 その位置推定が正確かどうかの指標として、マハラノビスの距離を求め、二次元平面上に楕円を描き、移動軌跡がその楕円内にあるかを確認することが今後必要になります。 そのため、楕円をプログラムでプロットする必要があるのですが、その方法が分からず困っています。 些細なことでも構いませんので、回答していただけるとありがたいです。

  • MATLABのプログラミングについてご質問です

    MATLAB初心者です。 現在、以下の環境を使っています。 ------------------------------- OS:Windows XP MATLABのバージョン:R2007a ------------------------------- 以下の内容をプログラムでどう組み込めばよいのか分らないため、質問させて頂きました。 詳しい方、ご教授のほどお願いします。 (1)Windowsのペイントで、ドラッグ&ドロップすると    +----------+    |         |    +----------+  このように、点線で枠ができると思います。それをMATLABで表現する方法  (始点座標と終点座標はマウスで操作するため、座標は可変になります) (2)MATLAB-GUIに画像データ(sample.tif)を表示する方法 (3)MATLAB-GUIを表示した時に、表示位置を常にパソコンのモニター中央にする方法 (4)MATLAB-GUIで画面A, Bとある場合、画面Aの[次へ]ボタンを押すと画面Aを消して画面Bを表示する方法 長くて申し訳ございませんが、ご回答よろしくお願いします。

  • MATLABのプログラミングについてご質問です(3)

    MATLAB初心者です。 いつもお世話になります。 現在、以下の環境を使っています。 ------------------------------- OS:Windows XP MATLABのバージョン:R2007a ------------------------------- 以下の内容をプログラムでどう組み込めばよいのか分らないため、質問させて頂きました。 詳しい方、ご教授のほどお願いします。 (1)カレントディレクトリ内のフォルダ(hoge)の中に「JPEGファイル」が何個あるかをカウントする方法 (2)MATLABの guide のプロパティ インスペクターの中に文字の水平位置(left, center, right)を設定する  「HorizontalAlignment」があると思います。  垂直位置を設定する箇所ってどこかにあるのでしょうか?  あれば、教えて頂きたいです。 (3)2つの画像ファイル「A.tif」「B.tif」を合成(論理和)して「C.tif」を出力する事って可能なのでしょうか?  色々と試してみましたが、今の自分の力量では無理でした。もし可能であれば、やり方を教えて頂きたいです。 全てでなくても、判る範囲までのご回答でもかまいません。 よろしくお願いします。

  • マウスカーソル+軌跡を遅らせて表示

    VisualBasic(6.0)で,Form上のマウスの軌跡(実線)を実際より時間的に遅れて表示させるプログラムを作成しています. 方法としては,Timer で数ステップ前の座標を記録し実線を表示+ マウスカーソルをロードしたImageをその位置に移動させる,という処理を行ってみたのですが, その方法ですと,カーソルが既に描かれた軌跡の上を通過すると,前の軌跡が消えてしまいます. そこでFormのAutoRedrawをTrueにすると,カーソルがちらついてしまいます. (TimerのIntervalは10msです.) このような現象を回避するための良い方法はありませんでしょうか? 宜しくお願いします.

  • matlabでplotを使う際の横軸設定 

    MATLAB R2013a を使って折れ線グラフを書こうとしています。 1*600の配列の中に計測データを格納しています。 これをDataとします。 このデータは計測対象を3mmずつ600回移動させて計測したものです。 plot(Data) とした場合、当然横軸は配列の添え字が使われます。 このとき、横軸をmmスケールで表示させたいと思っています。 また、メモリの間隔を指定し(10データ, 30mm)ごとに表示させたいと思っています。 初めての質問なので至らない点が多いかもしれませんが、よろしくお願い致します。

  • MATLABの使い方に関していくつか質問

    MATLABの使い方に関していくつか質問をお願い致します。 ・MATLABはスクリプトと関数を別のmファイルに記述して保存しますが、 小さな関数が増えてくると関数をいちいち開くのが大変です。 一つのmファイルにスクリプトと関数、あるいは複数の関数を記述して保存することは可能でしょうか? ・プログラムを更新するごとにバックアップを取ることで、何か不具合があっても元に戻せるようにしているのですが MATLABは複数のファイルに内容が書かれてあるため、フォルダ単位でバックアップを取る必要があります。 これら複数のmファイルを一つのプロジェクトファイルにまとめて保存することは可能でしょうか? ・エディターを開いた状態でメインウインドウをクリックすると エディターが隠れてしまいますが、エディターを常に前面表示して、隠れないようにすることは可能でしょうか? ・セミコロン無しでプログラムを書くとコマンドライン上でそれらの値が表示されます。 このとき、 xxx = 12345 のようにイコールの後に二回改行が自動的に入って表示されるのですが この改行を無くして xxx = 12345 のように表示するように変更することは可能でしょうか? よろしくお願いいたします。

  • mファイルを開こうとしてもMatlabのエディタが起動しない.

    こんばんわ. 新しくインストールしたMatlabR2007aに関する質問です. 今まで使っていたパソコンでは,デフォルト設定でmファイルをダブルクリックするとmatlabが起動された後,エディターが自動で開いていました. しかし,新しくインストールしたパソコンではmファイルが最初から関連付けされておらず,Matlabを常に使用するプログラムとして指定しました. その結果,Matlabが起動するところまではいくのですが,自動ではエディタが起動しないという状態になっています. 今までのようにm-ファイルをダブルクリックすればMatlabとリンクの取れた状態のエディタが起動するように設定しなおしたいのですが,ご存知の方はいらっしゃるでしょうか? 教えてください.

  • マウスを使わずに()の中に文字を入力する方法

    はじめまして。 (A)と入力する際、下記の操作をしています。 1、()を入力 2、数式バーをクリックする。 3、キーボードの矢印キーでカーソルを左に移動させて、()の中にカーソルをもってくる。 4、()の中にAを入力する。 2の【数式バーをクリックする】という操作は、数式バー(または入力中のセル)をクリックぜずに矢印キー(左)を押すと、カーソルではなく、セル自体が左に移動してしまうので行っています。 2の【数式バーをクリックする】という操作があると、キーボードからマウスに手を移動させなければならず手間です。 マウスを使わずに、キーボードのみで()の中に文字を入力する方法を教えてください。 よろしくお願い致します。

  • プログラミング教えてください

    Adobe flashソフトを使ってゲーム を作りたいのですが アクションスクリプト(プログラム )がわかりません 内容はドラックアンドドロップです シンボルを1つ作ります。 シンボル名は[block1]にします。 それを画面左に設置します。 そのシンボル[block1]にカーソル を合わせドラッグandドロップして 画面右に何個も移動させるプログラ ミングを教えてください

専門家に質問してみよう