exponenta event banner

Генерация кода HDL для адаптивного медианного фильтра

В этом примере показано, как генерировать код HDL из конструкции MATLAB ®, которая реализует алгоритм адаптивного медианного фильтра и генерирует код HDL.

Конструкция адаптивного фильтра MATLAB

Адаптивный медианный фильтр выполняет пространственную обработку для уменьшения шума в изображении. Фильтр сравнивает каждый пиксель изображения с окружающими пикселями. Если одно из значений пикселя значительно отличается от большинства окружающих пикселей, пиксель рассматривается как шум. Затем алгоритм фильтрации заменяет шумовой пиксель медианными значениями окружающих пикселей. Этот процесс повторяется до тех пор, пока все шумовые пиксели в изображении не будут удалены.

design_name = 'mlhdlc_median_filter';
testbench_name = 'mlhdlc_median_filter_tb';

Просмотрите проект MATLAB:

edit(design_name);
%#codegen
function [pixel_val, pixel_valid] = mlhdlc_median_filter(c_data, c_idx)
%   Copyright 2011-2019 The MathWorks, Inc.

smax = 9;
persistent window;
if isempty(window)
    window = zeros(smax, smax);
end

cp = ceil(smax/2); % center pixel;

w3 = -1:1;
w5 = -2:2;
w7 = -3:3;
w9 = -4:4;

r3 = cp + w3;      % 3x3 window
r5 = cp + w5;      % 5x5 window
r7 = cp + w7;      % 7x7 window
r9 = cp + w9;      % 9x9 window

d3x3 = window(r3, r3);
d5x5 = window(r5, r5);
d7x7 = window(r7, r7);
d9x9 = window(r9, r9);

center_pixel = window(cp, cp);


