creating a video - zoom in effect of still image

Hi!
I am trying to create a simple script in matlab that creates a video of - zoom in effect.
The original image is called : "start.jpeg" : it will be the first frame in the video.
The user need to draw a rectangular roi over the image, with the same AspectRatio of the original image dimentions.
The area in that roi will be the last frame in the video.
My idea was to create vectors: x ,y ,width ,height which represent the bounding box properties of each frame.
Using a for loop, every iteration we create a new frame by cropping the original image with the suitable bounding box.
after joining all the frames to one video , I see that the result is vert clumsy , and the zoom in effect is not "stable".
is there any way to create the zoom in effect stable?
here is the script I designed:
clc;
clear;
close all;
%% settings
time = 15; %15 sec
rate = 30; %30 frames per sec
nFrames = time * rate;
startFrame = imread('start.jpeg');
[row,col,~] = size(startFrame);
startPose = [0 0 col row];
figure; imshow(startFrame);
rect = drawrectangle("FixedAspectRatio",true,"AspectRatio",row/col);
endPose = rect.Position;
%%
x = floor(linspace(startPose(1),endPose(1),nFrames));
y = floor(linspace(startPose(2),endPose(2),nFrames));
w = floor(linspace(startPose(3),endPose(3),nFrames));
h = floor(linspace(startPose(4),endPose(4),nFrames));
v = VideoWriter('ZoomIn.avi');
open(v);
for i = 1:nFrames
crop = [x(i) ,y(i), w(i), h(i)];
f= imcrop(startFrame,crop);
[row,col,~] = size(startFrame);
f = imresize(f,[row col]);
writeVideo(v,f);
end
close(v);
The original script and image are attached.

 Accepted Answer

It's somewhat smoother if you use round instead of floor. But I think some of the jitter is due to using integer coordinates for the cropping. If you want it perfectly smooth you'll have to crop out with subpixel resolution and that means using interp2. Can you do it? I think you can.

6 Comments

Using interp2() seems like a pretty good way to deal with it all.
I read the documentation of the interp2() function, but i dont quite understand how to use it in this case.
Foregive me for my ignorance, I am quite new in matlab (half year experience), I really need your help.
I would really appreciate for a full code, to learn from it in the right way!
please!
This is pretty slow, but it's smooth.
time = 15; %15 sec
rate = 30; %30 frames per sec
nFrames = time * rate;
startFrame = imread('peppers.png');
startFrame = im2double(startFrame); % needs to be float for interpolator
[row,col,~] = size(startFrame);
startPose = [0 0 col row];
imshow(startFrame);
thisrect = drawrectangle("FixedAspectRatio",true,"AspectRatio",row/col);
endPose = thisrect.Position;
pos = interp1(0:1,[startPose; endPose],linspace(0,1,nFrames));
v = VideoWriter('ZoomIn.avi');
open(v);
for i = 1:nFrames
thisrect = pos(i,:);
% output coordinate space
xo = linspace(thisrect(1),sum(thisrect([1 3])),col);
yo = linspace(thisrect(2),sum(thisrect([2 4])),row);
thisframe = zeros([row col 3]);
for c = 1:3
thisframe(:,:,c) = interp2(startFrame(:,:,c),xo,yo.');
end
writeVideo(v,thisframe);
end
close(v);
Thanks @DGM. Yes, this is pretty much exactly what I was thinking. David, expand the comments and use DGM's code.
Wow!!! the result is amazing.
@DGM @Image Analyst thank you both, for your help! I very appreciate it
@David Levi David, please vote for @DGM answer below since he gave you the code for the floating point interpolation (I did not have time to, at that point in time). This will award him 2 "Reputation Points" for his efforts to help you. (Both Accepted answers and votes both give the person 2 points.)

Sign in to comment.

More Answers (1)

You can get a bit better results by
  • not rounding the rect parameter
  • scaling prior to cropping
It's not perfect, but it's a bit better.
time = 15; %15 sec
rate = 30; %30 frames per sec
nFrames = time * rate;
startFrame = imread('peppers.png');
[row,col,~] = size(startFrame);
startPose = [0 0 col row];
figure; imshow(startFrame);
thisrect = drawrectangle("FixedAspectRatio",true,"AspectRatio",row/col);
endPose = thisrect.Position;
% just directly interpolate to get all rect vectors
% don't round; imcrop() accepts fractional inputs
pos = interp1(0:1,[startPose; endPose],linspace(0,1,nFrames));
v = VideoWriter('ZoomIn.avi');
open(v);
for i = 1:nFrames
thisrect = pos(i,:);
scale = mean([col row]./thisrect(3:4));
f = imresize(startFrame,scale);
f = imcrop(f,thisrect.*scale);
f = f(1:row,1:col,:); % crop any remaining excess
writeVideo(v,f);
end
close(v);

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!