Matlab Class Chapter 4

background image

Chapter 4 - 1 - 4/18/2007

Chapter 4 - Beginning the first experiment


In this chapter we are actually going to begin writing real code for a real experiment. We
are going to do a version of a very cool illusion first demonstrated by Mike Webster
(Webster, Kaping, Mizokami, and Duhamel, 2004, Adaptation to natural facial
categories.
Nature 428, 558-561.)

The illusion works like this – after staring at a series of male faces for a long time, a face
that previously appeared gender neutral will look female. Similar aftereffects are very
famous in other domains (look on the web for color adaptation effects and the waterfall
illusion) but it’s still pretty surprising to see such strong adaptation for human faces.

What we are going to do is write a program where subjects adapt for 2 minutes to a set of
male or female images, and then carry out a series of trials where they respond whether a
morph image (morphed between male and female) is perceived as being male or female.
Between each trial will be a 5 second adaptation top-up period. The goal is to measure
how adaptation to male or female images influences your perception of the morphed
images.

You should have a website where you can collect the necessary images. Make a new
folder in your MatlabClass/ folder called ‘Face Experiment’. Then download the images
into that folder. You should have a folder called ‘male’, a folder called ‘female’ and a
folder called ‘morph’. In the male and female folders you should have 10 images:
male01, male02 … etc. In the morph folder you should have morphs going from morph00
to morph49.

So let’s think about the structure of the program. You can think of it having 5 parts, as
shown below.

Decide if adapting to m or f

Pre-adapt for X seconds
to series of m or f images

Present test morph image
& get response

Top-up adaptation for X
seconds to series of m or
f images

Repeat X times

Analyze Data

Decide if adapting to m or f

Pre-adapt for X seconds
to series of m or f images

Present test morph image
& get response

Top-up adaptation for X
seconds to series of m or
f images

Repeat X times

Analyze Data


background image

Chapter 4 - 2 - 4/18/2007

(I’ve put the Analyze Data part in gray since we’re not going to worry about that right
now.)

Each sub-part of this program can also be diagrammed.

Pre-adapt for X seconds to series of m or f images

Load new m or f image

Display image for X seconds

Repeat X times

Number of repeats = total pre-adapt time

display time per image

Pre-adapt for X seconds to series of m or f images

Load new m or f image

Display image for X seconds

Repeat X times

Number of repeats = total pre-adapt time

display time per image



Whenever you create a program with multiple parts you should make the effort to
diagram it in this way. Trust me – you will end up writing better code and it will save you
time in the long run. Now create a program in your MatlabClass/Face Experiment folder
called FaceAdaptation.m. Now away we go.

We are actually going to start by programming each sub-part of the program as a separate
little chunk.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

% Face adaptation experiment

% A program where subjects adapt for 1 minute to

% a set of male or female images.

% then carry out a series of trials where they respond

% whether they perceive a morph image (morphed between male and female)

% as being male or female.

% Between each trial will be a 5 second adaptation

% top-up period.

% Measures how adaptation to male or female images

% influences your perception of morphs.

%

% written IF Mar 2007

