ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

基于 FPGA 的高级数字电路设计(9)数学形态学设计

2021-10-04 11:34:26  阅读:193  来源: 互联网

标签:缓存 运算 FPGA 物体 数字电路 腐蚀 wire 设计 膨胀


Morphology(形态学)

在数学形态学中,闭运算被定义为先膨胀后腐蚀,反之,开运算被定义为先腐蚀后膨胀。膨胀与腐蚀(Dilate and Erode)操作被称为形态学操作。(注意,这里是先闭后开,即膨胀腐蚀腐蚀膨胀,输入大小为 640*480,窗口为 21*21)。

1、膨胀

  会扩大一幅图像中的组成部分(扩大白色区域,缩小黑色区域);例如,5*5 大小的 Filter 在一幅二值化图像上移动,就像一个滤波器一样,如果像素区域在 5*5 窗口中都是黑色,则将像素变成黑色,黑色为 0(0),即全 0 为 0 ,否则为 1。

2、腐蚀

  会缩小一幅图像中的组成部分(缩小白色区域,扩大黑色区域),例如,5*5 大小的 Filter 在一幅二值化图像上移动,就像一个滤波器一样,如果像素区域在 5*5 窗口中都是白色,则将像素变成白色,白色为 255(1),即全 1 为 1 ,否则为 0。

  数学形态学在降噪中是有用的,可以平滑物体的轮廓、消除小斑点或突出物、填补轮廓线中的断裂、关闭物体内的小孔或暗区等等;例如开运算中,腐蚀首先消除噪声并收缩物体,然后膨胀再次扩大物体。

1、开运算的效果:

  1. 删除小物体(滤掉突刺);
  2. 将物体拆分为小物体(切断细长搭接)起分离作用;
  3. 平滑大物体边界而不明显改变它们面积(平滑图像轮廓)。

2、闭运算的作用:

  1. 填充物体的裂缝和小洞;
  2. 连相近物体(搭接短的间断)起连通补接作用;
  3. 平滑大物体边界而不明显改变它们面积(平滑图像轮廓)。

以下是简单地形态学操作代码:

module Morphology(
		clk_i,
		rst_n,

		iStart,
		iData,

		oStart,
		oData
		);
input clk_i;
input rst_n;

input iStart;
input iData;

output oStart;
output oData;

//=======================================================
// output reg and wire
//=======================================================
wire oStart;
wire oData;

//=======================================================
//说明,先膨胀后腐蚀
//(暂时做近距离,膨胀5*29,腐蚀9*34)
//先一行29的缓存,将29个data的或结果,作为输出1
//输出1的进行5行缓存,将5个输出做或,作为输出2
//将输出2进行34行缓存,34个data的与结果,作为输出3
//将输出3进行9行缓存,将9个输出做与,作为最终输出。
//所有寄存器默认为0.
//=======================================================

//=======================================================
//1 29个Data缓存,或运算
//=======================================================
reg [28:0]Dilate_H;
wire Data1;
//=======================================================
//2 5行缓存,5列同位置做或运算
//=======================================================
wire [4:0]Dilate_V;
wire [23:0]Dilate_RowBuffer_taps;
wire Data2;
//=======================================================
//3 34个Data缓存,与运算 
//=======================================================
reg [33:0]Erode_H;
wire Data3;

//=======================================================
//4 9行缓存,9个同位置数据做与运算
//=======================================================
wire [8:0]Erode_V;
wire [47:0]Erode_RowBuffer_taps;
wire Data4;

//=======================================================
//5 Start signal 
//=======================================================
reg Start_d1,Start_d2;
reg [4:0]Delay_Count;


//=======================================================
//1 29个Data缓存,或运算
//=======================================================
always @ (posedge clk_i or negedge rst_n)begin
	if(!rst_n)begin
		Dilate_H <= 29'd0;	
	end
	else begin
		if(iStart)begin
			Dilate_H <= {Dilate_H[27:0],iData};
		end
		else begin
			Dilate_H <= 29'd0;
		end
	end
end

assign Data1 = Dilate_H == 29'd0 ? 1'b0 : 1'b1;

//=======================================================
//2 5行缓存,5列同位置做或运算
//  Data2 为膨胀结果
//=======================================================
LPR_LPL_Morphology_DilateRowBuffer LPR_LPL_Morphology_DilateRowBuffer (
	.clock(clk_i),
	.shiftin(Data1),
	.taps(Dilate_RowBuffer_taps)
);

assign Dilate_V = {Dilate_RowBuffer_taps[19],
					Dilate_RowBuffer_taps[14],
					Dilate_RowBuffer_taps[9],
					Dilate_RowBuffer_taps[4],
					Data1};
assign Data2 = Dilate_V == 5'd0 ? 1'b0 : 1'b1;

//=======================================================
//3 34个Data缓存,与运算 
//=======================================================
always @ (posedge clk_i or negedge rst_n)begin
	if(!rst_n)begin
		Erode_H <= 34'd0;	
	end
	else begin
		if(iStart)begin
			Erode_H <= {Erode_H[32:0],Data2};
		end
		else begin
			Erode_H <= 34'd0;	
		end
	end
end

assign Data3 = Erode_H == 34'h3_ffff_ffff ? 1'b1 : 1'b0;

//=======================================================
//4 9行缓存,9个同位置数据做与运算
//=======================================================
LPR_LPL_Morphology_ErodeRowBuffer LPR_LPL_Morphology_ErodeRowBuffer(
	.clock(clk_i),
	.shiftin(Data3),
	.taps(Erode_RowBuffer_taps)
);

assign Erode_V = {  Erode_RowBuffer_taps[39],
					Erode_RowBuffer_taps[34],
					Erode_RowBuffer_taps[29],
					Erode_RowBuffer_taps[24],
					Erode_RowBuffer_taps[19],
					Erode_RowBuffer_taps[14],
					Erode_RowBuffer_taps[9],
					Erode_RowBuffer_taps[4],
					Data3};
assign Data4 = Erode_V == 9'h1ff ? 1'b1 : 1'b0;
assign oData = Data4;

//=======================================================
//5 Start signal 
//实际准确输出的数据要比输入的少,但是边界影响不大,
//所以简单延时几个,对齐每行数据即可。
//两个29和34延时用的是reg,所以延时两个clk即可(理论上)
//=======================================================
always @ (posedge clk_i or negedge rst_n)begin
	if(!rst_n)begin
		Start_d1 <= 1'd0;	
		Start_d2 <= 1'd0;	
		Delay_Count <= 5'd31;
	end
	else begin
		Start_d1 <= iStart;

		if(Delay_Count == 5'd31)begin
			if(Start_d1 ~^ iStart)
				Start_d2 <= Start_d1;
			else begin
				Delay_Count <= 5'd0;
				Start_d2 <= Start_d2;
			end
		end
		else begin
			Delay_Count <= Delay_Count + 1'b1;
			Start_d2 <= Start_d2;
		end

	end
end

assign oStart = Start_d2;

endmodule

标签:缓存,运算,FPGA,物体,数字电路,腐蚀,wire,设计,膨胀
来源: https://blog.csdn.net/MicroTalent12/article/details/107139667

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有