Main Content

このページの内容は最新ではありません。最新版の英語を参照するには、ここをクリックします。

適応メディアン フィルターの 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 関数はモジュール化されていて、いくつかの関数を使用してイメージのノイズをフィルター処理します。

適応フィルター 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

より高速なシミュレーションのための設計の高速化

テスト ベンチをより高速にシミュレートするには、次を行います。

1. MATLAB Coder™ を使用して MEX ファイルを作成します。これらの手順は、設計の固定小数点シミュレーションの実行時に HDL ワークフロー アドバイザーによって自動化されます。

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

2.MEX ファイルを使用して設計をシミュレートします。テスト ベンチの実行時に、HDL Coder は MEX ファイルを使用してシミュレーションをより高速に実行します。

  mlhdlc_median_filter_tb

3.MEX ファイルをクリーンアップします。

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

HDL Coder プロジェクトの作成

1. 次のように HDL Coder プロジェクトを作成します。

coder -hdlcoder -new mlhdlc_med_filt_prj

2.mlhdlc_median_filter.m ファイルを [MATLAB 関数] としてプロジェクトに追加し、mlhdlc_median_filter_tb.m[MATLAB テスト ベンチ] として追加します。

3.[型の自動定義] をクリックして MATLAB 関数 mlhdlc_median_filter の入力と出力の推奨される型を使用します。

MATLAB HDL Coder プロジェクトの作成と入力に関する詳細なチュートリアルについては、MATLAB から HDL へのワークフロー入門を参照してください。

固定小数点変換と HDL コード生成の実行

  1. [ワークフロー アドバイザー] ボタンをクリックして、ワークフロー アドバイザーを開始します。

  2. [HDL コード生成] タスクを右クリックして [選択したタスクまで実行] を選択します。

単一の HDL ファイル mlhdlc_median_filter_fixpt.vhd が MATLAB 設計に対して生成されます。フィルター設計に対する生成された HDL コードを確認するには、コード生成ログのウィンドウでハイパーリンクをクリックします。

MATLAB 設計の関数ごとに HDL ファイルを生成する場合は、[HDL コード生成] タスクの [詳細設定] タブで [関数に対してインスタンス化可能なコードを生成] チェック ボックスを選択します。関数のインスタンス化可能なコードの生成も参照してください。