HLS实现Bilateral Filtering双边滤波器

时间:2022-07-08 18:26:28

双边滤波(Bilateral filter)是一种可以保边去噪的滤波器。之所以可以达到此去噪效果,是因为滤波器是由两个函数构成。一个函数是由几何空间距离决定滤波器系数。另一个由像素差值决定滤波器系数。

双边滤波器中,输出像素的值依赖于邻域像素的值的加权组合,

HLS实现Bilateral Filtering双边滤波器

权重系数w(i,j,k,l)取决于定义域核

HLS实现Bilateral Filtering双边滤波器

和值域核

HLS实现Bilateral Filtering双边滤波器

的乘积

HLS实现Bilateral Filtering双边滤波器

同时考虑了空间域与值域的差别,而Gaussian Filter和α均值滤波分别只考虑了空间域和值域差别。

template<int WIN_SZ,typename W_T>
unsigned char bilateralProc(
hls::Window<WIN_SZ,WIN_SZ,W_T> &win,
WEIGHT_VALUE weights[WIN_SZ*WIN_SZ][256],
WEIGHT_MAP map[(WIN_SZ>>1)*(WIN_SZ>>1)+1])
{
#pragma HLS INLINE
ap_ufixed<16,1> color_weights;
ap_ufixed<32,16> weight_sum=0;
ap_ufixed<32,16> px_sum=0;

for (int i=0;i<WIN_SZ;i++)
{
for (int j=0;j<WIN_SZ;j++)
{
#pragma HLS unroll
ap_uint<8> sub = WIN_SZ>>1;
ap_uint<8> sub_sq = sub*sub;
ap_int<8> ei = i-sub;
ap_int<8> ej = j-sub;
ap_uint<8> comp = ei*ei;
comp += ej*ej;
if(comp>sub_sq)
{
continue;
}
else
{
ap_int<9> diffpx = win(i, j) - win(WIN_SZ>>1,WIN_SZ>>1);
if(diffpx < 0)
{
diffpx = -diffpx;
}
if(comp == 0)
color_weights = 1;
else
color_weights = (ap_ufixed<16,1>)weights[map[comp]][diffpx];
px_sum += (color_weights)*(ap_uint<16>)(win(i,j));
weight_sum += color_weights;
}
}
}

ap_uint<8> value = (ap_ufixed<32,16>)(px_sum/weight_sum) + (ap_ufixed<32,16>)(0.5);

return value;
}


