画像の印象評定

下記プログラムの改良版 画像の印象評定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;