专栏首页瓜大三哥形态学滤波(六)

形态学滤波(六)

形态学滤波(六)

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

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

上面的结构图中涉及到:

(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

本文分享自微信公众号 - 瓜大三哥(xiguazai_tortoise),作者:xiguazaitortoise

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2017-09-21

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 图像分割(五)

    图像分割(五) 之基于FPGA的局部自适应分割 子模块设计 数据累加模块add_tree 数据累加模块负责将窗口内所有元素与均值之差的平方相加,这里还是采用以前...

    anytao
  • 图像分割(四)

    图像分割(四) 之基于FPGA的局部自适应分割 子模块设计 窗口缓存模块win_buf 本模块不做任何算法上的处理,只是负责将当前输入像素的二维窗口元素缓存并组...

    anytao
  • 形态学滤波(五)

    形态学滤波(五) 之一维形态学腐蚀/膨胀子模块设计 对于图像处理而言,是纵向和横向两个维度的处理。我们知道,对于任何二维的操作,都可以分解为一维方向的操作来简化...

    anytao
  • IDEA 使用SequenceDiagram插件绘制时序图

      最近看代码,由于代码的调用层级深度比较多,层层深入到某处时,已经忘记了身处何处,虽然自己可以使用一些画图工具来时序图,但是,这种情况下,自己画时序图很繁琐,...

    JAVA葵花宝典
  • 分享自制的C#和VB Code互转工具

    作为.NET程序员,往往习惯使用一种语言(据我观察,2006年后的程序员习惯用C#,之前的喜欢VB)。而对于另一种语言虽然能读懂但是写起来总是比较费事。尤其面对...

    葡萄城控件
  • Here Documents 结合expect的使用--(1)

    使用expect 命令来解决自动交互问题是非常广泛的,expect有自己独特的语法,可以写expect脚本来解决复杂的交互问题;但是很多时候,我们会需要在she...

    干点啥吧
  • 新冠肺炎获正式命名COVID-19,钟南山「希望」疫情4月左右结束,回应「最长潜伏期24天」为个例

    昨晚,世界卫生组织(WHO)召开新一轮会议,探讨有关新冠病毒疫情事宜。会上对新冠病毒肺炎疾病进行了命名,为「COVID-19」,即 coronavirus di...

    机器之心
  • 介绍CodeRush Xpress for C#

    用过Eclipse编写java代码,感觉它的某些功能在visual studio 中是没有的,比如Toggle Mark Occurrences:

    williamwong
  • [python]使用django快速生成自己的博客小站,含详细部署方法

    一枝花算不算浪漫
  • 4.django restframework 项目部署到ubuntu18.04上(安装配置nginx)

    玩蛇的胖纸

扫码关注云+社区

领取腾讯云代金券