cd(

'C:\WORK\Matlab class & book\MatlabBookOrganization\Spring2007\MatlabClass\Face

addpath(pwd);

addpath(

'morph'

);

% adapting variables

background image

Chapter 4 - 3 - 4/18/2007

20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76

stim.preadapttime=10;

% pre-adapt time (in seconds)

stim.adaptpresentationrate=2;

% presentation time (secs) for each adaptation image

stim.numadaptimages=10;

% there are 10 images in each adaptation set of images

stim.preadaptstoptimes=stim.adaptpresentationrate:stim.adaptpresentationrate:stim.p

adapttype=input(

'Do you want to adapt to males (m) or females (f)? ... '

,

's'

);

if

adapttype ==

'f'

addpath(

'female'

);

adaptstr=

'female'

;

elseif

adapttype ==

'm'

addpath(

'male'

);

adaptstr=

'male'

;

else

disp(

'Error 1. Sorry, response about adapt type is not correct'

);

end

pause

% waits for a keypress before going to the next stage of the program

%%%%%%%%%%%%%%%%%%%%

% Preadapting interval

%%%%%%%%%%%%%%%%%%%%

adaptcount=1;

% keeps track of which adaptation image is being presented

tic

% starts a stopwatch

for

a=1:stim.preadapttime/stim.adaptpresentationrate

figure(1)

% create a string that matches the filename of the image you want to

% read

if

adaptcount<10

imname=[adaptstr,

'0'

, num2str(adaptcount)];

else

imname=[adaptstr, num2str(adaptcount)];

end

img=imread(imname,

'JPG'

);

image(img);

axis

off

; axis

equal

;

colormap(gray(256));

title(

'pre-adapt'

);

drawnow

while

toc<stim.preadaptstoptimes(1)

;

end

stim.preadaptstoptimes=stim.preadaptstoptimes(2:end);

% move on to the next image, and keep cycling through the images, so

% adaptcount goes between 1-10

adaptcount=adaptcount+1;

adaptcount=mod(adaptcount, stim.numadaptimages)+1;

end

pause

% waits for a keypress before going to the next stage of the program

%%%%%%%%%%%%%%%%%%%%

% Test image

%%%%%%%%%%%%%%%%%%%%

% test variables

ntrials=10;

stim.testindices=linspace(0,49,8);

background image

Chapter 4 - 4 - 4/18/2007

77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133

stim.numtestimages=length(stim.testindices);

beep=sin(1:0.5:100);

trialcount=1;

% keeps track of which test image is being presented

if

stim.testindices(trialcount)<10

imname=[

'morph0'

, num2str(stim.testindices(trialcount))];

else

imname=[

'morph'

, num2str(stim.testindices(trialcount))];

end

img=imread(imname,

'JPG'

);

figure(1)

image(img);

title(

'test'

)

axis

off

; axis

equal

;

colormap(gray(256)); drawnow;

% get response

sound(beep);

FlushEvents;

response.char=input(

'Press m for male, f for female'

,

's'

);

title([

'response was '

, response.char]);

pause

% waits for a keypress before going to the next stage of the program

%%%%%%%%%%%%%%%%%%%%

% Top Up interval

%%%%%%%%%%%%%%%%%%%%

stim.topuptime=6;

% seconds for each top up interval

stim.topupstoptimes=stim.adaptpresentationrate:stim.adaptpresentationrate:stim.topu
adaptcount=1;

tic

for

a=1:stim.topuptime/stim.adaptpresentationrate

if

adaptcount<10

imname=[adaptstr,

'0'

, num2str(adaptcount)];

else

imname=[adaptstr, num2str(adaptcount)];

end

img=imread(imname,

'JPG'

);

image(img);

axis

off

; axis

equal

;

figure(1)

colormap(gray(256));

title(

'top-up'

)

drawnow

while

toc<stim.topupstoptimes(1)

;

end

stim.topupstoptimes=stim.topupstoptimes(2:end);

% move on to the next image, and keep cycling through the images, so

% adaptcount goes between 1-10

adaptcount=adaptcount+1;

adaptcount=mod(adaptcount, stim.numadaptimages)+1;

end

pause

% waits for a keypress before going to the next stage of the program

background image

Chapter 4 - 5 - 4/18/2007

134
135
136
137
138
139
140
141
142
143
144
145

%%%%%%%%%%%%%%%%%%%%%

% blank interval

%%%%%%%%%%%%%%%%%%%%%%

stim.shortpause=2;

blankcmap=ones(256, 3);

colormap(blankcmap);

title(

'small pause'

);

drawnow;

tic

while

toc<stim.shortpause

;

end


The pre-adapt section of the experiment

Line 20-23. Here we have bundled all the parameters we are going to use for the pre-adapt part of the
experiment into a structure called stim. Structures are like little shopping baskets – they allow you to collect
a bunch of variables that are related to each other into a little bundle. The reason you want to do this will be
clearer later. Here we’ve bundled all the stimulus parameters together under the structure

stim

.

Line 23. Look at

stim.preadaptstoptime

. It basically is a list of the times at which we want to

move to the next adapting image. We want to move onto the next image every 2 seconds.
Lines 25-34. Here we are checking what response the subject gave. Based on whether the subject
responded ‘m’ or ‘f’, we are setting the path and the name of the string that will be used to pull up jpg image
files. Note that if the subject gives a meaningless response we put in an Error. Good error management will
make your programs much more robust against the random behavior of undergraduate subjects.
Line 41.

tic

starts a stopwatch. We’ll find out how much time has gone by since we started the stopwatch

using

toc

Line 42. We want to adapt for 10 seconds (

stim.preadapttime

), and we want to present a new

image every 2 seconds (

stim.adaptpresentationrate

). So we will need to present a total of 5

images (

stim.preadapttime/stim.adaptpresentationrate).

We’re therefore going

to go through this loop 5 times, each time presenting a face image.
Lines 46-51. Here we are creating a string that represents the filename of the image we want to present on
the screen. We want to present the image with number

adaptcount

. The first time we run through this

loop,

adaptcount

will equal 1 (see Line 40).

Line 51. Here we load in the image. The image is saved as a jpg. When loaded in, it becomes a matrix, like
the ones we have been using. But if you

whos

your workspace you will notice something odd about img -

it’s described as a uint8 rather than a double. The reason for this is that jpg often saves images as unsigned
integers (whole numbers between 0-255) in order to save memory (depending on the particular settings that
were chosen when the jpg image was saved). When Matlab reads in the jpg file it actually reads from the
header of the jpg file that the values inside the file are unsigned integers, and it therefore loads the matrix as
unsigned integers.

> whos
Name Size Bytes Class

a 1x1 8 double array
adaptcount 1x1 8 double array
stim.adaptstr 1x6 12 char array
adapttype 1x1 2 char array
img 540x720 388800 uint8 array
imname 1x8 16 char array
stim 1x1 520 struct array

If you look at img, you will see that the values in img range between 0 and 255.

>max(img)
>min(img)

background image

Chapter 4 - 6 - 4/18/2007

Line 52. Here we use image to look at the image. But wait a moment – when we used image before, to look
at gratings and Gabors, the values in the matrix varied between 1-256. But here the values range between
0-255. What’s going on?
One peculiarity about image is that when you are using 2D matrices for

image

the way it indexes into

colormaps depends on whether the input matrix consists of doubles or uint8. If the matrix consists of
doubles then image uses 1-256 to reference into the colormap. i.e. 1 refers to first paintpot, 2 refers to
second paintpot etc. But if you are using unsigned integers (uint8 or uint16) then image actually uses 0-255
to reference into the colormap, so 0 refers to the first paintpot, 1 refers to the second paintpot and so on.
When we get to 3D matrices (where the third dimension holds separate information for the red, green and
blue monitor gun) things get even weirder.
This is always something to think about when dealing with colormap issues (Psychtoolbox, which we will be
dealing with later) has similar ambiguities). The main reason for weirdnesses like these is historical – C/C++
generally uses 0-based referencing whereas Matlab generally uses 1-based referencing. But sometimes
Matlab uses routines that were actually written in C or were originally written for C programs (or other 0-
based reference programs). In those cases Matlab moves to a 0-based system. So be wary of this issue.
Line 56. Normally drawing things in the figure window is a pretty low priority for Matlab.

