Wacomタブレット 文字表示 数値化

タブレットにペンで書いたものを、X軸、Y軸、Z軸のデータで読み込み表示することを行っています。
wacomタブレットを用いて下記のコードを元に数値を取り込んでいます。 数値としてデータを読み込むことまではできたのですが、読み込みの際にタブレットに書いているものを表示できていないので、読み込みの際に書いている文字などが表示されるようにし、読み込みが終わると数値が表示されるようにしたいです。
ここでウィンドウを開いているのですがデータを読み込む際に画面すべてを使うのではなく、小さいウィンドウのようなものに表示するようにしたいのですが、どのように定義したらよいかわかっていません。
try
[wPtr rect] = Screen('OpenWindow', 0);
WinTabMex(0, wPtr);
使用中のコード
function fastLoop
% function fastLoop
%
% PTB画面を開き、関連付けられた画面ポインタwPtrにタブレットを接続し、イベントキューの内容をダンプします。
%
%
% pkt = WinTabMex(5)タブレットのイベントキューから最新のデータポイントを読み込みます。このキューは約50のデータポイントを保持できるバッファです。
% このキューは、キューを空にするWinTabMex(2)への呼び出しの後に満ちあがり、
% 高速ループ'(fastLoop.m参照)での刺激提示中に運動データを記録するために使用できます。
%
% pktは8x1の列ベクトルです
%
% tabletTestData.mat:
% xPos = pkt(1), x軸の位置(タブレット座標)
% yPos = pkt(2), y軸の位置(タブレット座標)
% zPos = pkt(3), z軸の位置(タブレット座標)
% buttonState = pkt(4), エンコードされたボタンの状態(少し不規則に動作します)
% serialNumber = pkt(5)
% tabletTimeStamp = pkt(6), タブレットからの時間(ミリ秒)
% penStatus = pkt(7), さまざまなイベントを通知します(例:penOutOfRange)
% penChange = pkt(8), 最後のサンプルから何が変更されたかを示すフラグ
%
%pkt(1:6)は単純ですが、pkt(7:8)はそれが何を意味するか
%
%Andrew D. Wilson, 2009 (adwkiwi@gmail.com)
KbName('UnifyKeyNames');
spaceKeyID = KbName('space');
data = [];
try
[wPtr rect] = Screen('OpenWindow', 0);
WinTabMex(0, wPtr); %タブレットドライバを初期化し、 'wPtr'に接続します。
%PTB things
Priority(1);
ListenChar(2);
HideCursor;
black = BlackIndex(wPtr);
white = WhiteIndex(wPtr);
%*******************************************************************************************
%ウィンドウをロードし、入力を待って録音を開始します。
instructions = 'Place the stylus on the tablet and press the space bar to begin recording';
[instructionsX instructionsY] = centreText(wPtr, instructions, 15);
Screen('DrawText', wPtr, instructions, instructionsX, instructionsY, black); Screen(wPtr, 'Flip');
%スペースバーを待つ
[keyIsDown, secs, keyCode] = KbCheck;
while keyCode(spaceKeyID)~=1
[keyIsDown, secs, keyCode] = KbCheck;
end
%*******************************************************************************************
WinTabMex(2); %実際のデータを収集するためにパケットキューを空にします。
information = 'Event queue is filling up...you will be able to retrive up to 50 events (500ms @ 100Hz)';
[informationX informationY] = centreText(wPtr, information, 15);
Screen('DrawText', wPtr, information, informationX, informationY, black);
Screen(wPtr, 'Flip');
WaitSecs(3);
%キューからすべてのデータを変数にダンプする高速ループ。 WintabMex(5)を呼び出すたびに、データポイントがキューの先頭から取り出され、
%このループは、Matlabがキューが排水されるまで実行できるように速く実行されます
%
%注意:データが収集された後、キューを排水するこのループが実行されます
while 1
pkt = WinTabMex(5);
if isempty(pkt) %キューが空です
data = [data zeros(9,1)]; %breakが呼び出されたことを示す
break;
else
data = [data pkt];
end
status = uint32(pkt(7));
if bitget(status, 1)
disp('Pen is outside the tablet');
end
if bitget(status, 2)
disp('Queue overflow - packets getting lost');
end
end
data = data' %Matlabのメモリ環境設定が行や列などを扱う方法に合わせてこのようにします
samplingRate = 1000 / mean(diff(data(1:end-1,6)));
disp(['Your sampling rate appears to be ', int2str(samplingRate), 'Hz.']);
endInstructions = 'Queue drained...pull the stylus away from the tablet';
[endX endY] = centreText(wPtr, endInstructions, 15);
Screen('DrawText', wPtr, endInstructions, endX, endY, black); Screen(wPtr, 'Flip');
WaitSecs(3);
WinTabMex(3); %データ収集を停止/一時停止します。
WinTabMex(1); % シャットダウンドライバ.
ListenChar(1); ShowCursor;
Screen('CloseAll');
catch
disp('Quit with error (wintabfastLoop.m)');
WinTabMex(3); WinTabMex(1);
ListenChar(1); ShowCursor;
Screen('CloseAll');
tabletTestError = lasterror;
message = tabletTestError(1).message
identifier = tabletTestError(1).identifier
stack = tabletTestError(1).stack;
file = stack.file
line = stack.line
end
function [x y] = centreText(wPtr, text, preferredFontSize)
%function [x y] = centreText(wPtr, text, preferredFontSize)
%
%Psychtoolboxで使用する場合。
%ウィンドウのポインタと文字列を受け取り、Screen( 'DrawText')に入力された場合にテキストを中央に配置するx、y座標を返します
%
%議論:
%wPtr = Screen( 'OpenWindow')への呼び出しによって返されたウィンドウポインタ
%text =画面に送信する文字列
%preferredFontSize =あなたが望む最大サイズのフォント。テキストが大きすぎる場合、
% centreTextは動作するまでテキストサイズを循環させ、最大のサイズに設定します
%
%戻り値:
%[x y] =(x、y)座標を中心とするベクトルです。
%
%NB Screen( 'OpenWindow')を使用する必要があります
%
%Andrew D. Wilson (v1.0.3; 11 April 2008)
x=-1; y=-1; %ループを1回実行できるようにする
while x<0
Screen('TextSize', wPtr, preferredFontSize);
[normBoundsRect, offsetBoundsRect]= Screen('TextBounds', wPtr, text);
rect = Screen('Rect', wPtr);
windowCentre = [rect(3)/2 rect(4)/2];
textCentre = [normBoundsRect(3)/2 normBoundsRect(4)/2];
x = windowCentre(1) - textCentre(1);
y = windowCentre(2) - textCentre(2);
if x < 0 || y < 0 %つまり、テキストが画面外に描画された場合
preferredFontSize = preferredFontSize-1;
end
end
return;

 Réponse acceptée

