MATLAB Answers

0

wacomタブレットを使用し文字を数値化したい

Psychtoolboxを用いて行うため まず、SucversionのインストールとPTBのインストールを行いました。 PTB(toolbox)内にあるサンプルコードをMATLABで動かしてやってみようと思ったのですが、そのサンプルコードがうまく動きません。 修正箇所や動かし方がわかる方がいましたら教えていただけると助かります。
サンプルコードです。 2行目のWinTabMex(0, wPtr);は元々WinTabMex(0, w);でしたがwが未定義ということでwPtrにしたところできました。 実行すると3行目のstartが未定義と出ました。どう定義したらいいかわからずここで止まっています。
wPtr = Screen('OpenWindow', 0, 0, [0 0 30 30]);
WinTabMex(0, wPtr); %Initialize driver, connect it to window ‘wPtr’.
WinTabMex(2); % Start data acquisition.
for time = start:stop
pkt = WinTabMex(5);
if ~isempty(pkt)
disp(pkt);
end;
end
WinTabMex(3); % Stop/Pause data acquisition.
WinTabmex(1); % Shutdown driver.
Screen('CloseAll');
%%%%%/Pseudo Matlab Code%%%%%

  0 Comments

Sign in to comment.

2 Answers

Answer by Hirokazu Tanaka on 13 Oct 2018
Edited by Hirokazu Tanaka on 13 Oct 2018
 Accepted Answer

start だけでなく stop も定義されていないので動かないかもしれませんね。 "Pseudo Matlab Code" とのコメントがあるように、参考にしているサンプルコードがそのまま実行することを想定していないようにも見えます。
の TabletDemo_README.pdf を参考にしていますか?せっかくなら wintabfastLoop.m の方を試してみてはどうでしょうか。

  2 Comments

