I made a movie in Matlab, and when I run my code, the movie runs fine and looks great, but when I attach the video on an email, the video appears to show only the last frame of the movie.
In my for loop with all the plotting code, I used a getframe command, with variable G, before ending the loop:
G = getframe;
Then I wrote:
v = VideoWriter('my movie.avi','Motion JPEG AVI');
v.Quality = 100;
open(v)
writeVideo(v,G)
close(v)
Then I see the movie created and saved in my folder. I go to attach the movie to an email, open it up, and see that the movie only has the last frame.
What am I missing?
Thanks!
The MATLAB getframe() function returns the current frame, and you write it into the variable G in your for-loop. This overwrites G in each iteration, so at all times in your program, G will contain the last frame only. When you write it to a video file, that video will also contain only that one last frame, as you noticed.
The solution is to create an array of frames, as shown in the example on how to record videos using getframe() in the MATLAB help pages:
movie_frames(N) = struct('cdata',[],'colormap',[]); % pre-allocate frames struct
for k=1:N
% Your plotting code here
movie_frames(k) = getframe();
end
The writeVideo() function is actually designed to work with such arrays of frames, this makes saving the video as simple as
v = VideoWriter('test_video.avi');
v.open();
v.writeVideo(movie_frames);
v.close();
Related
this is my first question so I hope I am writing in the right place.
I am currently working with a Grasshopper3 camera, model: GS3-U3-50S5M-C from Point Grey Research connected to MATLAB.
I am recording a lot of frames at a time in grayscale and in order to avoid filling up my memory I would like to move some of the frames to my disk as stacked TIFFs during the recordings. The stacked TIFF format is needed for other programs used.
I am doing this by moving the recorded frames from the camera to the workspace using getdata. This creates a 4-D uint8 object containing height, width, color plane and frame number of the frames. In order to save the frames as a stacked TIFF I use a for loop with imwrite to save one frame at a time as shown below. However when I do this I most often get the error:
Error using imwrite (line 454) Unable to open file "C:\Users\My_User\Desktop\CraneStuff3\Name.tif" for writing. You might not have write permission.
When this happens MATLAB has typically saved some of the frames, e.g. if I have recorded 500 frames it might save 300 before giving me the error. Sometimes it manages to save every frame with no error, sometimes it only saves 30 frames before failing. I do not understand how it can save some frames and then claim that it cannot open the file for writing.
I have noticed, however, that if I instead save the file in "C:\Users\My_User\Documents\MATLAB" it seems to never give any error and save every frame as wanted.
Does anyone know why this is the case or how I can fix my problem?
I have included my code below here.
Note: I tried saving the frames as a .mat-file. To do this I had to use version '-v7.3' in save.
Thank you advance.
% Connect to camera:
vid = videoinput('pointgrey',1,'F7_Mono8_2448x2048_Mode0');
vid.TriggerRepeat = 100;
vid.FrameGrabInterval = 1;
% Make a recording:
start(vid)
pause(50)
stop(vid)
% Get data from camera to workspace:
data = getdata(vid,vid.FramesAvailable);
% Save data to disk one image at a time:
num = size(data);
output_name = fullfile('C:\Users\My_User\Desktop\CraneStuff3', ['Name' '.tif']);
for k = 1:num(4)
imwrite(data(:,:,:,k),output_name,'WriteMode','append');
end
One possible solution is to try saving each of the frames separately into a tiff file.
If you save a .mat file, better use savefast
I need to crop a specific area of a video in MATLAB to be replayed and saved as that specific area. Currently I only know of a way to separate all the frames, crop them, and then put them back together as a video - is there an easier way or tool to crop a video in MATLAB or am I just going to have to rely on frame-by-frame cropping?
Matlab is generally horrible for video processing. I would recommend using a generic video editor. If you have to use matlab, there are a couple of toolboxes on fileexchange which will serve your purpose (for short videos in the most generic formats and also require image toolbox).
Description
With Movie Editor you can:
- Load movies (avi's only)
- Cut movies
- Crop movies
- Split movies into separate color layers
- Rotate movies
- Save movies as avi or mpg (thanks to David Foti)
- Save independent frames as bmp, jpg, png, and tif
- You can always stroll through the movie using the slider and edittext underneath the image (maybe somebody can combine it with the 'Interactive MATLAB Movie Player' of Don Orofino.
Maybe you can add a function? The user interface is pretty self-explanatory. But questions are welcome. An example of a before- and after-movie are added to the zip-file.
Following is the code that I wrote a while ago to process video files. Before executing this file save the ROI1.m file in the path.
%frame by frame processing of video files
clear all;
close all;
clc;
mov=VideoReader('C:\Users\Syd_R\OneDrive\Desktop\entrap\holo_bright_10_MMStack_Pos0.ome.avi');
vidFrames=read(mov);
nFrames=mov.NumberOfFrames;
A=vidFrames(:,:,1);
for fr=1:nFrames
set(0,'DefaultFigureVisible','off')
elseX=vidFrames(:,:,fr);
if exist('position')==0
ROI1
else
imshow(elseX)
I2 = imcrop(elseX,[position(:,1) position(:,2) position(:,3) position(:,4)]);
end
mycell_h(fr)={I2};
end
close all;
set(0,'DefaultFigureVisible','on')
% This file should be saved (as ROI1.m) in the same path as this file will be called while executing the main file
% ROI
if exist('A')==1;
figure, imshow(A);
h = imrect(gca,[10 10 512 512]);
position = wait(h); % returns coordinates in "position" when user doubleclicks on rectangle
figure, imshow(A)
I2=imcrop(A,position);
phROI2=I2;
figure(11);
imshow(phROI2);
imwrite(phROI2, 'roi', 'tiff')
end;
The cropped frames will be saved in the cell [mycell_h]. To view the cropped frames, for example:
imshow(mycell_h{1,1})
how can i record video by webcam in matlab and take frame of that and compare it with next frames
this is my code:
camvid1 = videoinput('winvideo',1,'YUY2_640x480');
subplot(211)
h1 = image;
axis ij
preview(camvid1,h1)
start(camvid1);
pause(2),camfrm1=getdata(camvid1);
camfrm1=rgb2gray(imread(camfrm1));
for i=1:n
camfrm2=getdata(camvid1);
camfrm2=rgb2gray(camfrm2);
bt=abs(double(camfrm2)-bouble(camfrm1));
imread is used to read a file from a folder which is already in a particular compressed or uncompressed format. In your case, you have raw data, on which you can perform operations. So, try using:
camfrm1 = rgb2gray(camfrm1);
This should work.
There is a second typo:
bt = abs(double(camfrm2)-double(camfrm1));
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.
The function getframe captures whatever is visible on the screen. However in my application I want the figure to be invisible when storing its content in a matrix. So what the getframe does is that, for a short period, it makes the figure visible and captures its contents and then sets the 'visibile' property back to what it was before screen capture.
I do not want that flash happening on the screen. As well, saving in file and reading it back reduces speed. There has got to be a way to get around this.
hFig=figure('Visible','off'')
text ('String','ABC','fontsize',300)
imageData = getframe(hFig);
img = imageData.cdata; % img is what I am interested in
The only way I know to do this is to print the figure to a temporary file. For example:
%Create a figure
hFig=figure('Visible','off')
text ('String','ABC','fontsize',300)
%Save the figure to a tiff file using a salted name
tmpName = sprintf('Temp_Figure_%04d.tiff', floor(rand*1000));
print(['-f' num2str(hFig)], '-dtiff', tmpName)
%Read the data
img = imread(tmpName);
%Delete the temporary figure
delete(tmpName);
Not the prettiest thing, but it seems to work.