画像の印象評定
下記プログラムの改良版 画像の印象評定2 があります。特に理由がなければ改良版をお勧めします。
パソコン上に画像を提示し、その印象評定を7件法で行うサンプルプログラムです。
実際に実験を行う際は、プログラムが正しく動いているか十分に動作確認をしてください。
以下のサンプルプログラムを動かすには、プログラムと同じフォルダに
Images
というフォルダを作り、その中にjpeg形式の画像を3枚保存してください。
画像ファイル名は
1.jpg
2.jpg
3.jpg
としてください。
function InsyoHyotei
% 画像(JPEG形式)を呈示して印象評定を行うプログラムです。
% 質問項目は7件法です。
% 1から7のテンキーを押すと、対応する場所に○がつきます。
% 0(ゼロ)で回答を決定し、次の質問に変わります。
% すべての質問に回答すると、次の画像に変わります。
%
% 画像ファイルは、プログラムと同じフォルダに「Imagesという名前のフォルダ 」を作り
% そこに 1.jpg などを置いておくこと。
%
% 実験データは「プログラムと同じフォルダ 」にできます。
%
% SubNameは結果を出力するファイル名に使われる
% 実験参加者名の入力
SubName = input(['Name? '], 's'); % 名前をたずねる
if isempty(SubName) % 名前の入力がなかったらプログラムを終了
return;
end;
try
AssertOpenGL;
ListenChar(2);
%OSで共通のキー配置にする
KbName('UnifyKeyNames');
%myKeyCheck;
%あらかじめ読み込んでおく必要がある関数たち
GetSecs;
WaitSecs(1);
rand('state', sum(100*clock));
HideCursor;
screenNumber = max(Screen('Screens'));
%ウィンドウモード
%[windowPtr, windowRect] = Screen('OpenWindow', screenNumber, BlackIndex(screenNumber), [50 50 1000 700]);
%フルスクリーンモード
[windowPtr, windowRect] = Screen('OpenWindow', screenNumber, BlackIndex(screenNumber));
%画面の中央の座標
[centerX centerY] = RectCenter(windowRect);
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% 以下の変数を必要に応じて変更してください
%
imgNum = 3; %呈示する画像の枚数
imgRatio = 0.5; %画像を拡大縮小して呈示するときの割合。1のとき原画像のサイズ
%評定用(7件法)の線分
% 5件法のときなどは適宜変更をしてください。
LineKankaku = 50; %垂直線分の間隔
LineNagasa = 30; %垂直線分の長さ
LineHaba = 2; %線分の幅
LineVertPos = 600; %水平線分の垂直方向の位置
%線分を描画するための座標。転置行列であることに注意
LinesXY = [
LineKankaku*(-3) -LineNagasa/2
LineKankaku*(-3) LineNagasa/2
LineKankaku*(-2) -LineNagasa/2
LineKankaku*(-2) LineNagasa/2
LineKankaku*(-1) -LineNagasa/2
LineKankaku*(-1) LineNagasa/2
0 -LineNagasa/2
0 LineNagasa/2
LineKankaku*(1) -LineNagasa/2
LineKankaku*(1) LineNagasa/2
LineKankaku*(2) -LineNagasa/2
LineKankaku*(2) LineNagasa/2
LineKankaku*(3) -LineNagasa/2
LineKankaku*(3) LineNagasa/2
LineKankaku*(-3) 0
LineKankaku*(3) 0
]';
%線分の番号の微調整
NumPosX = -7;
NumPosY = -50;
%質問項目
Question = {
'嫌いな' '好きな';
'暗い' '明るい'
'美しくない' '美しい'};
QLPos = 220; %質問項目(左)の水平位置
QRPos = 650; %質問項目(右)の水平位置
QYPos = LineVertPos - 20; %質問項目の垂直位置(微調整が必要)
%評定の回答円の半径
Radius = 10;
% 被験者の回答を記録する行列
% 1列目は画像ファイルの番号
% 2列目は1つ目の質問
% 3列目は2つ目の質問
Answer = zeros(imgNum, size(Question, 1)+1);
CancelFlag = 0; %1になるとプログラムの強制終了
%order = [1:imgNum]; % 刺激を番号順で呈示するとき
order = randperm(imgNum); % 刺激をランダムに呈示するとき
for i = 1:imgNum
%呈示する画像ファイル名(win)
myimgfile = ['Images\' int2str(order(i)) '.jpg'];
%呈示する画像ファイル名(mac)
myimgfile = ['Images/' int2str(order(i)) '.jpg'];
%画像情報をテクスチャに
imdata = imread(myimgfile, 'jpg');
[iy, ix, id] = size(imdata);
imagetex = Screen('MakeTexture', windowPtr, imdata);
DrawFormattedText(windowPtr, 'スペースキーを押してください', 'center', 'center', WhiteIndex(windowPtr));
%メッセージを呈示
Screen('Flip', windowPtr);
DrawFlag = 0; %刺激を提示してよいかどうか
OvalCnt = 0; %回答円の場所を示す
QCnt = 1; %何番目の質問か
NumKeyFlag = 0; %数字キーを押すと1になる
tmpAns = 0; %現在の質問に対する回答(0キーで決定する前)
SpaceFlag = 0; %スペースキーを押した後かどうか
while 1
%キー入力を待つ
[secs, keyCode]=KbWait([],3);
if keyCode(KbName('ESCAPE')) %プログラムの強制終了
CancelFlag = 1;
break;
end;
if keyCode(KbName('space'))
DrawFlag = 1;
SpaceFlag = 1;
end;
%0キーを押すと回答が決定
if keyCode(KbName('0'))
%回答を決定してよい状態だったら
if NumKeyFlag == 1
Answer(i, QCnt+1) = tmpAns; %1列目には画像ファイルの番号が入る
QCnt = QCnt+1; %次の質問へ
NumKeyFlag = 0;
%ある画像について全部の質問に答えたら
if QCnt > size(Question, 1)
Answer(i, 1) = order(i); %呈示した画像ファイルの番号
QCnt = 1;
break;
else
OvalCnt = 0; %回答円を消去
DrawFlag = 1;
end;
end;
end;
if keyCode(KbName('1')) && SpaceFlag
[DrawFlag, NumKeyFlag, OvalCnt, tmpAns] = SetAns(1);
end;
if keyCode(KbName('2')) && SpaceFlag
[DrawFlag, NumKeyFlag, OvalCnt, tmpAns] = SetAns(2);
end;
if keyCode(KbName('3')) && SpaceFlag
[DrawFlag, NumKeyFlag, OvalCnt, tmpAns] = SetAns(3);
end;
if keyCode(KbName('4')) && SpaceFlag
[DrawFlag, NumKeyFlag, OvalCnt, tmpAns] = SetAns(4);
end;
if keyCode(KbName('5')) && SpaceFlag
[DrawFlag, NumKeyFlag, OvalCnt, tmpAns] = SetAns(5);
end;
if keyCode(KbName('6')) && SpaceFlag
[DrawFlag, NumKeyFlag, OvalCnt, tmpAns] = SetAns(6);
end;
if keyCode(KbName('7')) && SpaceFlag
[DrawFlag, NumKeyFlag, OvalCnt, tmpAns] = SetAns(7);
end;
if DrawFlag
%画像を描画(拡大縮小にも対応)
x1 = centerX-(ix/2)*imgRatio;
y1 = centerY-(iy/2)*imgRatio;
x2 = centerX+(ix/2)*imgRatio;
y2 = centerY+(iy/2)*imgRatio;
Screen('DrawTexture', windowPtr, imagetex, [], [x1 y1 x2 y2]);
%評定用の線分
Screen('DrawLines', windowPtr, LinesXY, LineHaba, WhiteIndex(windowPtr), [centerX LineVertPos]);
%線分に添える数字
for k = 1:7
tmpX = LinesXY(1,1) + LineKankaku*(k-1) + centerX + NumPosX;
tmpY = LineVertPos + NumPosY;
DrawFormattedText(windowPtr, int2str(k), tmpX, tmpY, WhiteIndex(windowPtr));
end;
QL = char(Question(QCnt,1)); %質問対の左側の文字
QR = char(Question(QCnt,2)); %質問対の右側の文字
%質問対の描画
DrawFormattedText(windowPtr, QL, QLPos, QYPos, WhiteIndex(windowPtr));
DrawFormattedText(windowPtr, QR, QRPos, QYPos, WhiteIndex(windowPtr));
%回答円の描画
if OvalCnt > 0
x1 = LinesXY((OvalCnt-1)*4+1)+centerX-Radius;
y1 = LineVertPos-Radius;
x2 = LinesXY((OvalCnt-1)*4+1)+centerX+Radius;
y2 = LineVertPos+Radius;
OvalRect = [x1 y1 x2 y2]';
Screen('FrameOval', windowPtr, [255 0 0], OvalRect);
end;
Screen('Flip', windowPtr);
DrawFlag = 0;
end;
%次の行でキーボードから手を離したことを確認している
while KbCheck; end;
end
%次の行でキーボードから手を離したことを確認している
while KbCheck; end;
if CancelFlag
DrawFormattedText(windowPtr, 'プログラムを強制終了しました。何かキーを押してください。', 'center', 'center', WhiteIndex(windowPtr));
Screen('Flip', windowPtr);
KbWait([],3);
break;
end;
end;
%データの保存
tmpStr = ['ファイル,'];
for i=1:size(Question, 1)
tmpStr = [tmpStr char(Question(i, 2)) ','];
end;
SaveFileName = [SubName '.csv'];
Fid = fopen(SaveFileName, 'wt');
fprintf(Fid, '%s\n', SubName);
fprintf(Fid, '%s\n', datestr(now, 'yy-mmdd-HH:MM'));
fprintf(Fid, '%s\n', tmpStr);
fprintf(Fid, '%d,%d,%d,%d\n', Answer'); %転置行列になっていることに注意
fclose(Fid);
DrawFormattedText(windowPtr, '実験は終了です。お疲れさまでした。', 'center', 'center', WhiteIndex(windowPtr));
Screen('Flip', windowPtr);
KbWait([],3);
sca;
ListenChar(0);
%psychrethrow(psychlasterror);
catch
sca;
ListenChar(0);
psychrethrow(psychlasterror);
end;
function [DrawFlag, NumKeyFlag, OvalCnt, tmpAns] = SetAns(NumKey)
OvalCnt = NumKey;
DrawFlag = 1;
NumKeyFlag = 1;
tmpAns = NumKey;