Quantcast

Documentation Center

  • Trial Software
  • Product Updates

Corner Detection

This example shows how to generate HDL code from a design that computes the corner metric by using Harris' technique.

Algorithm

Corners are robust to image rotation, translation, and lighting change. They are used in many applications such as image registration and object tracking. Corners are usually identified through corner metric, which corresponds to the likelihood that the pixels locate at the corner of some objects. Peaks of corner metric identify the corners. The Harris' technique is the well known method for computing corner metric.

image_in = checkerboard(10);
metric = cornermetric(image_in);
figure;
subplot(1,2,1);
imshow(image_in);
title('Original');
subplot(1,2,2);
imshow(imadjust(metric));
title('Corner metric');

MATLAB Design

The following example shows how to implement the image processing algorithm for HDL code generation.

design_name = 'mlhdlc_corner_detection.m';
testbench_name = 'mlhdlc_corner_detection_tb.m';

Let us take a look at the MATLAB® design

type(design_name);
%#codegen
function [valid, ed, xfo, yfo, cm] = mlhdlc_corner_detection(data_in)

[~, ed, xfo, yfo] = mlhdlc_sobel(data_in);

cm = compute_corner_metric(xfo, yfo);

% compute valid signal
persistent cnt
if isempty(cnt)
  cnt = 0;
end
cnt = cnt + 1;
valid = cnt > 3*80+3 && cnt <= 80*80+3*80+3;


end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function bm = compute_corner_metric(gh, gv)

cmh = make_buffer_matrix_gh(gh);
cmv = make_buffer_matrix_gv(gv);
bm = compute_harris_metric(cmh, cmv);

end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function bm = make_buffer_matrix_gh(gh)

persistent b1 b2 b3 b4;
if isempty(b1)
    b1 = dsp.Delay('Length', 80);
    b2 = dsp.Delay('Length', 80);
    b3 = dsp.Delay('Length', 80);
    b4 = dsp.Delay('Length', 80);
end

b1p = step(b1, gh);
b2p = step(b2, b1p);
b3p = step(b3, b2p);
b4p = step(b4, b3p);

cc = [b4p b3p b2p b1p gh];

persistent h1 h2 h3 h4;
if isempty(h1)
    h1 = dsp.Delay();
    h2 = dsp.Delay();
    h3 = dsp.Delay();
    h4 = dsp.Delay();

%     h1 = dsp.Delay();
%     h2 = dsp.Delay();
%     h3 = dsp.Delay();
%     h4 = dsp.Delay();

end

h1p = step(h1, cc);
h2p = step(h2, h1p);
h3p = step(h3, h2p);
h4p = step(h4, h3p);

bm = [h4p h3p h2p h1p cc];

end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function bm = make_buffer_matrix_gv(gv)

persistent b1 b2 b3 b4;
if isempty(b1)
    b1 = dsp.Delay('Length', 80);
    b2 = dsp.Delay('Length', 80);
    b3 = dsp.Delay('Length', 80);
    b4 = dsp.Delay('Length', 80);
end

b1p = step(b1, gv);
b2p = step(b2, b1p);
b3p = step(b3, b2p);
b4p = step(b4, b3p);

cc = [b4p b3p b2p b1p gv];

persistent h1 h2 h3 h4;
if isempty(h1)
    h1 = dsp.Delay();
    h2 = dsp.Delay();
    h3 = dsp.Delay();
    h4 = dsp.Delay();
end

h1p = step(h1, cc);
h2p = step(h2, h1p);
h3p = step(h3, h2p);
h4p = step(h4, h3p);

bm = [h4p h3p h2p h1p cc];

end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function cm = compute_harris_metric(gh, gv)

[g1, g2, g3] = gaussian_filter(gh, gv);
[s1, s2, s3] = reduce_matrix(g1, g2, g3);

cm = (((s1*s3) - (s2*s2)) - (((s1+s3) * (s1+s3)) * 0.04));

end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function [g1, g2, g3] = gaussian_filter(gh, gv)

%g=fspecial('gaussian',[5 5],1.5);
g = [0.0144    0.0281    0.0351    0.0281    0.0144
     0.0281    0.0547    0.0683    0.0547    0.0281
     0.0351    0.0683    0.0853    0.0683    0.0351
     0.0281    0.0547    0.0683    0.0547    0.0281
     0.0144    0.0281    0.0351    0.0281    0.0144];

g1 = (gh .* gh) .* g(:)';
g2 = (gh .* gv) .* g(:)';
g3 = (gv .* gv) .* g(:)';

end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function [s1, s2, s3] = reduce_matrix(g1, g2, g3)

s1 = sum(g1);
s2 = sum(g2);
s3 = sum(g3);

end
type(testbench_name);
clear mlhdlc_corner_detection;
clear mlhdlc_sobel;

