Генерация HDL-кода для алгоритма детектирования углов методом Харриса

В этом примере показано, как сгенерировать HDL-код из проекта MATLAB®, который вычисляет угловую метрику при помощи метода Харриса.

Угловой алгоритм обнаружения

Угол является точкой в изображении, где два ребра изображения пересекаются. Углы устойчивы к повороту изображения, переводу и освещению. Углы содержат важные функции, которые можно использовать во многих приложениях, таких как восстановление данных изображения, регистрации изображений и объектного отслеживания.

Угловые алгоритмы обнаружения идентифицируют углы при помощи угловой метрики. Эта метрика соответствует вероятности пикселей, расположенных на углу определенных объектов. Peaks угловой метрики идентифицирует углы. См. также Угловое Обнаружение (Computer Vision Toolbox) в документации Computer Vision Toolbox. Угловой алгоритм обнаружения:

1. Читает входное изображение.

Image_in = checkerboard(10);

2. Находит углы.

cornerDetector = detectHarrisFeatures(Image_in);

3. Отображает результаты.

[~,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');

Угловое обнаружение проект MATLAB

design_name = 'mlhdlc_corner_detection';
testbench_name = 'mlhdlc_corner_detection_tb';

Рассмотрите проект MATLAB:

edit(design_name);
%#codegen
function [valid, ed, xfo, yfo, cm] = mlhdlc_corner_detection(data_in)
%   Copyright 2011-2019 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


Функция MATLAB является модульной и использует несколько функций, чтобы вычислить углы изображения. Функция:

  • compute_corner_metric вычисляет угловую метрическую матрицу путем инстанцирования функционального compute_harris_metric.

  • compute_harris_metric обнаруживает угловые функции во входном изображении путем инстанцирования функций gaussian_filter и reduce_matrix. Функция берет выходные параметры make_buffer_matrix_gh и make_buffer_matrix_gv как входные параметры.

Угловое обнаружение испытательный стенд MATLAB

Рассмотрите испытательный стенд MATLAB:

edit(testbench_name);
clear mlhdlc_corner_detection;
clear mlhdlc_sobel;

%   Copyright 2011-2019 The MathWorks, Inc.

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 circles at corners
ImageCornersMarked = step(drawMarkers, image_in, Corners);

% Display results
% ...
%

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',newline,' Gradient'])
axis square

subplot(1,nplots,3);
imshow(gradient_vert(3:end,3:end),[min(gradient_vert(:)) max(gradient_vert(:))]);
title(['Horizontal',newline,' Gradient'])
axis square

% subplot(1,nplots,4);
% imshow(y_ed);
% title('Edges')

subplot(1,nplots,4);
imagesc(ImageCornersMarked)
title('Corners');
axis square

Протестируйте алгоритм MATLAB

Чтобы избежать ошибок времени выполнения, симулируйте проект с испытательным стендом.

mlhdlc_corner_detection_tb

Создайте папку и скопируйте соответствующие файлы

Прежде чем вы сгенерируете HDL-код для проекта MATLAB, скопируете проект и файлы испытательного стенда к writeable папке. Эти команды копируют файлы во временную папку.

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

Создайте временную папку и скопируйте файлы MATLAB.

cd(tempdir);
[~, ~, ~] = rmdir(mlhdlc_temp_dir, 's');
mkdir(mlhdlc_temp_dir);
cd(mlhdlc_temp_dir);

Скопируйте файлы проекта во временную директорию.

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);

Создайте проект HDL Coder™

1. Создайте проект HDL Coder:

coder -hdlcoder -new mlhdlc_corner_detect_prj

2. Добавьте файл mlhdlc_corner_detection.m к проекту как функция MATLAB и mlhdlc_corner_detection_tb.m как испытательный стенд MATLAB.

3. Нажмите типы Autodefine, чтобы использовать рекомендуемые типы для вводов и выводов функции MATLAB mlhdlc_corner_detection.m.

Обратитесь к Началу работы с MATLAB к Рабочему процессу HDL для более полного примера при создании и заполнении проектов HDL Coder MATLAB.

Запустите преобразование фиксированной точки и генерацию HDL-кода

  1. Нажмите кнопку Workflow Advisor, чтобы запустить Советника по вопросам Рабочего процесса.

  2. Щелкните правой кнопкой мыши по задаче генерации HDL-кода и выберите Run к выбранной задаче.

Один файл HDL mlhdlc_corner_detection_fixpt.vhd сгенерирован для проекта MATLAB. Чтобы исследовать сгенерированный HDL-код на создание фильтра, кликните по гиперссылкам в окне Code Generation Log.

Если вы хотите сгенерировать файл HDL для каждой функции в вашем проекте MATLAB во Вкладке "Дополнительно" задачи генерации HDL-кода, выберите Generate instantiable код для флажка функций. См. также Генерируют Код Instantiable для Функций.

Очистите сгенерированные файлы

Чтобы очистить временную папку проекта, запустите эти команды:

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');