Combining two visual experiments written in Psychtoolbox - matlab

I have two different experiments (one is a “change blindness task” and the other one is an “optokinetic stimulation of dots”) both written in psychtoolbox.
I want to combine these two task while running (i.e., to superimpose change blindness task on the OKS paradigm). I would be so thankful if you can let me know about possible ways to combine these two experiment? Or any sources that can be of help to learn how can I approach this.
Best regards,
Parishad

This is hard to answer without any code provided by you. You should probably look at the examples here: http://peterscarfe.com/ptbtutorials.html
I'm still going to try to answer, but again, without code from you, this might or might not be helpful.
In psychtoolbox you draw stimuli first off screen and then you 'Flip' what has been drawn off screen to be displayed on the monitor. First you set up the display window like this:
screenNumber = max(Screen('Screens'));
[w, wRect] = PsychImaging('OpenWindow', screenNumber, [0 0 0]);
Now you have a fully black monitor. If you want to show something else (here a red dot with a size of 20 pixels at the center of the screen), you have to draw it on the upcoming frame and then 'Flip', like this:
[screenXpixels, screenYpixels] = Screen('WindowSize', w);
Screen('DrawDots', w, [screenXpixels/2, screenYpixels/2], 20, [1 0 0], [], 2);
Screen('Flip', w)
Your experiments probably have loops that draw the stimuli and flip to them at the appropriate times within each trial. You will have to figure out what things from which loop to put into a combined loop, so they are drawn at the same time and then flipped together. Good luck.

It may be a good way to define two separate screens and handle both tasks simultaneously:
[windowPtrBig, rectBig] = Screen('OpenWindow', max(Screen('screens')), [256 256 256]);
[windowPtrSmall, rectSmall] = Screen('OpenWindow', max(Screen('screens')), [256 256 256 ], [0 100 1000 1000]);
To get closer to the appropriate answer, the code is needed.

Related

MATLAB: How to make a figure fit the screen on a 2nd monitor?

