getsnapshot returns a cyan screen - matlab

I run this code in MATLAB but it returns a Cyan frame
obj = videoinput('winvideo', 1);
% Select the source to use for acquisition.
set(obj, 'SelectedSourceName', 'input1')
% View the properties for the selected video source object.
src_obj = getselectedsource(obj);
get(src_obj)
% Acquire and display a single image frame.
frame = getsnapshot(obj);
image(frame);
% Remove video input object from memory.
delete(obj);
But preview video works well.

Perhaps the problem is with the input to image command.
Try to run
class(frame)
max(frame(:))
min(frame(:))
And see what the results are.
Double values should be between [0-1], whereas uint8 should be in the range of [0-255].

Adding obj.ReturnedColorSpace = 'rgb'; in the second line solved it.

Related

How to Fix Frame Size Error When Making Animation in MATLAB

I have this code to create an animation:
obj = VideoWriter(pvideo);
open(obj);
pic=dir(strcat(outputs,'/','*.tif'));
num=length(pic);
for i=1:num
im = imread(strcat(outputs,'/',pic(i).name));
writeVideo(obj,im);
end
close(obj)
It is giving me the following error:
Error using VideoWriter/writeVideo (line 368)
Frame must be 1768 by 1326
I understand that my video dimensions are off, but I'm not sure what part of my code needs to be changed to fix this.
Possible Size Mismatch
I believe a possible issue is that the images being combined into the video file may not match in resolution/dimensional size. Here is a sample script that creates a video file from built-in MATLAB images. Here all the images are written as size 500 by 500. If one of the images are not matching the error is thrown. They're are two ways to handle the issue resize the image using the imresize() function or crop the image using the imcrop() function or indexing (this can be done in the for-loop). Can one of the 500 dimensions in the script below throws the same error which might be an indicator of this problem.
%Creating test images to combine into video file%
Folder_Path = "";
Image = imresize(imread('moon.tif'),[500 500]);
imwrite(Image,fullfile(Folder_Path,"Image_1.tif"));
Image = imresize(imread('circuit.tif'),[500 500]);
imwrite(Image,fullfile(Folder_Path,"Image_2.tif"));
Image = imresize(imread('autumn.tif'),[500 500]);
imwrite(Image,fullfile(Folder_Path,"Image_3.tif"));
%Starting to create video%
Pictures = dir(fullfile(Folder_Path,'*.tif'));
%Creating a video object to save the video structure to%
Video_Object = VideoWriter('Saved_Video.mp4','MPEG-4');
Video_Object.FrameRate = 1;
Video_Object.Quality = 100;
Number_Of_Frames = length(Pictures);
open(Video_Object);
%Scanning the frames into the video structure%
for Frame_Index = 1: Number_Of_Frames
writeVideo(Video_Object,imread(fullfile(Folder_Path,Pictures(Frame_Index).name)));
end
close(Video_Object);
implay('Saved_Video.mp4');

Convert video into greyscale in matlab

I'm trying to convert a video file into greyscale. When I try running the Matlab script I get a "Invalid video data-must be a numeric or logical data type". Can someone help me with what I am doing wrong? I am also new to matlab.
filename = 'Project1.m4v';
vid = VideoReader(filename);
newVid = VideoWriter('NewVid');
open(newVid);
numFrames = vid.NumberOfFrames;
for frame = 1 : numFrames
% Extract the frame from the movie structure.
thisFrame = read(vid, frame);
%Convert each frame to black and white
gray = rgb2gray(thisFrame);
writeVideo(newVid,gray);
end
close(newVid);
implay(newVid);
Use implay('NewVid.avi') instead of implay(newVid);
The only problem in your code is the last line: implay(newVid);.
newVid is a VideoWriter object - you create it using newVid = VideoWriter('NewVid');.
I recommend you to add '.avi' file extension to 'NewVid' file name:
Use: newVid = VideoWriter('NewVid.avi');
implay does't take VideoWriter object as input parameter.
Instead of displaying an error message in Matlab workspace, it displays the error message in the video window.
All you need to do, is replacing last code line with implay('NewVid.avi').

Repeating trials in MatLab