template<int WIN_SZ, int ROWS, int COLS, int SRC_T,int DST_T>
void _filter(
hls::Mat<ROWS, COLS, SRC_T> &src,
hls::Mat<ROWS, COLS, DST_T> &dst,
WEIGHT_VALUE weights[WIN_SZ*WIN_SZ][256],
WEIGHT_MAP map[(WIN_SZ>>1)*(WIN_SZ>>1)+1])
{
HLS_SIZE_T IMG_HEIGHT = src.rows;
HLS_SIZE_T IMG_WIDTH = src.cols;

hls::filter2d_kernel fk_opr;

hls::Window<WIN_SZ, WIN_SZ,HLS_TNAME(HLS_8UC1)> src_kernel_win;
hls::LineBuffer<WIN_SZ,MAX_WIDTH,HLS_TNAME(HLS_8UC1)> main_buf;
hls::LineBuffer<WIN_SZ,1,HLS_TNAME(HLS_8UC1)> col_buf;

HLS_SIZE_T fillvalue=255;
HLS_SIZE_T loophight=IMG_HEIGHT+WIN_SZ-1;
HLS_SIZE_T loopwidth=IMG_WIDTH+WIN_SZ-1;

HLS_SIZE_T buf_row=0;
HLS_SIZE_T buf_rows,buf_cols;
HLS_SIZE_T heightloop= IMG_HEIGHT+WIN_SZ-1;
HLS_SIZE_T widthloop = IMG_WIDTH+WIN_SZ-1;//one pixel overlap, so it should minus one

loop_height: for(HLS_SIZE_T i= 0;i< heightloop;i++) {
#pragma HLS LOOP_TRIPCOUNT MAX=ROWS
loop_width: for (HLS_SIZE_T j= 0;j< widthloop;j++) {
#pragma HLS DEPENDENCE array inter false
#pragma HLS LOOP_TRIPCOUNT MAX=COLS
#pragma HLS LOOP_FLATTEN OFF
#pragma HLS PIPELINE II=1
if(j<IMG_WIDTH) {
for(HLS_SIZE_T row=0; row<WIN_SZ; row++){
for(HLS_SIZE_T col=WIN_SZ-1; col>=1; col--)
{
src_kernel_win(row,col) = src_kernel_win(row,col-1); //column left shift
}
}

{
HLS_TNAME(SRC_T) temp;
if(i < IMG_HEIGHT)
src.data_stream[0] >> temp;
else
temp=fillvalue;
main_buf(0,j)=(temp&0xFF);
}

for(buf_row=0; buf_row<WIN_SZ; buf_row++){
// Fetch the column from the line buffer to shift into the window.
col_buf(buf_row,0)= main_buf(buf_row,j);
}

{
HLS_TNAME(HLS_8UC1) toppixel=col_buf(WIN_SZ-1,0);
src_kernel_win(WIN_SZ-1,0)=toppixel;
}

for(buf_row=WIN_SZ-1; buf_row>=1; buf_row--){
HLS_TNAME(HLS_8UC1) temp=col_buf(buf_row-1,0);
src_kernel_win(buf_row-1,0)=temp;
main_buf(buf_row,j)=temp;
}
}
else
{

for(HLS_SIZE_T row=0; row<WIN_SZ; row++){
for(HLS_SIZE_T col=WIN_SZ-1; col>=1; col--)
{
src_kernel_win(row,col) = src_kernel_win(row,col-1);
}
}
for(HLS_SIZE_T row=0; row<WIN_SZ; row++){
src_kernel_win(row,0)=fillvalue;
}
}

// figure out the output image pixel value
if(i >= (WIN_SZ-1) && j>=(WIN_SZ-1))
{
ap_uint<8> temp_out = bilateralProc(src_kernel_win, weights, map);

dst.data_stream[0] << temp_out;
}
}//w
}//h
}

void hls_BilateralFilter( AXI_STREAM &INPUT_STREAM, AXI_STREAM &OUTPUT_STREAM,int rows, int cols,
WEIGHT_VALUE weights[MAX_WIN_SZ*MAX_WIN_SZ][256],
WEIGHT_MAP map[(MAX_WIN_SZ>>1)*(MAX_WIN_SZ>>1)+1])
{
#pragma HLS INTERFACE axis port=INPUT_STREAM
#pragma HLS INTERFACE axis port=OUTPUT_STREAM

#pragma HLS INTERFACE s_axilite port=rows bundle=BUS_CTRL
#pragma HLS INTERFACE s_axilite port=cols bundle=BUS_CTRL
#pragma HLS INTERFACE s_axilite port=weights bundle=BUS_CTRL
#pragma HLS INTERFACE s_axilite port=map bundle=BUS_CTRL

#pragma HLS INTERFACE s_axilite port=return bundle=BUS_CTRL

hls::Mat<MAX_HEIGHT,MAX_WIDTH,HLS_8UC3> src(rows,cols);
hls::Mat<MAX_HEIGHT,MAX_WIDTH,HLS_8UC3> dst(rows,cols);
hls::Mat<MAX_HEIGHT,MAX_WIDTH,HLS_8UC3> src0(rows,cols);
hls::Mat<MAX_HEIGHT,MAX_WIDTH,HLS_8UC3> src1(rows,cols);
hls::Mat<MAX_HEIGHT,MAX_WIDTH,HLS_8UC1> gray0(rows,cols);
hls::Mat<MAX_HEIGHT,MAX_WIDTH,HLS_8UC1> gray1(rows,cols);

#pragma HLS dataflow
hls::AXIvideo2Mat(INPUT_STREAM, src);

hls::Duplicate(src,src0,src1);

hls::CvtColor<HLS_BGR2GRAY>(src0,gray0);

_filter<MAX_WIN_SZ>(gray0, gray1, weights, map);

hls::CvtColor<HLS_GRAY2BGR>(gray1,dst);

hls::Mat2AXIvideo(dst, OUTPUT_STREAM);
}


C仿真效果:

HLS实现Bilateral Filtering双边滤波器

                                                                  原图

HLS实现Bilateral Filtering双边滤波器

双边滤波器

HLS实现Bilateral Filtering双边滤波器

对比一下高斯模糊滤波器