I exclusively use an external monitor connected to my laptop (laptop's screen is turned off). When I try to make a MATLAB figure fit the screen it only gets a size big enough to fit the laptop screen (which has a lower resolution) it seems. I use the following:
figure('outerposition',get(0,'screensize')); % or 'monitorpositions'
I even tried:
figure('outerposition',[0 0 1 1.2]);
but it does not do it and the figure only fits a part of the monitor's screen.
Any help would be greatly appreciated as I am out of ideas.
P.-S. What I would like to do, ultimately, is to have a figure fit 90% (for example) of the screen (width and height).
Thanks in advance!
This solution is based on the screensize function written by Doug Schwarz in this Newsreader thread.
I have done some quick tests, it seems to return the desired results, find my adaptation at the bottom of this post.
Example use
Fullscreen, monitor 2
% Pass the monitor number to the screensize function, this example uses monitor 2
sz = screensize(2);
% The function returns pixel values, so must use units pixels
% Set the outerposition according to that.
figure('units', 'pixels', 'outerposition', sz)
Just filling 90% of the screen, monitor 2:
sz = screensize(2);
pad = 0.05; % 5% padding all around
szpadded = [sz(1:2) + sz(3:4)*pad, sz(3:4)*(1-2*pad)];
figure('units', 'pixels', 'outerposition', szpadded);
screensize function
Doug's original code relied on moving the mouse pointer to get positions, I'm not sure why and have slimmed that code down. I've also removed code duplication etc. to make things a bit more compact. The function essentially relies on getting the screen device array from the java back end.
function ss_out = screensize(screen_number)
%screensize: return screen coordinates of multiple monitors.
% Version: 1.0, 26 June 2008 Author: Douglas M. Schwarz
% Version: 1.1, 21 July 2017 Author: Wolfie
persistent myss
if isempty(myss)
% Get Screen Devices array.
sd = java.awt.GraphicsEnvironment.getLocalGraphicsEnvironment.getScreenDevices;
% Initialize screensize array.
num_screens = length(sd);
myss = zeros(num_screens,4);
% Loop over all Screen Devices.
for ii = 1:num_screens
bounds = sd(ii).getDefaultConfiguration.getBounds;
myss(ii,:) = [bounds.x, bounds.y, bounds.width, bounds.height];
end
end
num_screens = size(myss,1);
if nargin == 0
screen_number = 1:num_screens;
end
screen_index = min(screen_number,num_screens);
ss_out = myss(screen_index,:);
end
The problem might be related to this note in the documentation:
MATLAB sets the display information values for this property at startup. The values are static. If your system display settings change, the values do not update. To refresh the values, restart MATLAB.
In my desktop, starting Matlab with only one active screen gives that:
>> get(0,'MonitorPositions')
ans =
1 1 1280 1024
and even if I try to activate the screen later, it doesn't change. However, if I activate the second screen and then restart Matlab, I get:
>> get(0,'MonitorPositions')
ans =
-1919 -123 1920 1080
1 1 1280 1024
And then I can set the figure to this size:
figure('OuterPosition',[-1920 -123 3200 1080]);
which covers both screens.

MATLAB: Blockproc with overlapping windows but no padding

I spent quite some time on understanding and applying the Matlab function blockproc.
I also read some posts on stackoverflow on this function, like this, and this one, still I can not utilize the function as I want.
Basically, all I want is a sliding window on my image, which overlaps the windows, but does not (zero-) pad the edges of the image.
For example, on a 10x10 image, I'd like to apply a 8x8 window, with an overlap of 2. IF
img = reshape(1:100,[10,10]);
then, in Matlab-Notation, I'd like to get the
desired ranges:
[1:8, 1:8] [1:8, 3:10]
[3:10, 1:8] [3:10, 3:10]
The command I thought would do the trick is:
fun = #(block_struct) mean2(block_struct.data);
blockproc(img, [4,4], fun, 'BorderSize', [2,2], 'TrimBorder', true)
Where, 4+2*2=8 is my windowsize, and the 2 indicates the overlap.
However this does not work.
I tried other combinations of parameters and values, but with no luck.
I would be really glad if someone could help me out! Thanks in advance!

counting the number of objects on image with MatLab

I need to count the number of chalks on image with MatLab. I tried to convert my image to grayscale image and than allocate borders. Also I tried to convert my image to binary image and do different morphological operations with it, but I didn't get desired result. May be I did something wrong. Please help me!
My image:
You can use the fact that chalk is colorful and the separators are gray. Use rgb2hsv to convert the image to HSV color space, and take the saturation component. Threshold that, and then try using morphology to separate the chalk pieces.
This is also not a full solution, but hopefully it can provide a starting point for you or someone else.
Like Dima I noticed the chalk is brightly colored while the dividers are almost gray. I thought you could try and isolate gray pixels (where a gray pixel says red=blue=green) and go from there. I tried applying filters and doing morphological operations but couldn't find something satisfactory. still, I hope this helps
mim = imread('http://i.stack.imgur.com/RWBDS.jpg');
%we average all 3 color channels (note this isn't exactly equivalent to
%rgb2gray)
grayscale = uint8(mean(mim,3));
%now we say if all channels (r,g,b) are within some threshold of one another
%(there's probabaly a better way to do this)
my_gray_thresh=25;
graymask = (abs(mim(:,:,1) - grayscale) < my_gray_thresh)...
& (abs(mim(:,:,2) - grayscale) < my_gray_thresh)...
& (abs(mim(:,:,3) - grayscale) < my_gray_thresh);
figure(1)
imshow(graymask);
Ok so I spent a little time working on this- but unfortunately I'm out of time today and I apologize for the incomplete answer, but maybe this will get you started- (if you need more help, I'll edit this post over the weekend to give you a more complete answer :))
Here's the code-
for i=1:3
I = RWBDS(:,:,i);
se = strel('rectangle', [265,50]);
Io = imopen(I, se);
Ie = imerode(I, se);
Iobr = imreconstruct(Ie, I);
Iobrd = imdilate(Iobr, se);
Iobrcbr = imreconstruct(imcomplement(Iobrd), imcomplement(Iobr));
Iobrcbr = imcomplement(Iobrcbr);
Iobrcbrm = imregionalmax(Iobrcbr);
se2 = strel('rectangle', [150,50]);
Io2 = imerode(Iobrcbrm, se2);
Ie2 = imdilate(Io2, se2);
fgm{i} = Ie2;
end
fgm_final = fgm{1}+fgm{2}+fgm{3};
figure, imagesc(fgm_final);
It does still pick up the edges on the side of the image, but from here you're going to use connected bwconnectedcomponents, and you'll get the lengths of the major and minor axes, and by looking at the ratios of the objects it will get rid those.
Anyways good luck!
EDIT:
I played with the code a tiny bit more, and updated the code above with the new results. In cases when I was able to get rid of the side "noise" it also got rid of the side chalks. I figured I'd just leave both in.
What I did: In most cases a conversion to HSV color space is the way to go, but as shown by #rayryeng this is not the way to go here. Hue works really well when there is one type of color- if for example all chalks were red. (Logically you would think that going with the color channel would be better though, but this is no the case.) In this case, however, the only thing all chalks have in common is the relative shape. My solution basically used this concept by setting the structuring element se to something of the basic shape and ratio of the chalk and performing morphological operations- as you originally guessed was the way to go.
For more details, I suggest you read matlab's documentation on these specific functions.
And I'll let you figure out how to get the last chalk based on what I've given you :)

Stair plot to vertical bar plot in Matlab