% use 1D filter for 3x3 region
outbuf = get_median_1d(d3x3(:)');
[min3, med3, max3] = getMinMaxMed_1d(outbuf);

% use 2D filter for 5x5 region
outbuf = get_median_2d(d5x5);
[min5, med5, max5] = getMinMaxMed_2d(outbuf);

% use 2D filter for 7x7 region
outbuf = get_median_2d(d7x7);
[min7, med7, max7] = getMinMaxMed_2d(outbuf);

% use 2D filter for 9x9 region
outbuf = get_median_2d(d9x9);
[min9, med9, max9] = getMinMaxMed_2d(outbuf);


pixel_val = get_new_pixel(min3, med3, max3, ...
    min5, med5, max5, ...
    min7, med7, max7, ...
    min9, med9, max9, ...
    center_pixel);


% we need to wait until 9 cycles for the buffer to fill up
% output is not valid every time we start from col1 for 9 cycles.
persistent datavalid
if isempty(datavalid)
    datavalid = false;
end
pixel_valid = datavalid;
datavalid = (c_idx >= smax);


% build the 9x9 buffer
window(:,2:smax) = window(:,1:smax-1);
window(:,1) = c_data;

end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function [min, med, max] = getMinMaxMed_1d(inbuf)

max = inbuf(1);
med = inbuf(ceil(numel(inbuf)/2));
min = inbuf(numel(inbuf));

end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function [min, med, max] = getMinMaxMed_2d(inbuf)

[nrows, ncols] = size(inbuf);
max = inbuf(1, 1);
med = inbuf(ceil(nrows/2), ceil(ncols/2));
min = inbuf(nrows, ncols);

end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function new_pixel  = get_new_pixel(...
    min3, med3, max3, ...
    min5, med5, max5, ...
    min7, med7, max7, ...
    min9, med9, max9, ...
    center_data)

if (med3 > min3 && med3 < max3)
    new_pixel = get_center_data(min3, med3, max3,center_data);
elseif (med5 > min5 && med5 < max5)
    new_pixel = get_center_data(min5, med5, max5,center_data);
elseif (med7 > min7 && med7 < max7)
    new_pixel = get_center_data(min7, med7, max7,center_data);
elseif (med9 > min9 && med9 < max9)
    new_pixel = get_center_data(min9, med9, max9,center_data);
else
    new_pixel = center_data;
end

end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function [new_data] = get_center_data(min,med,max,center_data)
if center_data <= min || center_data >= max
    new_data = med;
else
    new_data = center_data;
end
end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% perform median 1d computation
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function outbuf = get_median_1d(inbuf)

numpixels = length(inbuf);

tbuf = inbuf;

for ii=coder.unroll(1:numpixels)
    if bitand(ii,uint32(1)) == 1  
        tbuf = compare_stage1(tbuf);
    else
        tbuf = compare_stage2(tbuf);
    end
end

outbuf = tbuf;

end

function outbuf = compare_stage1(inbuf)
numpixels = length(inbuf);
tbuf = compare_stage(inbuf(1:numpixels-1));
outbuf = [tbuf(:)' inbuf(numpixels)];
end

function outbuf = compare_stage2(inbuf)
numpixels = length(inbuf);
tbuf = compare_stage(inbuf(2:numpixels));
outbuf = [inbuf(1) tbuf(:)'];
end

function [outbuf] = compare_stage(inbuf)

step = 2;
numpixels = length(inbuf);

outbuf = inbuf;

for ii=coder.unroll(1:step:numpixels)
    t = compare_pixels([inbuf(ii), inbuf(ii+1)]);
    outbuf(ii) = t(1);
    outbuf(ii+1) = t(2);
end

end

function outbuf = compare_pixels(inbuf)
if (inbuf(1) > inbuf(2))
    outbuf = [inbuf(1), inbuf(2)];
else
    outbuf = [inbuf(2), inbuf(1)];
end
end


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% perform median 2d computation
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function outbuf = get_median_2d(inbuf)

outbuf = inbuf;
[nrows, ncols] = size(inbuf);
for ii=coder.unroll(1:ncols)
    colData = outbuf(:, ii)';
    colDataOut = get_median_1d(colData)';
    outbuf(:, ii) = colDataOut;
end
for ii=coder.unroll(1:nrows)
    rowData = outbuf(ii, :);
    rowDataOut = get_median_1d(rowData);
    outbuf(ii, :) = rowDataOut;
end

end

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

Испытательный стенд Adaptive Filter MATLAB

Испытательный стенд MATLAB mlhdlc_median_filter_tb выполняет проектирование фильтра с использованием репрезентативного диапазона ввода.

Проверьте тестовый стенд MATLAB:

edit(testbench_name);
I = imread('mlhdlc_img_pattern_noisy.tif');
J = I;

%   Copyright 2011-2019 The MathWorks, Inc.

smax = 9;
[nrows, ncols] = size(I);
ll = ceil(smax/2);
ul = floor(smax/2);

for ii=1:ncols-smax
    for jj=1:nrows-smax
        
        c_idx = ii;                    
        c_data = double(I(jj:jj+smax-1, ii));            
                
        [pixel_val, pixel_valid] = mlhdlc_median_filter(c_data, c_idx);
        
        if pixel_valid
            J(jj, ii) = pixel_val;
        end
    end
end

h = figure;
set( h, 'Name', [ mfilename, '_plot' ] );
subplot( 1, 2, 1 );
imshow( I, [  ] );
subplot( 1, 2, 2 );
imshow( J, [  ] );



Тестирование алгоритма MATLAB

Во избежание ошибок во время выполнения смоделировать конструкцию с помощью испытательного стенда.

mlhdlc_median_filter_tb

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

Перед созданием кода HDL для проекта MATLAB скопируйте файлы проекта и тестового стенда в записываемую папку. Эти команды копируют файлы во временную папку.

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

Создайте временную папку и скопируйте файлы 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_img_pattern_noisy.tif'), mlhdlc_temp_dir);

Ускорение проектирования для более быстрого моделирования

Для более быстрого моделирования испытательного стенда:

1. Создайте файл MEX с помощью Coder™ MATLAB. Помощник по рабочим процессам HDL автоматизирует эти шаги при выполнении моделирования конструкции с фиксированной точкой.

  codegen -o mlhdlc_median_filter -args {zeros(9,1), 0} mlhdlc_median_filter
  [~, tbn] = fileparts(testbench_name);

2. Моделирование конструкции с помощью файла MEX. При запуске тестового стенда кодер HDL использует файл MEX и выполняет моделирование быстрее.

  mlhdlc_median_filter_tb

3. Очистите файл MEX.

  clear mex;
  rmdir('codegen', 's');
  delete(['mlhdlc_median_filter', '.', mexext]);

Создание проекта кодера HDL

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

coder -hdlcoder -new mlhdlc_med_filt_prj

2. Добавить файл mlhdlc_median_filter.m в качестве функции MATLAB и mlhdlc_median_filter_tb.m в качестве испытательного стенда MATLAB.

3. Щелкните Автоопределение типов (Autodefine types) и используйте рекомендуемые типы для входов и выходов функции MATLAB. mlhdlc_median_filter.

Более подробное руководство по созданию и заполнению проектов кодера MATLAB HDL см. в разделе Начало работы с MATLAB в Workflow-процессе HDL.

Выполнение преобразования с фиксированной точкой и создание кода HDL

  1. Нажмите кнопку Помощник по рабочим процессам, чтобы запустить помощник по рабочим процессам.

  2. Щелкните правой кнопкой мыши задачу Создание кода HDL и выберите Выполнить для выбранной задачи.

Один файл HDL mlhdlc_median_filter_fixpt.vhd создается для проекта MATLAB. Чтобы проверить созданный код HDL для конструкции фильтра, щелкните гиперссылки в окне Журнал генерации кода (Code Generation Log).

Если требуется создать файл HDL для каждой функции в конструкции MATLAB, на вкладке Дополнительно (Advanced) задачи Создание кода HDL (HDL Code Generation) установите флажок Генерировать код экземпляра для функций (Generate instantable code for functions). См. также раздел Создание кода экземпляра для функций.

Очистка созданных файлов

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

  mlhdlc_demo_dir = fullfile(matlabroot, 'toolbox', 'hdlcoder', 'hdlcoderdemos', 'matlabhdlcoderdemos');
  mlhdlc_temp_dir = [tempdir 'mlhdlc_med_filt'];
  clear mex;
  cd (mlhdlc_demo_dir);
  rmdir(mlhdlc_temp_dir, 's');