drawnow

tells

Matlab to prioritize updating the window.
Line 57-59. Here we use another loop command.

while

checks to see if the statement after the

while

(

toc<stim.preadaptstoptimes(1))

is true. If it is true then it does what’s inside the loop. In

this case there is just a semi-colon inside the loop, which doesn’t do anything, so the program simply
repeats the loop (doing nothing) until

toc

is greater or equal to

stim.preadaptstoptimes(1).

toc

is a measure of how much time has gone by since

tic

, which we called on line 41. So this line

basically pauses the program until 2 seconds go by.
Line 60. Here we remove the stim.preadaptstoptime that has just passed, so we have a list of the remaining
times on the clock
Line 63. Here we add 1 onto adaptcount, so the next time we run through the loop we will present adapt
image number 2, and then 3 and so on. Of course eventually we are going to want to present adapting
images in a random order, but we’ll worry about that later.
Line 64. Of course we only have 10 different adapting images. So if adapt count goes above 10 the program
will try to read a jpg image that doesn’t exist. Here we use the command

mod

. We find the remainder after

dividing

adaptcount

by the number of adapting images. So the remainder will vary between 0-9. We

then add 1 to that and

adaptcount

will now vary between 1-10, as do our jpg images.


The test section of the experiment

Line 76. The labels for the morph jpg images range from 0-49. We don’t want to test every single image (if
you look at them, each image is barely distinguishable from each other) so we are only going to test 8

images evenly spaced between 0-49

.

Line 78. Here we are creating the sound wave for a beep. You can plot beep to see what it looks like

>plot(beep).

Because it is a simple sine wave it should sound like a pure tone.

Line 79.

trialcount

is going to be used to update which test image is presented. At the moment we

are only going to present a single image, but that will change.
Line 80-90. Read in the morph jpg images and put them up in the figure window.
Line 92. Then we play our

beep

.

Line 93. We are going to collect a key-press (an event). Before we do that we want to make sure that no
events are stored in the computer memory, using

FlushEvents

Line 94. We then collect the subjects’ response using

input

–which basically pauses the program, waits

for the subject to respond with a keypress, and saves that response as

response.char

The top-up section of the experiment

This is almost identical to the pre-adapt part of the experiment and you should be able to work it out for
yourself.

The blank interval section of the experiment

Line 137. Define how long the blank interval will last
Line 138-139. Here we create a colormap that is all ones and use it to blank out the screen.

background image

Chapter 4 - 7 - 4/18/2007

Lines 143-144. Again we use the

while

command to pause the program until

toc

is 2 seconds

(

stim.shortpause

) later than

tic

.



What’s left?


There are only a few things left to do to make this into a proper experiment:

1. At the moment the adaptation faces during the pre-adaptation period and the top-up
adaptation period are always presented in the same order instead of in random order

2. We are always presenting the same test face instead of all 8 possible test faces in
random order

3. We need to retain a list of the key-press for every single trial

4. We need to retain a list of which test face was presented on each trial

5. We don’t want to present data in the figure window – we want a proper display screen.

6. We want to save the data

But before we do this we are going to learn about functions.




Wyszukiwarka

Podobne podstrony:
Matlab Class Chapter 1
Matlab Class Chapter 6
Matlab Class Chapter 1
Matlab Class Chapter 6
Matlab Class Chapter 3
Figures for chapter 5
Figures for chapter 12
Matlab cw1 2 zaoczni
Figures for chapter 6
cz 1, Matlab moj
Chapter16
Image Processing with Matlab 33

więcej podobnych podstron