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})
Related
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();
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 have a video written with the Xvid MPEG4-Codec. Unfortunately, each frame has an annoying bar to the right and to the bottom of a couple of pixels. What I would like to do is to remove this bar, preferably using MATLAB.
For this purpose, I have written this code to try this out:
function [] = changeVideo(in_path, out_path, reqSize)
videoList = dir(strcat(in_path, '\*.avi'));
for ii = 1:numel(videoList)
vidReader = VideoReader(strcat([in_path '\'], videoList(ii).name));
vidWriter = VideoWriter(strcat([out_path '\'], videoList(ii).name),'MPEG-4');
open(vidWriter);
while hasFrame(vidReader)
% here I would change the size of the frame
writeVideo(vidWriter,readFrame(vidReader));
end
close(vidWriter);
close(vidReader);
end
end
Unfortunately, this does not seem to work. The resulting video has a different memory footprint and quality than the original video. Since MATLAB can read the original video, I was hoping that there is a way to replicate this video, but only change each frame slightly in its size. Is this possible?
Thank you!
I have a video file that I need to visualize in Matlab. From this file, I extract down-sampled thumbnails and merge them into a single image. This image is displayed using imshow command and gives the overview of the whole video.
I would like click (or hover) by mouse over any thumbnail and automatically extract from the video full sized version and display it in new figure.
What functions I need to implement such a functionality?
Roughly:
Connect to your video file using a VideoReader object.
Get the NumberOfFrames property of the VideoReader object.
Use the read method of the VideoReader object to read in frames.
Loop from 1 to NumberOfFrames, and read in each frame.
Having read in each frame, store it in the kth plane of an M-by-N-by-3-by-K array, where K is the number of frames. (the 3 is if your video is RGB - it would be 1 if grayscale).
Also, resize each frame to a thumbnail using the function imresize, and store it in the kth plane of an m-by-n-by-3-by-K array, where m < M and n < N.
Once stored in this form, display the results in a figure using the command montage, which will lay all the thumbnails out nicely for you in a grid.
Add a callback to the figure that fires when you click on the image. The callback should get the current mouse position (at the time of the click), determine which frame was clicked on, and create a new figure which displays the corresponding plane from the unresized array.
Does that sound possible?
I would like to export this picture to pdf format:
P2_tilde =
0.1029 0.4118 0.0245 0.1814 0.2794
0.3925 0.0234 0.0280 0.4626 0.0935
0.0928 0.1237 0.2680 0.2990 0.2165
0.0699 0.2219 0.0182 0.5106 0.1793
0.2611 0.0887 0.0837 0.3251 0.2414
figure('color',[1,1,1])
hBar2=bar3(P2_tilde);
colormap('pink')
set(hBar2,{'CData'},C);
set(gca,'xticklabel',surfaces)
set(gca,'yticklabel',surfaces)
surfaces={'Equipment','Patient','Hygiene products','Near-bed','Far-bed'};
colorbar
zlabel('Probability');
colormap('pink')
colorbar('location','southOutside')
set(gca,'xticklabel',surfaces)
set(gca,'yticklabel',surfaces)
surfaces={'Equipment','Patient','Hygiene products','Near-bed','Far-bed'};
zlabel('Probability');
Want to export to PDF format:
currentScreenUnits=get(gcf,'Units') % Get current screen units
currentPaperUnits=get(gcf,'PaperUnits') % Get current paper units
set(gcf,'Units',currentPaperUnits) % Set screen units to paper units
plotPosition=get(gcf,'Position') % Get the figure position and size
set(gcf,'PaperSize',plotPosition(3:4)) % Set the paper size to the figure size
set(gcf,'Units',currentScreenUnits) % Restore the screen units
print -dpdf ptilde % PDF called "ptilde.pdf"
Gives something completely off the page. Any thoughts how to center the figure on the canvas and make it only the size of the figure? Otherwise how can I trim it?
The PaperSizer parameter needs to be the actual size of the paper it will be printed on (the pdf file that will be displayed) not the size that the Matlab figure appears on the screen. For example, if you change it to this:
set(gcf,'PaperSize',[9,11])
you'll get something that looks reasonable.
I couldn't quite replicate your figure (errors in your code: need a definition for C) but use
f=figure('color',[1,1,1]);
%rest of figure code....
set(f,'PaperPositionMode','auto')
print -dpdf ptilde
Also, I'm not sure how to crop the pdf from within MATLAB, but if you want a cropped vector graphic use -depsc or -depsc2 as the print flag. see MATLAB help on print.