Matlab - combine two videos into a single split-screen video - matlab

I have 2 videos I would like to play side by side in a split screen. They are same duration and dimensions. I found a code developed few years back to do the job. The problem is, it is full of errors maybe due to the fact I am using a newer Matlab version (2014a). The errors start from (%name of the new avi file) onward.
Can anyone please try and fix it:
% select two files:
[filename1,pathname1] = uigetfile('.avi','pick first AVI file');
[filename2,pathname2] = uigetfile('.avi','pick second AVI file');
file1 = fullfile(pathname1,filename1);
file2 = fullfile(pathname2,filename2);
pdMovie1 = aviread(file1);
pdMovie2 = aviread(file2);
fileinfo1 = aviinfo(file1);
fileinfo2 = aviinfo(file2);
% check if AVI files have the same length and height:
if fileinfo1.NumFrames~=fileinfo2.NumFrames || ...
fileinfo1.Height~=fileinfo2.Height
errordlg('files are not compatible!')
else
% inspired by Herbert Ramoser in Message-ID:
% <art0c0$l9fip$1#ID-148798.news.dfncis.de>
for i=1:size(pdMovie1,2)
output(i).cdata = [pdMovie1(i).cdata, pdMovie2(i).cdata];
output(i).colormap = pdMovie1(i).colormap;
end;
% name of the new avi file:
[pathstr,name,ext,versn] = fileparts(filename1);
newmoviename = [pathname1,name,'_combined', ...
num2str(fileinfo1.FramesPerSecond;),ext];
% create the avi file:
movie2avi(output, newmoviename, ...
'fps', fileinfo1.FramesPerSecond;, ...
'compression', 'none');
close
end

If it is just for playing the videos side-by-side, this simplker code will work,
close all
clc
clear
vid1 = vision.VideoFileReader('video1.avi');
vid2 = vision.VideoFileReader('video2.avi');
vidP = vision.VideoPlayer;
while ~isDone(vid1)
frame1 = step(vid1);
frame2 = step(vid2);
frame = horzcat(frame1, frame2);
step(vidP,frame);
end
release(vid1);
release(vid2);
release(vidP);
UPDATE:
I'm assuming both input videos have the same length and frame dimension.
Ok, now if you want to record a new video from the first 2, with the same frame rate of the previous, it is better to use the following code,
close all
clc
clear
vid1 = VideoReader('video1.avi');
vid2 = VideoReader('video2.avi');
videoPlayer = vision.VideoPlayer;
% new video
outputVideo = VideoWriter('newvideo.avi');
outputVideo.FrameRate = vid1.FrameRate;
open(outputVideo);
while hasFrame(vid1) && hasFrame(vid2)
img1 = readFrame(vid1);
img2 = readFrame(vid2);
imgt = horzcat(img1, img2);
% play video
step(videoPlayer, imgt);
% record new video
writeVideo(outputVideo, imgt);
end
release(videoPlayer);
close(outputVideo);

If you have two video clips with different frame rates and resolutions or you would like to join/cut pairs of video clips, use the code below.
For example: My dashcam is able to record video in the front and the rear of the car at the same time. But the front and rear videos come in separate files. I want to show them side by side as well as to join 6 files (3 pairs) into a single file.
%Read video
clc
clear
vidObj_f = VideoReader('video1.mp4');
FrameRate_f = vidObj_f.FrameRate;
vidObj_b = VideoReader('video2.mp4');
FrameRate_b = vidObj_b.FrameRate;
%New video
outputVideo = VideoWriter('combinedvideo.avi');
outputVideo.FrameRate = 24;
open(outputVideo);
skip = 95; %first seconds
j=skip*24;
try
while 1
front = read(vidObj_f,1+round(j*FrameRate_f*1/24));
back = read(vidObj_b,1+round(j*FrameRate_b*1/24));
front = imresize(front,[720 1280]);
videoframe = [front;back];
writeVideo(outputVideo, videoframe);
j = j+1;
end
catch
disp('...end 1');
end
vidObj_f = VideoReader('video3.mp4');
FrameRate_f = vidObj_f.FrameRate;
vidObj_b = VideoReader('video4.mp4');
FrameRate_b = vidObj_b.FrameRate;
skip = 0; %first seconds
j=skip*24;
try
while 1
front = read(vidObj_f,1+round(j*FrameRate_f*1/24));
back = read(vidObj_b,1+round(j*FrameRate_b*1/24));
front = imresize(front,[720 1280]);
videoframe = [front;back];
writeVideo(outputVideo, videoframe);
j = j+1;
end
catch
disp('...end 2');
end
vidObj_f = VideoReader('video5.mp4');
FrameRate_f = vidObj_f.FrameRate;
vidObj_b = VideoReader('video6.mp4');
FrameRate_b = vidObj_b.FrameRate;
skip = 0; %first seconds
j=skip*24;
cut = 30; %after playing 'cut' seconds
try
while 1
front = read(vidObj_f,1+round(j*FrameRate_f*1/24));
back = read(vidObj_b,1+round(j*FrameRate_b*1/24));
front = imresize(front,[720 1280]);
videoframe = [front;back];
writeVideo(outputVideo, videoframe);
if j>cut*24
disp('...end 3 (cut)');
break
end
j = j+1;
end
catch
disp('...end 3');
end
close(outputVideo);