image_in = checkerboard(10);
[image_height, image_width] = size(image_in);

% Pre-allocating y for simulation performance
y_cm = zeros(image_height, image_width);
y_ed = zeros(image_height, image_width);
gradient_hori = zeros(image_height,image_width);
gradient_vert = zeros(image_height,image_width);

dataValidOut = y_cm;

idx_in = 1;
idx_out = 1;
for i=1:image_width+3
    for j=1:image_height+3
        if idx_in <= image_width * image_height
            u = image_in(idx_in);
        else
            u = 0;
        end
        idx_in = idx_in + 1;
        
        [valid, ed, gh, gv, cm] = mlhdlc_corner_detection(u);
        
        if valid
            
            y_cm(idx_out) = cm;
            y_ed(idx_out) = ed;
            gradient_hori(idx_out)   = gh;
            gradient_vert(idx_out)   = gv;
            
            idx_out = idx_out + 1;
        end
    end
end

padImage = y_cm;
findLocalMaxima = vision.LocalMaximaFinder('MaximumNumLocalMaxima', 100, ...
    'NeighborhoodSize', [11 11], ...
    'Threshold', 0.0005);
Corners = step(findLocalMaxima, padImage);
drawMarkers = vision.MarkerInserter('Size', 2); % Draw marker circles at corners
ImageCornersMarked = step(drawMarkers, image_in, Corners);

% Display results
% figure('Name', 'Corners');
% subplot(1,5,5);
% imagesc(y_cm), colormap('gray')
% figure('Name', 'Corners Marked on Original');
% imagesc(ImageCornersMarked), colormap('gray')


nplots = 4;

scrsz = get(0,'ScreenSize');
figure('Name', [mfilename, '_plot'], 'Position',[1 300 700 200])
subplot(1,nplots,1);
imshow(image_in,[min(image_in(:)) max(image_in(:))]);
title('Checker Board')
subplot(1,nplots,2);
imshow(gradient_hori(3:end,3:end),[min(gradient_hori(:)) max(gradient_hori(:))]);
title('Vertical Gradient')
subplot(1,nplots,3);
imshow(gradient_vert(3:end,3:end),[min(gradient_vert(:)) max(gradient_vert(:))]);
title('Horizontal Gradient')
% subplot(1,nplots,4);
% imshow(y_ed);
% title('Edges')
subplot(1,nplots,4);
imagesc(ImageCornersMarked)
title('Corners');


Simulate the Design

It is a good practice to simulate the design with the testbench prior to code generation to make sure there are no runtime errors.

mlhdlc_corner_detection_tb

Setup for the Example

Executing the following lines of code copies the necessary example files into a temporary folder

mlhdlc_demo_dir = fullfile(matlabroot, 'toolbox', 'hdlcoder', 'hdlcoderdemos', 'matlabhdlcoderdemos');
mlhdlc_temp_dir = [tempdir 'mlhdlc_cdetect'];

% create a temporary folder and copy the MATLAB files
cd(tempdir);
[~, ~, ~] = rmdir(mlhdlc_temp_dir, 's');
mkdir(mlhdlc_temp_dir);
cd(mlhdlc_temp_dir);

% copy the design files to the temporary directory
copyfile(fullfile(mlhdlc_demo_dir, design_name), mlhdlc_temp_dir);
copyfile(fullfile(mlhdlc_demo_dir, testbench_name), mlhdlc_temp_dir);
copyfile(fullfile(mlhdlc_demo_dir, 'mlhdlc_sobel.m'), mlhdlc_temp_dir);

Create a New HDL Coder™ Project

coder -hdlcoder -new mlhdlc_sobel_prj

Next, add the file 'mlhdlc_corner_detection.m' to the project as the MATLAB Function and 'mlhdlc_corner_detection_tb.m' as the MATLAB Test Bench.

You can refer to Getting Started with MATLAB to HDL Workflow tutorial for a more complete tutorial on creating and populating MATLAB HDL Coder projects.

Run Fixed-Point Conversion and HDL Code Generation

Launch HDL Advisor and right click on the 'Code Generation' step and choose the option 'Run to selected task' to run all the steps from the beginning through the HDL code generation.

Examine the generated HDL code by clicking on the hyperlinks in the Code Generation Log window.

Clean up the Generated Files

You can run the following commands to clean up the temporary project folder.

mlhdlc_demo_dir = fullfile(matlabroot, 'toolbox', 'hdlcoder', 'hdlcoderdemos', 'matlabhdlcoderdemos');
mlhdlc_temp_dir = [tempdir 'mlhdlc_cdetect'];
clear mex;
cd (mlhdlc_demo_dir);
rmdir(mlhdlc_temp_dir, 's');
Was this topic helpful?