Implementation of the Lucas-Kanade Pyramid Optical Flow Method in MATLAB

MATLAB Function for Pyramid-Based LK Optical Flow

This article presents a complete MATLAB implementation of the Lucas-Kanade (LK) optical flow algorithm using a pyramidal (coarse-to-fine) approach. The function estimates the apparent motion vector field between two successive grayscale image frames.

Main Algorithm Function

function [flowX, flowY] = computePyramidLK(frameA, frameB, numLevels, winSz)
% computePyramidLK Pyramid-based Lucas-Kanade optical flow estimator.
% Inputs:
%   frameA, frameB - Consecutive grayscale image frames (2D matrices).
%   numLevels      - Number of pyramid levels.
%   winSz          - Size of the local analysis window (odd integer).
% Outputs:
%   flowX, flowY   - Horizontal and vertical flow component matrices.

% Convert to double precision for numerical stability.
frameA = im2double(frameA);
frameB = im2double(frameB);

% Build Gaussian image pyramids.
pyramidA = cell(1, numLevels);
pyramidB = cell(1, numLevels);
pyramidA{1} = frameA;
pyramidB{1} = frameB;

for idx = 2:numLevels
    pyramidA{idx} = impyramid(pyramidA{idx-1}, 'reduce');
    pyramidB{idx} = impyramid(pyramidB{idx-1}, 'reduce');
end

% Initialize flow at the coarsest pyramid level.
flowX = zeros(size(pyramidA{numLevels}));
flowY = zeros(size(pyramidA{numLevels}));

% Coarse-to-fine iteration.
for currLevel = numLevels:-1:1
    I1 = pyramidA{currLevel};
    I2 = pyramidB{currLevel};

    % Upscale flow from a coarser level, if not at the top.
    if currLevel < numLevels
        flowX = 2 * imresize(flowX, size(I1), 'bilinear');
        flowY = 2 * imresize(flowY, size(I1), 'bilinear');
    end

    % Warp the second image using the current flow estimate.
    I2_warped = applyWarp(I2, flowX, flowY);

    % Compute incremental flow correction at this level.
    [dX, dY] = estimateSingleLevelFlow(I1, I2_warped, winSz);

    % Update the complete flow estimate.
    flowX = flowX + dX;
    flowY = flowY + dY;
end

% Optional: Visualize the computed flow field.
visualizeFlowField(flowX, flowY, frameA);
end

Supporting Function: Image Warping

function imgOut = applyWarp(imgIn, warpU, warpV)
% applyWarp Warps an input image according to flow vectors (u,v).
[Xgrid, Ygrid] = meshgrid(1:size(imgIn,2), 1:size(imgIn,1));
imgOut = interp2(Xgrid, Ygrid, imgIn, ...
                 Xgrid + warpU, Ygrid + warpV, 'linear', 0);
end

Supporting Function: Single-Level LK Flow Estimation

function [u, v] = estimateSingleLevelFlow(imgRef, imgTarget, winRadius)
% estimateSingleLevelFlow Computes optical flow for one pyramid level.
% Computes spatial and temporal derivatives.
[gradX, gradY] = gradient(imgRef);
gradT = imgTarget - imgRef; % Temporal derivative.

u = zeros(size(imgRef));
v = zeros(size(imgRef));
halfWin = floor(winRadius / 2);

% Iterate over central pixels with a full neighborhood.
for row = halfWin+1:size(imgRef,1)-halfWin
    for col = halfWin+1:size(imgRef,2)-halfWin
        % Extract local window patches.
        patchGx = gradX(row-halfWin:row+halfWin, col-halfWin:col+halfWin);
        patchGy = gradY(row-halfWin:row+halfWin, col-halfWin:col+halfWin);
        patchGt = gradT(row-halfWin:row+halfWin, col-halfWin:col+halfWin);

        % Form the linear system A * d = b.
        A = [patchGx(:), patchGy(:)]; % Design matrix.
        b = -patchGt(:);              % Target vector.

        % Solve via normal equations (A'*A) * d = A' * b.
        if rank(A'*A) >= 2
            delta = (A'*A) \ (A'*b);
            u(row, col) = delta(1);
            v(row, col) = delta(2);
        end
    end
end

% Post-processing: median filtering to reduce outliers.
filterSize = [5 5];
u = medfilt2(u, filterSize);
v = medfilt2(v, filterSize);
end

Supporting Function: Flow Visualization

function visualizeFlowField(U, V, backgroundImg)
% visualizeFlowField Overlays flow vectors on an image.
figure;
imshow(backgroundImg);
hold on;

% Subsample for a clearer visualization.
sampleStep = 10;
[gridX, gridY] = meshgrid(1:sampleStep:size(backgroundImg,2), ...
                          1:sampleStep:size(backgroundImg,1));
U_sampled = U(1:sampleStep:end, 1:sampleStep:end);
V_sampled = V(1:sampleStep:end, 1:sampleStep:end);

% Normalize arrow lengths for consistent display.
maxMag = max(sqrt(U_sampled(:).^2 + V_sampled(:).^2));
if maxMag > 0
    normFactor = 3 / maxMag;
else
    normFactor = 1;
end

quiver(gridX(:), gridY(:), ...
       U_sampled(:)*normFactor, V_sampled(:)*normFactor, ...
       0, 'y', 'LineWidth', 1.5);
title('Optical Flow Vector Field');
hold off;
end

Example Usage

% Load two consecutive video frames.
frame1 = imread('video_frame_001.png');
frame2 = imread('video_frame_002.png');

% Ensure images are grayscale.
if size(frame1, 3) == 3
    frame1 = rgb2gray(frame1);
    frame2 = rgb2gray(frame2);
end

% Set algorithm parameters and compute flow.
pyramidDepth = 4;   % Number of pyramid levels.
windowLength = 17; % Local window size (odd).
[horizontalFlow, verticalFlow] = computePyramidLK(frame1, frame2, ...
                                                  pyramidDepth, windowLength);

Algorithm Breakdown and Notes

1. Pyramidal Framework: A Gaussian pyramid is constructed using impyramid. Flow is computed at the coarsest level and then upsampled to initialize the computation at the next finer level. This allows the algorithm to handle larger displacements.

2. Core LK Method: For each level, the standard LK equations are solved within a local window. The system models brightness constancy, leading to the linear equation shown in the original material.

3. Iterative Warping: At each pyramid level, the second image is warped towards the first using the current flow estimate. The incremental flow (dX, dY) is then computed between the first image and the warped second image. This process helps refine the estimate.

4. Parameter Guidance:

  • Pyramid Levels (numLevels): 3 to 5 levels are typical. More levels can help capture very large motions.
  • Window Size (winSz): A size like 15x15 or 21x21 is common. Larger windows provide more spatial support but can oversmooth motion boundaries.

5. Potantial Enhancements: The basic implementation can be extended by adding iterative refinement within each pyramid level, employing robust cost functions, performing sub-pixel interpolation, or incorporating global smoothness constraints.

Tags: MATLAB Computer Vision Optical Flow Lucas-Kanade Image Processing

Posted on Fri, 15 May 2026 12:24:19 +0000 by Brandito520