i'm am very new to Matlab but really want improve. For my experiment i want to show a picture which the participant response yes/no to, using two different keys (f&g) and then the next picture is presented and it repeats so onward.
Presenting the picture, using the keys works for far, but i can't get it to repeat the trial. Thus my question is how can i get the program to repeat/loop my trial?
Is there something wrong in my code so far or is there additional coding i should use?
this is my code so far
function try1_6()
cleanupObj= onCleanup(#() myCleanupFxn);
% PRETEST
% Initialize screen with black background
winID = Screen('openWindow',0, [0 0 0]);
%Parameter
backcol=255;
textcol=0;
% Load image file(s)
structimages= [];
TheImagesdir = dir('theImagesdir/*.jpg');
for i=1: length(TheImagesdir);
TheImages = imread(['theImagesdir/' TheImagesdir(i).name], 'JPEG');
% Get width and height
imageX = size(TheImages,2);
imageY = size(TheImages,1);
% Convert to texture
myTexture = Screen('MakeTexture', winID, TheImages);
% Set destination rectangle
destRect = [50 100 50+imageX 100+imageY];
%save to structure
structimages(end+1).filename=TheImagesdir(i).name;
structimages(end).destRect= destRect;
structimages(end).texture= myTexture;
end
%Make triallist
numberOfItems= [5]; %list of all possible items
Nrepeats=4;
Response=0;
TrialList=HH_mkTrialList({numberOfItems Response},Nrepeats);
%PRESENTATION
for trialnum=1:size(TrialList,1)
nitems = TrialList(trialnum,1);
Screen('FillRect', winID,backcol); % makes the screen blank
%displays text
DrawFormattedText(winID,'dkjfghaslkdfglksdjgfh','center','center',textcol);
Screen('Flip', winID)
HH_waitForKeyPress({'space'}); % waits for spacebar to be pressed
Screen('FillRect',winID,backcol);
Screen('Flip',winID);
WaitSecs(1);
%display picture
whichTheImages= randi(length(TheImagesdir)); % randomly selects image for directory
Screen('FillRect',winID,backcol);
Screen('DrawTexture', winID, myTexture, [], destRect);
Screen('Flip', winID);
HH_waitForKeyPress({'f','j'},5)
if resp==-1
break
end
TrialList(trialnum,4)= response; %records response
end
end
function myCleanupFxn()
Screen('CloseAll')
end
There are a number of problems with you code that you need to address. First of all, TrialList is used before it is declared/initialized. The Make triallist block of code seems out of place in the body of the for loop, and should probably be placed before you loop TrialList.
Your second problem is the inner for loop that loads images. Right now, it loads every image found in the directory, on every trial! There is no reason for you to be doing this, and you should be placing this for loop outside the trial loop as well. Furthermore, your original code never worked as intended, because you never save the loaded texture anywhere; myTexture is overwritten by the last image in your folder and that's the only texture you're ever gonna get. So in addition to pre-loading the images before the loop, you need to save them in a data structure so that you can use them later in your trial loop. A simple struct will work nicely here:
structImages = [];
TheImagesdir = dir('theImagesdir/*.jpg');
for i = 1:length(TheImagesdir);
TheImages = imread(['theImagesdir/' TheImagesdir(i).name], 'JPEG');
% Get width and height
imageX = size(TheImages,2);
imageY = size(TheImages,1);
% Convert to texture
myTexture = Screen('MakeTexture', winID, TheImages);
% Set destination rectangle
destRect = [50 100 50+imageX 100+imageY];
%save to structure
structImages(end+1).filename = TheImagesdir(i).name;
structImages(end).destRect = destRect;
structImages(end).texture = myTexture;
end
There are other inconsistencies in your code:
whichTheIamges is defined but not used
resp is used in the comparison if resp==-1 but is not defined
response is saved into TrialList before it is defined
Finally, the biggest problem is Screen('CloseAll', winID); is inside the trial loop, so you tear down your whole presentation platform after the first trial.
FYI, as noted in my comment wrapping your entire script in a try block is really poor practice. I suspect you do this because you want to be able to Ctrl+C mid-task, but there's a better way to do this. If you make your entire script a function then you can use the onCleanup method to execute code whenever your function exits (whether normally, by error, or by interruption). The method goes like this:
function myScript()
%//make your script a function. There is an additional advantages to doing this:
%//function performance is better than script performance.
%//blah-blah-blah
%//setup the cleanup object before opening screen
cleanupObj = onCleanup(#() myCleanupFxn);
%//open the screen
winID = Screen('openWindow',0, [0 0 0]);
%//blah-blah-blah
end
function myCleanupFxn()
%//local function, not visible outside of this file
Screen('CloseAll');
end

Matlab how to display snapshots?

vido = videoinput('winvideo',1);
vido.FrameGrabInterval = 10;
start(vido)
while(vido.FramesAcquired<=30)
data = getsnapshot(vido);
imshow(data);
flushdata(vido);
end
Hi.I have the code above.It is working but taking place from memory for every snapshot.For example it stars 600mb,610,620...Why ? how can I prevent this?
You are most likely not removing the video object when you're done. You keep creating video objects every time you run this code, even though you grab 30 frames from the source and stop capturing after that point. As such, make sure you remove the video object when the while loop finishes by delete.
In addition, you have stated that imshow is the reason why you keep getting an increase in memory. It actually shouldn't, but if you're really that concerned, you can spawn a blank figure and then grab a handle to the imshow window. Next, you can simply update the window for each frame you read in... so:
hAxes = subplot(1,1,1); % //Create a blank window and get the axes handle
%// First frame flag
firstFrame = true;
vido = videoinput('winvideo',1);
vido.FrameGrabInterval = 10;
start(vido);
while(vido.FramesAcquired<=30)
data = getsnapshot(vido);
if firstFrame % //If first frame, show the image and get a handle to the window
hImage = imshow(data, 'Parent', hAxes);
firstFrame = false;
else
%// Simply update the window after the first frame
set(hImage, 'CData', data);
end
flushdata(vido);
end
delete(vido); %// IMPORTANT

reading and displaying video file frame by frame

I am newly working with Matlab. I want to read a video file and do some calculations every frame and display every frame. I wrote the following code but every time it only displays the first frame. can anybody please help.
mov=VideoReader('c:\vid\Akiyo.mp4');
nFrames=mov.NumberOfFrames;
for i=1:nFrames
videoFrame=read(mov,i);
imshow(videoFrame);
end
Note: mmreader API has been discontinued by MATLAB so prefer using VideoReader.
See comment by #Vivek.
I usually do this:
obj=mmreader('c:\vid\Akiyo.mp4');
nFrames=obj.NumberOfFrames;
for k=1:nFrames
img=read(obj,k);
figure(1),imshow(img,[]);
end
As far as your code is concerned, I saw MATLAB's documentation. You should do the things in following order:
mov=VideoReader('c:\vid\Akiyo.mp4');
vidFrames=read(mov);
nFrames=mov.NumberOfFrames;
for i=1:nFrames
imshow(vidFrames(:,:,i),[]); %frames are grayscale
end
Function read() and the field NumberOfFrames() are now deprecated, Matlab suggests using
xyloObj = VideoReader(file);
vidHeight = xyloObj.Height;
vidWidth = xyloObj.Width;
mov = struct('cdata',zeros(vidHeight, vidWidth, 3,'uint8'), 'colormap',[]);
while hasFrame(xyloObj)
mov(k).cdata = readFrame(xyloObj,'native');
end
In case you want to estimate a number of frames in the video, use nFrames = floor(xyloObj.Duration) * floor(xyloObj.FrameRate);
Below suggested code is showing only one frame
imshow(vidFrames(:,:,i),[]);
I am doing following things to store each frame
obj = VideoReader('path/to/video/file');
for img = 1:obj.NumberOfFrames;
filename = strcat('frame',num2str(img),'.jpg');
b = read(obj,img);
imwrite(b,filename);
end
This will store all the frames in your home directory.And yes, as also suggested by Vivek and Parag
You need to use VideoReader as mmreader has been discontinued by
MATLAB.
*=I was making a function to play any .avi file as a set of frames in a figure. Here's what a did. A bit of a combo of what you've done, except my NumberOfFrames wasn't working: (noteL this also shows it in colour)
function play_video(filename)
% play_video Play a video file
% play_video(filename) plays the video file specified by filename in a MATLAB Figure window.
figure
set(figure, 'Visible', 'on')
mov=VideoReader(filename);
vidFrames=read(mov);
duration = mov.Duration;
frame_rate = mov.FrameRate;
total_frames = duration .* frame_rate
for i=1:1:total_frames
imshow(vidFrames(:, :, :, i), []);
drawnow
end