前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >形态学滤波(六)

形态学滤波(六)

作者头像
瓜大三哥
发布2018-02-26 11:35:17
6610
发布2018-02-26 11:35:17
举报
文章被收录于专栏:瓜大三哥瓜大三哥

形态学滤波(六)

之二维形态学腐蚀/膨胀子模块设计

按照二维扩展的思路,将每一行的一维算子的计算结果对齐在列方向上再进行一维运算,得到的结果即是二维运算结果。

上面的结构图中涉及到:

(1)minmax(0)为当前行的一维运算数据流。

(2)Line_buffer(0)中数据为第(i-1)行的一维运算数据流。

(3)Line_buffer(i)中数据为第(i-1)行的一维运算数据流与第i行的一维运算数据流的比较结果。

`timescale 1ns / 1ps

module morph_2D(

rst_n,

clk,

din,

din_valid,

dout_valid,

dout,

vsync, //输入场同步信号

vsync_out //输出场同步信号

);

parameter IH = 512;

parameter IW = 640;

parameter DW = 14;

parameter KSZ = 3;

parameter ERO_DIL = 1; //0 膨胀操作

//1 腐蚀操作

localparam med_idx = (KSZ>>1);

input rst_n;

input clk;

input [DW-1:0] din;

input din_valid;

input vsync;

output [DW-1:0] dout;

output dout_valid;

output vsync_out;

reg rst_all;

reg [DW-1:0] line_din[0:KSZ-2];

wire [DW-1:0] line_dout[0:KSZ-2];

wire [KSZ-2:0] line_empty;

wire [KSZ-2:0] line_full;

wire [KSZ-2:0] line_rden;

reg [KSZ-2:0] line_wren;

wire [9:0] line_count [0:KSZ-2];

wire [DW-1:0] min_max_value;

wire [DW-1:0] min_max_value_r;

wire din_valid_r;

reg [DW-1:0] min[0:KSZ-1];

reg [DW-1:0] max[0:KSZ-1];

reg [KSZ-2:0] buf_pop_en;

reg valid_r;

reg [10:0] in_line_cnt;

reg [15:0] flush_cnt;

reg flush_line;

reg [15:0] out_pixel_cnt;

reg [15:0] out_line_cnt;

reg [DW-1:0] dout_temp_r;

reg dout_valid_temp_r;

wire [DW-1:0] dout_temp;

wire dout_valid_temp;

wire is_boarder;

wire valid;

reg din_valid_r2;

wire [31:0] j;

wire [31:0] k;

wire rst_all_low;

wire data_tmp1[0:KSZ-2];

wire [DW-1:0] data_tmp2;

wire [DW-1:0] data_tmp3;

//帧同步复位信号

always @(posedge clk or negedge rst_n)

if(~rst_n)

rst_all <= 1'b1;

else

begin

if(vsync)

rst_all <= 1'b1;

else

rst_all <= 1'b0;

end

//低电平帧同步复位信号

assign rst_all_low = ~rst_all;

//全局有效信号

assign valid = din_valid | flush_line;

//一维方向上的Morph操作

morph_1D row_1st(

.rst_n(rst_all_low),

.clk(clk),

.din(din),

.din_valid(valid),

.dout_valid(din_valid_r),//一维输出有效信号

.dout(min_max_value) //一维输出min_max_value

);

//缓存一维输出有效信号用于时序对齐

always @(posedge clk)

din_valid_r2 <= din_valid_r;

always @(*) min[0] <= min_max_value;

always @(*) max[0] <= min_max_value;

generate

begin : xdhl0

genvar i;

for(i=0;i<=KSZ-2;i=i+1)

begin : buf_cmp_inst

assign data_tmp[i] = din_valid_r & line_rden[i];

//输入有效信号

//例化列方向上的比较电路

minmax cmp_inst(

.clk(clk),

.valid(data_tmp1[i]),

.din_a(line_dout[i]),

.din_b(min_max_value),

.dout_min(min[i+1]),

.dout_max(max[i+1])

);

if(ERO_DIL)

begin : map10

always @(*) line_din[i] <= min[i];//腐蚀取最小值

end

if(~ERO_DIL)

begin : map11

always @(*) line_din[i] <= max[i];//膨胀取最大值

end

if(i==0)

begin : map12

always @(din_valid_r)

line_wren[i] <= din_valid_r;//第一个行缓存的输入为一维数据输出

end

if(i!=0)

begin : map13

always @(posedge clk)

begin

if(rst_all)

line_wren[i] <= 1'b0;

else

line_wren[i] <= line_rden[i-1]; //其他行缓存接成菊花链结构

end

end

assign line_rden[i] = buf_pop_en[i] & din_valid_r;

//行缓存装满后允许流水线开始运行

always @(posedge clk)

begin

if(rst_all)

buf_pop_en[i] <= 1'b0;

else if(line_count[i] == IW)

buf_pop_en[i] <= 1'b1;

end

//例化行缓存

fifo_generator_0 line_buffer_inst (

.clk(clk), // input wire clk

.rst(rst_all), // input wire rst

.din(line_din[i]), // input wire [13 : 0] din

.wr_en(line_wren[i]), // input wire wr_en

.rd_en(line_rden[i]), // input wire rd_en

.dout(line_dout[i]), // output wire [13 : 0] dout

.full(line_full[i]), // output wire full

.empty(line_empty[i]) // output wire empty

);

end

end

endgenerate

generate

if(ERO_DIL)

begin : map14

assign dout_temp = (line_rden[KSZ-2]==1'b0) ? min[med_idx] : min[KSZ-1];

end

endgenerate

generate

if(~ERO_DIL)

begin : map15

assign dout_temp = (line_rden[KSZ-2]==1'b0) ? max[med_idx] : max[KSZ-1];

end

endgenerate

//输出有效信号

assign dout_valid_temp = (line_rden[KSZ-2]==1'b0) ? line_wren[med_idx] : (din_valid_r2 & buf_pop_en[KSZ-2]);

//输出场同步信号

generate

if(KSZ == 5)

begin : map16

assign vsync_out = ((din_valid_r2==1'b1)&(line_wren[1]==1'b0)) ? 1'b1 : 1'b0;

end

endgenerate

//边界清零

assign data_tmp2 = (dout_valid_temp) ? dout_temp : {DW{1'b0}};

assign data_tmp3 = (is_boarder) ? {DW{1'b0}} :data_tmp2;

always @(posedge clk)

begin

if(rst_all)

begin

dout_temp_r <= {DW{1'b0}};

dout_valid_temp <= 1'b0;

valid_r <= 1'b0;

end

else

begin

dout_temp_r <= data_tmp3;

dout_valid_temp_r <= dout_valid_temp;

valid_r <= valid;

end

end

//输出数据流与输出数据有效

assign dout = dout_temp_r;

assign dout_valid = dout_valid_temp_r;

//输入行计数

always @(posedge clk)

begin

if(rst_all)

in_line_cnt <= {11{1'b0}};

else

in_line_cnt in_line_cnt +1'b1;

end

//溢出行计数及溢出行内计数

always @(posedge clk)

begin

if(rst_all)

begin

flush_line <= 1'b0;

flush_cnt <= {16{1'b0}};

end

else

begin

if(flush_cnt >= (IW-1))

flush_cnt <= {16{1'b0}};

else if(flush_line)

flush_cnt <= flush_cnt +1'b1;

if(flush_cnt >= (IW-1))

flush_line <= 1'b0;

else if(in_line_cnt>=IH&out_line_cnt<(IH-1))

flush_line <= 1'b1;

end

end

//输出行计数和输出行内计数

always @(posedge clk)

begin

if(rst_all)

begin

out_pixel_cnt <= {16{1'b0}};

out_line_cnt <= {11{1'b0}};

end

else

begin

if(dout_valid_temp_r==1'b1 & dout_valid_temp==1'b0)

out_line_cnt <= out_line_cnt + 1'b1;

else

out_line_cnt <= out_line_cnt;

if(dout_valid_temp_r==1'b1 & dout_valid_temp==1'b0)

out_pixel_cnt <= {16{1'b0}};

else

out_pixel_cnt <= out_pixel_cnt + 1'b1;

end

end

//边界判决

assign is_boarder = (((dout_valid_temp==1'b1)

&(out_pixel_cnt<=(med_idx-1)

|out_pixel_cnt >= (IW-med_idx)

|out_line_cnt <= (med_idx-1)

|out_line_cnt >= (IH-med_idx)) ? 1'b1 : 1'b0;

endmodule

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2017-09-21,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 瓜大三哥 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 形态学滤波(六)
  • 之二维形态学腐蚀/膨胀子模块设计
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档