I want to create a vertical bar plot. This is my code:
bar (x, sensiv);
title ('Promedio X')
xlabel('Nm')
ylabel('Refl.')
The problem is it looks like a stair plot. I've tried to add (x,sensiv, 'stacked') but it doesn't work. It looks grouped, as you can see in the next image:
graph http://imageshack.us/a/img689/9449/capturawv.jpg
I think it's because of x-axis but I couldn't change it. How can I do it? Does somebody knows how can I do it?
EDIT
Thanks Colin! I've tried to zoom and I understand what you mean and I've tried with different values, as slayton and you said.
I think that maybe it's the way I've code the plot, it is possible?
abc=0;
for p=(61:201)
abc(p)=out1_c;
end
for p=(151:301)
abc(p)=out2_c;
end
for p=(231:380)
abc(p)=out3_c;
end
for p=(381:596)
abc(p)=out4_c;
end
for p=(1152:1531)
abc(p)=out5_c;
end
for p=(1651:2051)
abc(p)=out7_c;
end
for p=(2052:2151)
abc(p)= 0;
end
The default value for the width of the bars in a bar plot is 0.8, so given that you're not currently specifying the width, you should have gaps in between each bar. This is going to sound really obvious, but have you tried zooming in on the bar plot that is created? For some datasets, the bar function will return a plot that looks like a stair plot, but in fact has gaps if you zoom in far enough. If this is the case, then you should be able to get the gaps you want by tinkering with the width parameter as suggested by slayton.
EDIT
Okay. First things first. If you want to post additional information, you should add it to your question, NOT post it as a new answer! You can do this by clicking the edit button just below where your question is on the page. To make things more readable, you might preface your edit with a capitalized bold-face heading "EDIT" as I have done here. If you are able, try now to move the additional information you've given back into your question, and then delete the answer.
Second, I have to be honest, the additional information you posted was somewhat confusing. However, I think I understand what you want now. You want 7 bars coming up to the heights out1_c, out2_c, ..., out7_c (variable names taken from your additional information) with a small gap between each bar, and the x-axis to reflect (approximately) the intervals 450-550, 550-650, etc.
Well, if you want 7 bars, then you want your input to only have seven elements. Set:
y = [out1_c; out2_c; out3_c; out4_c; out5_c; out6_c; out7_c];
y now gives you the heights your bars will come up to on the y-axis. To locate the bars on the x-axis, define a vector x that also has seven elements, where each element gives the midpoint of where you want the bar to be on the x-axis. For example:
x = [100; 200; 300; 400; 500; 600; 700];
Then just use bar(x, y). This should get you started.
A final point on the code you posted, you can actually completely avoid the loops: read up on vectorization. But if you are going to insist on loops, the first and most important rule is to preallocate your vectors/matrices. In your code abc starts out as a scalar (a 1 by 1 matrix), but then for every p, you are adding an element at index p. What is actually happening in the background is for every p, matlab is scrapping the current abc you have in memory, and building it again from scratch with the additional element. As you might expect, this will slow down your code by many orders of magnitude.
You can set the width of the individual bars by passing a value between 0 and 1 to bar. Passing 1 indicates that there should be no space between the bars
bar(x,y,1)
Passing anything less than 1 will reduce the bar sizes and introduce spacing between the individual bars
bar(x,y,.5)

Superimpose two web cam streams - Matlab

I currently have a code in Matlab that takes images from two webcams, overlays them and displays them in a figure which get's updated in time intervals to give semi-realtime.
However, I need to make this realtime, does anyone have any idea of how to overlay two webcam streams like you would do with a 3D movie?
Thanks!
If you mean Anaglyph 3D, having both images you can do the following:
left = imread('vipstereo_hallwayLeft.png');
right = imread('vipstereo_hallwayRight.png');
imshow(cat(3, left(:,:,1), right(:,:,2:3)));
both png's already come with the image processing toolbox.
The result will be this (and you can look at it with Red/Cyan glasses. I did!):
I already tried this method with real pictures in 2 ways:
1. 2 pictures taken at the same time with 2 diferent cameras a little displaced;
2. 2 pictures taken in a very short time with a moving camera. (burst mode)
And they both gave excelent results.
Then, to do it with 2 webcams, you need to:
1. init them properly;
2. set them to get 1 frame per trigger;
3. trigger them and get both frames;
4. mix frames and show them.
I do not have 2 webcams so I was no able to test it, but I think this code can do it:
Cameras setup:
% Get a handle to each cam
Lvid = videoinput('winvideo', 1, 'YUY2_1280x1024');
Rvid = videoinput('winvideo', 2, 'YUY2_1280x1024');
% Set them to get one frame/trigger
Lvid.FramesPerTrigger = 1;
Rvid.FramesPerTrigger = 1;
Then do an infinite loop to get frames, mix them and show the result.
while(1)
% Trigers both video sources
start(Lvid);
start(Rvid);
% Get the frames
left = getdata(Lvid);
right = getdata(Rvid);
% Convert them to RGB
left = ycbcr2rgb(left);
right = ycbcr2rgb(right);
% mix them (R from right + GB from left)
frame = cat(3, left(:,:,1), right(:,:,2:3));
% show
imshow(frame);
pause(0.0001) % to refresh imshow
end
Note that since my webcam is YUV i have to convert it to RGB prior to mixing the images.
Hope this helps you!
I'd suggest doing it in OpenCV.