Related

Saving a series of manually selected points

Just a quick question. I have generated a piece of code whereby I select the point of interest in every frame. However, the coordinates of the last selected point is the only one that is saved. Does anyone know how to set up the code such that all the points for each frame are saved for example in a text file with x position in column 1 and y position in column 2? Here is the code I have developed so far;
clear;
clc;
%% Video file information
obj = VideoReader('T9_720p_60p_60mm_f5.MOV');
%% Sampling rate
fps = get(obj, 'FrameRate');
dt = 1/fps;
%% Image Information
file_info = get(obj);
image_width = file_info.Width;
image_height = file_info.Height;
%%Desired image size
x_range = 1:image_height;
y_range = 1:image_width;
szx = length(x_range);
szy = length(y_range);
%%Image processing - Point selection
for n = 33:115
frame = read(obj,n);
imshow(frame);
hpoint = impoint(gca, []);
Position = getPosition(hpoint);
end
I just realized all I need was to add the following before the end of the loop
%%Save data
n = n-32;
data(n,:) = [Position];
end
Regards

MATLAB combine two avi. together

I created two avi. file and they have the same length.
I wanted to combine them on a same background and one on top another one on the bottom.
The code I used for one of the animation is below, the other one is similar.
Is there any way I can do that?
load Results.mat;
I = imread('hex08.jpg');
[rows,columns,numberOfColorChannels] = size(I);
if numberOfColorChannels >1
I = I(:,:,2);
end
background = imresize(background, [rows,columns]);
figure(1);
hold on;
for i=1:500
A=angle(i,:);
J = imrotate(I,A,'crop');
mask = J == 0;
mask = bwareafilt(mask,4);
J(mask) = background(mask);
pause(0.01)
imshow(J);
imwrite(J,[num2str(i),'.png']);
end
imageNames = dir(fullfile('*.png'));
imageNames = {imageNames.name}';
outputVideo = VideoWriter(fullfile('hex08.avi'));
outputVideo.FrameRate = 15;
open(outputVideo)
for ii = 1:length(imageNames)
img = imread(fullfile(imageNames{ii}));
writeVideo(outputVideo,img)
end
close(outputVideo)
Here is one way this can be done:
Just like you read the image into img, you can read a second image (from the second video) into img2. Then, you can create a combined image of the two: imgCombined = [img ; img2]; which will contain the first image on top and the second on bottom (This will work if both images are the same width, otherwise you will need to resize/crop). When you write to the video file, use writeVideo(outputVideo,imgCombined).

Comparing several webcam snapshots and saving Them when there is motion Using matlab

My question is how would i get live snapshots from my webcam and only save an image when there is motion, I would like to save several images i.e whenever there is motion the images do not overwrite so that at the end i will be able to see various captured motions
well i was able to come up with a simple solution for my problem as below; it saves images only when there is motion and also adds a time stamp
clear;
clc;
vid = videoinput('winvideo', '1');
set(vid, 'ReturnedColorSpace', 'RGB');
start(vid)
%preview(vid)
while true;
img = getsnapshot(vid);
pause(2)
img1 = getsnapshot(vid);
img12 = rgb2gray(img1);
img13 = rgb2gray(img);
diff1 =sum(sum(img12 - img13));
if diff1>100000;
display ('motion')
counter = 1;
baseDir = 'H:\';
fname = [baseDir ,'Wysla_', num2str((strrep(datestr(clock),':','-'))),'.jpg'];
% make a file name
while exist(fname,'file')
counter = counter + 1;
fname = [baseDir ,'Wysla_', num2str(counter),'.jpg'];
end
imwrite(img1, fname);
else
display('No motion')
end;
end
This is all and it was very simple only thing i can mention is the strrep(datestr(clock),':','-') this a way of saving the image time stamped and since there are semi colons in the date string the strrep() replaecs them with the hyphen or anything else
av fun.