TabletDemo_README.pdfの方を参考にしていました。
wintabfastLoop.mの方を試してみます。
ありがとうございます。
.mのコードを用いて行っていて、タブレットに書いたものをコマンドウィンドウに数値化するところまではできました。 9つ数値があり左から1つ目がX軸、2つ目がY軸、3つ目がZ軸、5つ目がシリアルナンバー、6つ目が時間だと思います。 他の数値がどういうものなのかがわかっていません。
タブレットのデータを読み込む時間が短いのでも少し長くしたいのですが、時間をどうやって長くしたらいいかがわかりません。 書いたものの数値しか出ていないので書いたものをfigureやプレビューのように表示したいというところが知りたい。
function fastLoop
% function fastLoop
%
% Opens a PTB Screen, attaches a tablet to the associated screen pointer wPtr and dumps out the contents of an event queue.
%
%
% pkt = WinTabMex(5) reads the latest data point out of a tablet's event queue. This queue is a buffer that can hold around 50 data points.
% This queue begins filling up after a call to WinTabMex(2), which empties the queue, and can be used to record movement data during
% stimulus presentation in a 'fast loop' (see fastLoop.m).
%
% pkt is a 8x1 column vector
%
% tabletTestData.mat:
% xPos = pkt(1), x axis position (tablet coordinates)
% yPos = pkt(2), y axis position (tablet coordinates)
% zPos = pkt(3), z axis position (tablet coordinates)
% buttonState = pkt(4), encoded button state (works a little erratically)
% serialNumber = pkt(5)
% tabletTimeStamp = pkt(6), time in ms from the tablet
% penStatus = pkt(7), signals various events (eg penOutOfRange)
% penChange = pkt(8), flags what has changed since the last sample
%
%pkt(1:6) are straightforward, pkt(7:8) need some work on figuring out what it all means
%
%Andrew D. Wilson, 2009 (adwkiwi@gmail.com)
KbName('UnifyKeyNames');
spaceKeyID = KbName('space');
data = [];
try
[wPtr rect] = Screen('OpenWindow', 0);
WinTabMex(0, wPtr); %Initialize tablet driver, connect it to 'wPtr'
%PTB things
Priority(1);
ListenChar(2);
HideCursor;
black = BlackIndex(wPtr);
white = WhiteIndex(wPtr);
%*******************************************************************************************
%Loads a window and waits for input to start recording - just for getting set up and ready
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');
%Waits for space bar
[keyIsDown, secs, keyCode] = KbCheck;
while keyCode(spaceKeyID)~=1
[keyIsDown, secs, keyCode] = KbCheck;
end
%*******************************************************************************************
WinTabMex(2); %Empties the packet queue in preparation for collecting actual data
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);
%Fast loop to dump all data from the queue into a variable. Each call to WintabMex(5) pulls a data point off the top of the queue, and
%this loops runs as fast as Matlab can execute it until the queue is drained
%
%NB: This loop to drain the queue runs after the data is collected
while 1
pkt = WinTabMex(5);
if isempty(pkt) %ie the queue is empty
data = [data zeros(9,1)]; %To index that a break got called
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' %Do it this way to suit the way Matlab memory preferences treat rows and columns, etc
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); % Stop/Pause data acquisition.
WinTabMex(1); % Shutdown driver.
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)
%
%For use with the Psychtoolbox.
%Takes a window pointer & a string and returns the x,y coordinates that will centre the text if fed to Screen('DrawText')
%
%ARGUMENTS:
%wPtr = the window pointer returned by a call to Screen('OpenWindow')
%text = a string to be sent to the screen
%preferredFontSize = the maximum sized font you would like to have. If the text is too big, centreText will cycle through
% text sizes until it works and set it to the biggest that fits
%
%RETURN VALUES:
%[x y] = a vector with the (x,y) coordinates to centre that text.
%
%NB Requires that you have used Screen('OpenWindow')
%
%Andrew D. Wilson (v1.0.3; 11 April 2008)
x=-1; y=-1; %Allows loop to run once
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 %ie if the text ends up being drawn offscreen
preferredFontSize = preferredFontSize-1;
end
end
return;
このデータがタブレットに書いた数値データです
data =
8242 7672 545 0 1 91894 2 918 0
8250 7672 613 0 2 91901 2 660 0
8268 7672 613 0 3 91909 0 150 0
8277 7686 613 0 4 91917 0 404 0
8303 7698 601 0 5 91924 0 916 0
8328 7718 601 0 6 91932 0 404 0
8351 7740 593 0 7 91939 0 916 0
8351 7764 585 0 8 91947 0 788 0
8357 7789 577 0 9 91954 0 916 0
8388 7816 569 0 10 91962 0 916 0
8418 7842 561 0 11 91969 0 916 0
8455 7870 553 0 12 91977 0 916 0
8487 7898 545 0 13 91984 0 916 0
8522 7929 545 0 14 91992 0 404 0
8560 7961 533 0 15 91999 0 916 0
8600 7995 533 0 16 92007 0 404 0
8642 8030 525 0 17 92014 0 916 0
8686 8066 525 0 18 92022 0 404 0
8732 8103 533 0 19 92029 0 916 0
8779 8141 533 0 20 92037 0 404 0
8828 8182 545 0 21 92044 0 916 0
8878 8225 545 0 22 92052 0 404 0
8930 8270 545 0 23 92059 0 404 0
8980 8317 545 0 24 92067 0 404 0
9030 8363 545 0 25 92074 0 404 0
9078 8409 545 0 26 92082 0 404 0
9126 8455 545 0 27 92089 0 404 0
9177 8500 545 0 28 92097 0 404 0
9227 8545 533 0 29 92104 0 916 0
9277 8589 525 0 30 92112 0 916 0
9327 8633 517 0 31 92119 0 916 0
9377 8677 517 0 32 92127 0 404 0
9428 8720 509 0 33 92135 0 916 0
9478 8762 501 0 34 92142 0 916 0
9527 8801 501 0 35 92150 0 404 0
9574 8836 493 0 36 92157 0 916 0
9619 8868 485 0 37 92165 0 916 0
9660 8895 485 0 38 92172 0 404 0
9697 8918 477 0 39 92180 0 916 0
9732 8937 477 0 40 92187 0 404 0
9765 8937 477 0 41 92195 0 148 0
9795 8941 477 0 42 92202 0 404 0
9823 8947 465 0 43 92210 0 916 0
9848 8951 457 0 44 92217 0 916 0
9869 8963 449 0 45 92225 0 916 0
9886 8972 441 0 46 92232 0 916 0
9886 8978 433 0 47 92240 0 788 0
9890 8981 433 0 48 92247 0 404 0
9895 8983 425 0 49 92255 0 916 0
9907 8983 417 0 50 92262 0 660 0
13051 6426 0 1 51 94275 0 2004 113
13067 6609 0 1 52 94298 0 1428 128
13067 6671 0 1 53 94305 0 1300 129
13067 6736 0 1 54 94313 0 1300 132
0 0 0 0 0 0 0 0 0

