Implementing Lukas and Kanade’s Optical Flow
By Mikel Rodriguez

Introduction:
Optical flow is a method used for estimating motion of objects across a series of frames. The method is based on an assumption which states that points on the same object location (therefore the corresponding pixel values) have constant brightness over time.
Optical flow can be said to have two components, normal flow and parallel flow. Normal flow can be computed directly without any further constraints. However, Parallel Flow cannot be computed this way. Several methods have been proposed to compute Parallel Flow; in this project a method proposed by Lucas and Kanade is implemented.
Results:
From the original image sequence, two frames were selected (60,61). A Gaussian pyramid of 3 levels was built for each of these frames:
|
Frame 60
|
Frame 61
|
For each level of the Gaussian pyramid, the optical flow was computed for each pair of frames, the following is the resulting plot of the optical flow vectors.
Level 3:

Level 2:

Level 1:

Source Code
%%*****************************************
%% Mikel Rodriguez {mikel at cs dot ucf dot edu} *
%% Lucas and Kanade's Optical flow *
%%*****************************************
function optical_flow();
clear;
gaus_sigma = 1;
%%Image Variables:
%%I precompute the priramyds using my code from the previous assignment
ORIGINAL_IMAGE_1=imread('flower_frame_0060_LEVEL0.jpg');
ORIGINAL_IMAGE_2=imread('flower_frame_0061_LEVEL0.jpg');
[height,width]=size(ORIGINAL_IMAGE_1);
ORIGINAL_IMAGE_1=im2double(ORIGINAL_IMAGE_1);
ORIGINAL_IMAGE_2=im2double(ORIGINAL_IMAGE_2);
IMAGE_1_SMOOTHED=zeros(height,width);
IMAGE_2_SMOOTHED=zeros(height,width);
%%Derivate Variables:
Dx_1=zeros(height,width);
Dy_1=zeros(height,width);
Dx_2=zeros(height,width);
Dy_2=zeros(height,width);
Ix=zeros(height,width);
Iy=zeros(height,width);
It=zeros(height,width);
%%Optical flow variables
neighborhood_size=5;
A=zeros(2,2);
B=zeros(2,1);
output1=zeros(height,width);
output2=zeros(height,width);
%%Kernel Variables:
Kernel_Size = 6*gaus_sigma+1;
k = (Kernel_Size-1)/2;
gaus_kernel_x=zeros(Kernel_Size,Kernel_Size);
gaus_kernel_y=zeros(Kernel_Size,Kernel_Size);
kernel=zeros(Kernel_Size,Kernel_Size);
%Make a kernel for partial derivatve
%Of of gaussian with respect to x (for computing Dx)
for i=1:Kernel_Size
for j=1:Kernel_Size
gaus_kernel_x(i,j) = -( (j-k-1)/( 2* pi * gaus_sigma^3 ) ) * exp ( - ( (i-k-1)^2 + (j-k-1)^2 )/ (2*gaus_sigma^2) );
end
end
%Make a kernel for partial derivatve
%Of of gaussian with respect to y (for computing Dy)
for i=1:Kernel_Size
for j=1:Kernel_Size
gaus_kernel_y(i,j) = -( (i-k-1)/( 2* pi * gaus_sigma^3 ) ) * exp ( - ( (i-k-1)^2 + (j-k-1)^2 )/ (2*gaus_sigma^2) );
end
end
%%Compute x and y derivates for both images:
Dx_1 = filter2(gaus_kernel_x,ORIGINAL_IMAGE_1);
Dy_1 = filter2(gaus_kernel_y,ORIGINAL_IMAGE_1);
Dx_2 = filter2(gaus_kernel_x,ORIGINAL_IMAGE_2);
Dy_2 = filter2(gaus_kernel_y,ORIGINAL_IMAGE_2);
Ix = (Dx_1 + Dx_2) / 2;
Iy = (Dy_1 + Dy_2) / 2;
%%Build a gaussian kernel to smooth images for computing It
for i=1:Kernel_Size
for j=1:Kernel_Size
kernel(i,j) = (1/(2*pi*(gaus_sigma^2))) * exp (-((i-k-1)^2 + (j-k-1)^2)/(2*gaus_sigma^2));
end
end
IMAGE_1_SMOOTHED = filter2(kernel,ORIGINAL_IMAGE_1);
IMAGE_2_SMOOTHED = filter2(kernel,ORIGINAL_IMAGE_2);
It = IMAGE_2_SMOOTHED - IMAGE_1_SMOOTHED;
for i=(1+floor(neighborhood_size/2)):(height-floor(neighborhood_size/2))
for j=(1+floor(neighborhood_size/2)):(width-floor(neighborhood_size/2))
A=zeros(2,2);
B=zeros(2,1);
for m=i-floor(neighborhood_size/2):i+floor(neighborhood_size/2)
for n=j-floor(neighborhood_size/2):j+floor(neighborhood_size/2)
A(1,1)=A(1,1) + Ix(m,n)*Ix(m,n);
A(1,2)=A(1,2) + Ix(m,n)*Iy(m,n);
A(2,1)=A(2,1) + Ix(m,n)*Iy(m,n);
A(2,2)=A(2,2) + Iy(m,n)*Iy(m,n);
B(1,1)=B(1,1) + Ix(m,n)*It(m,n);
B(2,1)=B(2,1) + Iy(m,n)*It(m,n);
end
end
Ainv=pinv(A); %%Pseudo inverse
result=Ainv*(-B);
output1(i,j)=result(1,1);
output2(i,j)=result(2,1);
end
end
output1=flipud(output1); % Flip matrix in up/down direction
output2=flipud(output2); % Same
quiver(output1, output2); %plot optical flow vectors as arrows