Hirokazu Tanaka
Hirokazu Tanaka le 20 Oct 2018

0 votes

 [wPtr rect] = Screen('OpenWindow', 0);

の部分の変更方法が分かれば・・と TabletDemo_README.pdf を見てみると、下記の呼び出しをしてました。

 wPtr = Screen('OpenWindow', 0, 0, [0 0 30 30]);

[0 0 30 30] の部分でWindowサイズを指定できるみたいですね。左から

  • スクリーン左上から、立ち上げる画面の左上までのピクセル数(横)
  • スクリーン左上から、立ち上げる画面の左上までのピクセル数(縦)
  • 立ち上げる画面の幅(ピクセル数)
  • 立ち上げる画面の高さ(ピクセル数)

を表すようです。ただ全画面起動以外では Psychotoolbox 側での何らかのチェックに引っかかるようですが、詳細は私も分かりません。

http://psychtoolbox.org/docs/Screen も参考にしました。こちらは Screen関数の使い方が羅列されていますが、いまいちよくわかりません・・。

15 commentaires

Keiichi Hirayama
Keiichi Hirayama le 22 Oct 2018
ありがとうございます。 30だと小さかったので200にして試してみたのですが、表示されたウィンドウが真っ黒のままうで固まってしまったので、なぜ固まるのか自分でも考えてみます。
タブレットに書いた文字などを数値だけでなく、Showやplotで定義して書いた文字を表示したいのですが、どのように定義したらよいかわかりません。 データを読み込んでいるときに書いている文字が表示されるのが一番良いのですが、その方法ではなく読み込んだ三次元データを別の質問の際にしていたようなposデータなどにして表示するほうがよいのでしょうか。
Keiichi Hirayama
Keiichi Hirayama le 22 Oct 2018
画面表示は下記のようにカラーが0だと黒だったので白の256にしたところ画面の4分の1くらいの大きさで表示することができました。
[wPtr rect] = Screen('OpenWindow', 0 ,256, [0 0 1000 500]);
Kazuya
Kazuya le 23 Oct 2018
実際に試せないのでコードを見ながらの推測になりますが、、下記の部分 while end 内に plot 関数を差し込めば、データを読み取りながら描くことは可能かもしれません。
while 1
pkt = WinTabMex(5);
if isempty(pkt) %キューが空です
data = [data zeros(9,1)]; %breakが呼び出されたことを示す
break;
else
data = [data pkt];
end
status = uint32(pkt(7));
if bitget(status, 1)
disp('Pen is outside the tablet');
end
if bitget(status, 2)
disp('Queue overflow - packets getting lost');
end
end
恐らく、、
pkt = WinTabMex(5);
で座標点を取っているので、、
h = animatedline;
while 1
pkt = WinTabMex(5);
if isempty(pkt) %キューが空です
data = [data zeros(9,1)]; %breakが呼び出されたことを示す
break;
else
data = [data pkt];
addpoints(h,pkt(1),pkt(2));
drawnow
end
status = uint32(pkt(7));
if bitget(status, 1)
disp('Pen is outside the tablet');
end
if bitget(status, 2)
disp('Queue overflow - packets getting lost');
end
end
でどうなるか試してみてください。 https://jp.mathworks.com/help/matlab/ref/animatedline.html を使ってみました。
Keiichi Hirayama
Keiichi Hirayama le 23 Oct 2018
試してみたところ、書いたデータに基づいて自動で座標が決められ線が表示されました。 表示されたものを添付しています。 ウィンドウでは左上の座標が0になっていて、表示されるものは左下が0になるので書いたものと表示されるものが少し違って表示されているみたいです。
Kazuya
Kazuya le 23 Oct 2018
Modifié(e) : Kazuya le 23 Oct 2018
y座標値にマイナスを掛けてプロットすれば、少なくとも上下は反転するのでそれらしく見えるようになるかも?
addpoints(h,pkt(1),-pkt(2));
Keiichi Hirayama
Keiichi Hirayama le 23 Oct 2018
現在、同じように書いても数値や表示結果が全く違っていて、表示される結果のX軸、Y軸の数値も決まっていないので、タブレットかウィンドウの幅を0から100までなど設定した方がよいのでしょうか。
また、読み取ったデータからX,Yのデータだけを他のファイルなどに読み取って表示させたらどうにかできないかとも考えているのですが、まだどうやったらよいかまではわかってはいなくできてはいません。
Keiichi Hirayama
Keiichi Hirayama le 23 Oct 2018
X,Yのデータを散布図のようにして表示する方法を試してみたのですが、データをうまく読み取れていないのか、最初の5つぐらいのでーたしか表示されませんでした。
x_datas=[];
y_datas=[];
for i=1:length(data)/9
x=data((i-1)*9+1)
y=data((i-1)*9+2)
x_datas=[x_datas x];
y_datas=[y_datas y];
end
scatter(x_datas,y_datas)
Kazuya
Kazuya le 23 Oct 2018
fastLoop 関数内で使われている data を処理しているのであれば、data は2次元配列のはずなので、↑のように length(data)/9 とすると全体の1/9のデータしか x_datas, y_datas に入らないのが原因かもしれません。
data = data' %Matlabのメモリ環境設定が行や列などを扱う方法に合わせてこのようにします
の部分で行列を転置しているので、data が Nx9 か 9xN かはコードの場所によって変わってきますが、
scatter(data(:,1),data(:,2))
もしくは
scatter(data(1,:),data(2,:))
で散布図が描けると思いますよ。
Keiichi Hirayama
Keiichi Hirayama le 23 Oct 2018
scatter(x_datas,y_datas
scatter(data(1,:),data(2,:))
に変更してみたところ、線で表示されていたものの各データが散布図のように表示されるようになりました。 一応タブレットからのデータを表示することはできているのですが、タブレットの書いたものと表示されているものがあっていないような気がします。 y座標にマイナスをかけて反転も試してみましたができませんでした。
Kazuya
Kazuya le 23 Oct 2018
線でつなぐなら
plot(data(1,:),data(2,:))
の方がいいですね。どう違うのかキャプチャ画像か何かで教えて頂けば何かわかるかもしれません。全く異なるものならデータの取得がうまくいっていないか(対策は・・??)、data ではない他の変数に座標値がはいっているのか、、それとも縦横の比が違う程度であれば、x軸、y軸のスケールがあっていないだけなのかもしれませんし。
Keiichi Hirayama
Keiichi Hirayama le 23 Oct 2018
plotに変更してタブレットの左下から右上がりで書いたところ、それと同じように結果も右上がりの直線が書けた結果が出せました。ありがとうございます。 ちなみにX,Yの座標の最大値や範囲などの設定はどうすればできるのでしょうか。 現在右上がりで書いたところXの値が最大約20000、Yの値が最大約14000くらいまであるのでその値の範囲を小さくしたいです。
Kazuya
Kazuya le 23 Oct 2018
プロットの表示範囲指定ならこちらをどうぞ。
y軸については ylim を使います。
Keiichi Hirayama
Keiichi Hirayama le 23 Oct 2018
参考にしてみます。 ありがとうございます。
よろしければ、また何かあったときは質問させてください。
Kazuya
Kazuya le 24 Oct 2018
Good luck :)
Keiichi Hirayama
Keiichi Hirayama le 5 Nov 2018
タブレットからの記録が始まってからfigureが表示され、線が表示されているのですが、現状では最初の方のデータがうまくデータをとれず、直線になってしまいます。そこで、実行したときに、先にfigureを表示しておき、そこに読み込んだデータをもとに線を表示したいのですが、どのようようにしたらfigurを先に表示し、そこに線を表示できるかわかりますでしょうか。
また、記録時間が短く、その時間を長くしたいと思っていて、WinTabMex(4)というものが、デフォルトではWinTabMex(4)=50;になっているみたいで、50を変更したら長くできるのではないかと思っているのですが、変更の仕方がわかりません。コードにも定義されていないので、どこに定義したらいいかわかっていません。
上記二つもし少しでも教えていただけるとありがたいです。 私がやりたいことに似たようなものでもいいので何か参考にさせてもらいたいです。お願いします。

Connectez-vous pour commenter.

Plus de réponses (0)

Catégories

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by