Sign in to comment.


Answer by Hirokazu Tanaka on 18 Oct 2018

コードをパッと見ただけではよくわかりませんでした。
説明文書を読み解く必要がありそうです。 まず、TabletDemo_README.pdf に下記の説明がありますが、これが9列のデータの意味ですね。
  • pkt(1) x axis position (tablet coordinates)
  • pkt(2) y axis position (tablet coordinates)
  • pkt(3) z axis position (tablet coordinates)
  • pkt(4) encoded button state (works a little erratically)
  • pkt(5) an index of which data point this is since the last call to WinTabMex(2)
  • pkt(6) timestamp in ms from the tablet (the difference between these values is the
  • pkt(7) signals various events (eg penOutOfRange)
  • pkt(8) flags what has changed since the last sample
  • pkt(9) Normal pressure: Info about the pressure along the tablet surface normal, or pressure on the pen tip, in arbitrary units. Value range and meaning of this parameter depends on the tablet device. Some tablets may not report any meaningful values here.
> タブレットのデータを読み込む時間が短いのでも少し長くしたいのですが
これに関しては wintabslowLoop.m の方が分かりやすいかも。trialLength という変数が定義されていて、なんとなく計測時間っぽいです。すいません、推測ですが。
>書いたものの数値しか出ていないので書いたものをfigureやプレビューのように表示したい
これは、得られたデータを plot 関数なりでプロットするコードを追加してみてください。 サンプルコードの一行一行読み解くのは大変かとは思いますが、TabletDemo_README.pdf も提供されておりますし、せっかっくなのでわからないコマンドなど、検索してみることをお勧めします。

  2 Comments

ありがとうございます。 理解できる範囲でも一度サンプルコードを読んでみます。
よろしければ質問させてください。
現段階で前までのような9つのデータを読み込むことと、タブレットに書いているものを表示することができているのですが、書いているものを表示する際に、読み込んだデータをもとに少し遅れて表示している為、最初の方のデータがうまくとれていないのか、曲線を描いても直線になってしまいます。そこで、コードを実行した際に、先にfigureでX.Yの座標を表示しておいて、そこに書いたデータを表示していくようにしたいです。
また、タブレットの縦が13500、横が21600になっているみたいで、どうもその数値をもとにX.Yの数値が出ている為最大値が約13499になったりしているみたいで、その数値を読み込む際に小さな値に変更してX,Yを表示できないかとも思っています。
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 ,256, [0 500 1000 1100]);
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
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
%here
% x_datas=[];
% y_datas=[];
%
% for i=1:length(data)
%
% x=data((i-1)*9+1)
% y=data((i-1)*9+2)
% x_datas=[x_datas x];
% y_datas=[y_datas y];
%
% end
%
% plot(data(1,:),data(2,:))
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;

Sign in to comment.