メディアン・フィルタ2: Verilog HDLでの実装
FPGA(Nexys4 DDR)を使ったリアルタイムエッジ検出 - メモ置き場
では,カメラから取り込んだ画像の平滑化としてメディアン・フィルタを使っている.前回に引き続きVerilog HDLで実装した方法を書いておく.
初めに
メディアンフィルタとは,中心の画素の値を領域に含まれる画素の中央値に置き換える,というものであった.
HDLで実装するには,与えられた画素(9個,25個,49個,…)をソートしてその中央値を返す仕組みが必要となる.
ソフトウェア的にはソートアルゴリズムの実装は簡単であるが,ハードウェアとしてやるには少し工夫が必要である.
今回は3×3のメディアン・フィルタを実装するので,9個の値から中央値を選び出すような回路を作成したい.
さらに欲を言うと,レイテンシ0で中央値を算出してくれる回路を作りたい.
調べてみると,次のような文献が見つかった:
3×3メディアンフィルタの高速アルゴリズム(浜村倫行, 2002)
この文献を元に実装する.具体的にざっくり説明すると,
1. 入力データを適当に3個ずつ3組に分け,それぞれの組のなかでソートする.
2. 3組をソートする.基準は,各組の中央値の大きい順とする.大きい順にA,B,C組とする.
3. Aの最小値,Bの中央値,Cの最大値を比較すると,9個の数の中央値がわかる
ということをやっている.結局3個の数のソートをVerilog HDLで実装すればいいわけだ.
今回はレイテンシを0にしたいので,Verilog HDLの実装は全て組み合わせ回路で記述する.具体的にどう実装したかについて説明する.
Verilogでの実装
3つの値のソートなので,通りの値比較をして,その結果を元にソートした値を出力する,と言う方針でいく.入力される値をとして
wire [2:0] switch = {( (p0<p1) ? 1'b1 : 1'b0), ( (p0<p2) ? 1'b1 : 1'b0), ( (p1<p2) ? 1'b1 : 1'b0)}
とすればswitch
の値をみることでp0, p1, p2
の大小関係がわかるようになる.例えばswich = 3'b011
はなのでとなる.
したがって,switch
の値でセレクタを書けば良い.今回は組み合わせ回路を実装するので,次のようにfunctionを使った.sort_3data_funcは与えられたデータを(小,中,大)の信号線にまとめてくれる.
parameter DATA_WIDTH = 8; function [DATA_WIDTH*3-1:0] sort_3data_func; input wire [DATA_WIDTH-1:0] p0,p1,p2; begin // swich shows the order of 3 inputs. // swich = 3'b011 means p0>=p1, p0<p2, p1<p2 // so the order is p1 < p0 < p2 case(switch) 3'b_111 : sort_3data_func = {p0,p1,p2}; // p0 < p1 < p2 case 3'b_110 : sort_3data_func = {p0,p2,p1}; // p0 < p2 < p1 case 3'b_011 : sort_3data_func = {p1,p0,p2}; // p1 < p0 < p2 case 3'b_001 : sort_3data_func = {p1,p2,p0}; // p1 < p2 < p0 case 3'b_100 : sort_3data_func = {p2,p0,p1}; // p2 < p0 < p1 case 3'b_000 : sort_3data_func = {p2,p1,p0}; // p2 < p1 < p0 case default : sort_3data_func = {p0,p1,p2}; endcase end endfunction
同様に3組のソートも行うfunctionを書き,中央値を出してくれるmoduleを作った.コード全体はgit repositoryのov7670_sobel.srcs/sources_1/new/median_filter.v である.
moduleのテスト
moduleのテストをVivadoのbehavior simulationで行なった.テスト用の入力パターンと対応する中央値はC++で作成した.
シミュレーション結果の波形を示す.
d0〜d8が与えた9つの値.ansが事前に計算した出力されるべき中央値で,d_outが実際にモジュールのシミュレーションで出力された中央値である.
レイテンシ0で正しく中央値を吐き出していることが確認できた.