live video with matlab

This code is supposed to take live video draw 2 lines, but when we run the code, the cam will take a live video but the 2 lines appear in different windows.
Can anyone please figure out what's the problem?
clear;
dev_info = imaqhwinfo('winvideo',1);
celldisp(dev_info.SupportedFormats);
vid1 = videoinput('winvideo',1);
%out = imaqhwinfo(vid);
%This is for triggering:
num_frames=5;
triggerconfig(vid1, 'Manual')
set(vid1,'FramesPerTrigger',num_frames)
start(vid1);
trigger(vid1)
%frame = getsnapshot(vid1);
%image(frame);
%here it will acquire 5 frames
%now move the data acquired to the workspace
[data1 time1] = getdata(vid1,num_frames);
kk=length(time1);
elapsed_time = time1(kk) - time1(1);
%frame = getsnapshot(vid1); %this is to get a single frame
for i=1:500
line([27,1523],[1753,1753]);
line([7,1531],[1395,1395]);
preview(vid1);
end
delete(vid1);
clear vid1;
aviobj = avifile('example.avi');
for i=1:kk
F=data1(:,:,:,i);
aviobj = addframe(aviobj,F);
end
aviobj = close(aviobj);
%then we can see the whole video clip
mov = mmreader('example.avi');
%................
%Also, we can directly play the video from the video file
mplay('example.avi');

Batch Processing Videos (Matlab) - Issue

I've wrote some code that imports a video and takes some DCT coefficients form a specific region of the image frame by frame, it then output a binary file (containing the coefficients) using a separate function. This works fine when doing it individually but I've tried to implement a batch version of the code as I'm working with over 200 videos files.
However their is a problem, when it goes through the loop it output the wrong file each time. If the number of frames in the next iteration has less frames it writes to the previous frames. I was told that i need to initialise one of my for loops before it runs. However I'm sure how to do this, i think the problem lies in the 2nd for loop but I'm not sure.
Any suggestion would be greatly appreciated!
files = dir('Videos/*.mov');
for m = 1:numel(files);
readerobj = mmreader(files(m).name);
vidFrames = read(readerobj);
numFrames = get(readerobj, 'numberOfFrames');
% Create a MATLAB movie struct from the video frames.
for k = 1 : numFrames
mov(k).cdata = vidFrames(:,:,:,k);
mov(k).colormap = [];
end
firstFrame = mov(1).cdata;
rect = [172,225,271,143;];
numFrames = length(mov);
dctCoeff = zeros((10*10),numFrames);
for i = 1 : numFrames
frameImage = imcrop(mov(i).cdata, rect);
frameImage = rgb2gray(frameImage);
dctImage = dct2(frameImage);
dctImage = dctImage(1:10,1:10);
dctCoeff(:,i) = reshape(dctImage,1,(10*10));
end
sRate = (1/29.9701)*1e7;
[status, error] = htk_write_mfc(files(m).name, size(dctCoeff,2),sRate,4*size(dctCoeff,1),9,dctCoeff);
status
error
end
Just remove the
numFrames = length(mov);
and it should work fine!
I was told that i need to initialise one of my for loops before it runs
Jup! You're not initializing mov.
I would also recommend you to put the code for one file into a function which you call from your first loop. That is better code!
Try setting mov to [] for each movie that you load. It's going to keep frames from the previous mov and extend that array to match your longest video. Before your loop for k = 1 : ... try writing a line that says mov = [];.
I am not entirely clear on why you are creating the movie struct. You can use the read() function to read specific frames in the video file. You can try the code below:
files = dir('Videos/*.mov');
numDctCoeffs = 100;
for m = 1:numel(files)
readerObj = mmreader(files(m).name);
numFrames = readerObj.NumberOfFrames;
rect = [172,225,271,143];
sRate = (1/29.9701)*1e7;
dctCoeff = zeros(numDctCoeffs, numFrames);
for cnt = 1:numFrames
frameImage = imcrop(read(readerObj, cnt), rect);
frameImage = rgb2gray(frameImage);
dctImage = dct2(frameImage);
dctImage = dctImage(1:10,1:10);
dctCoeff(:, cnt) = dctImage(:);
[status, error] = htk_write_mfc(files(m).name, size(dctCoeff,2),sRate,4*size(dctCoeff,1),9,dctCoeff);
end
end
Also mmreader has been replaced with VideoReader in newer versions of MATLAB. The syntax is the same just a name change.
Hope this helps.
Dinesh