This example shows how to generate HDL code from a design that computes the corner metric by using Harris' technique.
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); cornerDetector = vision.CornerDetector('MetricMatrixOutputPort',true); [~,metric] = step(cornerDetector,image_in); figure; subplot(1,2,1); imshow(image_in); title('Original'); subplot(1,2,2); imshow(imadjust(metric)); title('Corner metric');
The following example shows how to implement the image processing algorithm for HDL code generation.
design_name = 'mlhdlc_corner_detection'; testbench_name = 'mlhdlc_corner_detection_tb';
Let us take a look at the MATLAB® design
type(design_name);
%#codegen function [valid, ed, xfo, yfo, cm] = mlhdlc_corner_detection(data_in) % Copyright 2011-2015 The MathWorks, Inc. [~, 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(); 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);
% Copyright 2011-2015 The MathWorks, Inc. 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') axis square subplot(1,nplots,2); imshow(gradient_hori(3:end,3:end),[min(gradient_hori(:)) max(gradient_hori(:))]); title(['Vertical',char(10),' Gradient']) axis square subplot(1,nplots,3); imshow(gradient_vert(3:end,3:end),[min(gradient_vert(:)) max(gradient_vert(:))]); title(['Horizontal',char(10),' Gradient']) axis square % subplot(1,nplots,4); % imshow(y_ed); % title('Edges') subplot(1,nplots,4); imagesc(ImageCornersMarked) title('Corners'); axis square
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
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,'.m*']), mlhdlc_temp_dir); copyfile(fullfile(mlhdlc_demo_dir, [testbench_name,'.m*']), mlhdlc_temp_dir); copyfile(fullfile(mlhdlc_demo_dir, 'mlhdlc_sobel.m*'), mlhdlc_temp_dir);
coder -hdlcoder -new mlhdlc_corner_detect_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.
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.
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');