FPGA图像处理系列——实现窗处理

        本博文参考了《FPGA嵌入式图像处理系统设计》一书。该书的英文版下载链接:http://download.csdn.net/detail/lzy272942518/6949349

窗处理是图像处理中常见的一种处理,它的思想是对于图像矩阵,通过一个固定大小(例如3*3)的小矩阵对图像进行运算操作。常用的窗处理包括Sobel边缘检测,形态学操作,模糊滤波,高斯滤波等。在基于PC的图像处理领域,可以方便的实现窗处理操作。比如,在opencv库中可以自己随意构建窗口大小,然后调用相关的函数实现窗处理。

FPGA是一种可定制的逻辑电路,它拥有并行的结构特征,在设计上能实现硬件并行和流水线技术,可以实现算法的加速,而且性价比较高。本文即根据Sobel算法的理论,结合FPGA的结构特征,在FPGA上设计并尝试实现了Sobel窗处理算法方案。

Sobel边缘检测的思想是:该算子包含两组3 x 3的矩阵,分别为横向及纵向,将之与图像作平面卷积,即可分别得出横向及纵向的亮度查分近似值。如果以A代表原始图像,Gx及Gy分别代表经纵向向及横向边缘检测的图像,其公式如下(来源于百度图片):


对于FPGA实现Sobel,首先,是检测窗的实现。这种窗扩展了点运算,以一个局部邻域或窗口内像素值的函数运算结果作为输出:

Q[x,y] = f(I[x,y],...,I[x+△x,y+△y]),  (△x,△y)∈W

其中,W是I[x,y]为中心的窗口。以3×3大小的窗口为例,如图所示:


Sobel算子所需的窗口大小为3×3。在设计过程中,窗口应当满足以下要求:

1.能同时对窗口中所有的元素进行并行操作。

2.窗口采用流水的形式遍历整个图像。

设计的思路是:因为窗口在遍历图像过程中,每一个像素都会被窗口多次使用,因此需要通过缓存来存储像素,使得它们能在后续的窗口位置被重复利用。在FPGA中,可以设计3个单口行缓存(linebuffer),借助状态机和列计数值实现这种窗口,采用流水处理的方法,实现加速计算。如图为窗口结构:


其中状态信号用环形计数器来实现(计数值0-2),其驱动时钟为每一行第一个像素的像素时钟。窗口的行0由3个移位寄存器组成;行1——行2由状态机决定和行缓存的对应关系。窗口的控制逻辑如表1所示:

表1 窗口的控制逻辑

输入行

状态

行缓存0

行缓存1

行缓存2

输出行

0

0

(行2)

(行1)

(空)

1

1

行1

(行2)

(空)

2

2

行2

行1

1

3

0

行2

行1

2

4

1

行1

行2

3

5

2

行2

行1

4

6

0

行2

行1

5

 

……

……

……

……

……

  (注:行x对应窗口结构中的行x)

  对于窗口操作,存在的一个问题是边界部分无法得到处理。不过,本系统的窗口比较小,那么边界像素的输出可以不计算。这样输出的图像比输入图像减小了1行和1列,并不会影响图像显示效果。

具体实现思路:

1.窗口模块:

 3个行缓存,每个大小为640×8 bit;

 状态机,状态信号(0-2),以每一行第一个像素时钟作为驱动状态信号的时钟;

 3个移位寄存器,每个大小为8 bit,作为检测窗口的第一行

窗口的实现,需要建立一个像素时钟驱使的always块,根据窗口结构和表1的控制逻辑,构造窗口;

2.边缘判断模块:

    通过窗口可在像素点P处得到以其为中心,周围8个点的像素值。根据Sobel算子结构,进行计算。设置一个阈值,当计算后的值大于此阈值时,判定此像素为边缘。


关键部分代码(verilog):

always@(posedge PCLK)begin//产生行时钟,作为状态机驱动时钟
begin
	 if(VtcHCnt==0)
	   Line_CLK <= 1;
	 else
	   Line_CLK <= 0;
end
end

reg[1:0] state;
initial state = 0;

always@(posedge Line_CLK)begin//产生状态计数器
 if(VtcVCnt==1)
 state <= 2'b00;
 else begin
   if(state == 2'b10)
	   state <= 2'b00;
	else 
	   state <= state + 1;
	end
end 
//定义窗口第0行的三个元素
reg[7:0]S_Window0;
reg[7:0]S_Window1;
reg[7:0]S_Window2;


//定义行缓存
reg[7:0]LineBuffer0[639:0];
reg[7:0]LineBuffer1[639:0];
reg[7:0]LineBuffer2[639:0];
always@(posedge PCLK)begin
   case(state)
	 2'b00: begin
	    <span style="white-space:pre">	</span>LineBuffer0[VtcHCnt] <= GRAY;
		 LineBuffer1[VtcHCnt] <= LineBuffer1[VtcHCnt];
		 LineBuffer2[VtcHCnt] <= LineBuffer2[VtcHCnt];	
		 S_Window0 <= GRAY;
		 S_Window1 <= S_Window0;
	         S_Window2 <= S_Window1;
		if(VtcHCnt>=2&&VtcVCnt>=3)begin
		 if((S_Window0 + S_Window1*2 + S_Window2)>(LineBuffer1[VtcHCnt-2]+LineBuffer1[VtcHCnt-1]*2 +LineBuffer1[VtcHCnt]))
	          DOUT_reg <= ((S_Window0 + S_Window1*2  + S_Window2 -LineBuffer1[VtcHCnt-2]-LineBuffer1[VtcHCnt-1]*2  -LineBuffer1[VtcHCnt]))/4;
		 else
		 DOUT_reg <= (LineBuffer1[VtcHCnt-2]+LineBuffer1[VtcHCnt-1]*2  +LineBuffer1[VtcHCnt]-(S_Window0 + S_Window1*2  + S_Window2))/4;
		end 
		end 
	 2'b01: begin
	         LineBuffer1[VtcHCnt] <= GRAY;
		 LineBuffer0[VtcHCnt] <= LineBuffer0[VtcHCnt];
		 LineBuffer2[VtcHCnt] <= LineBuffer2[VtcHCnt];		 
		 S_Window0 <= GRAY;
	         S_Window1 <= S_Window0;
	         S_Window2 <= S_Window1;
	   if(VtcHCnt>=2&&VtcVCnt>=3)begin
   	 if((S_Window0 + S_Window1 *2 + S_Window2)>(LineBuffer2[VtcHCnt-2]+LineBuffer2[VtcHCnt-1]*2  +LineBuffer2[VtcHCnt]))
		 DOUT_reg <= ((S_Window0 + S_Window1*2  + S_Window2 -LineBuffer2[VtcHCnt-2]-LineBuffer2[VtcHCnt-1] *2 -LineBuffer2[VtcHCnt]))/4;
		 else
		 DOUT_reg <= (LineBuffer2[VtcHCnt-2]+LineBuffer2[VtcHCnt-1] *2 +LineBuffer2[VtcHCnt]-(S_Window0 + S_Window1*2  + S_Window2))/4;	
		end		   
		end
	 2'b10: begin
	    <span style="white-space:pre">	</span> LineBuffer2[VtcHCnt] <= GRAY;	 
		 LineBuffer0[VtcHCnt] <= LineBuffer0[VtcHCnt];
		 LineBuffer1[VtcHCnt] <= LineBuffer1[VtcHCnt];	
		 S_Window0 <= GRAY;
	    S_Window1 <= S_Window0;
	    S_Window2 <= S_Window1;
		if(VtcHCnt>=2&&VtcVCnt>=3)begin
		 if((S_Window0 + S_Window1*2  + S_Window2)>(LineBuffer0[VtcHCnt-2]+LineBuffer0[VtcHCnt-1] *2 +LineBuffer0[VtcHCnt]))
		 DOUT_reg <= ((S_Window0 + S_Window1*2  + S_Window2 -LineBuffer0[VtcHCnt-2]-LineBuffer0[VtcHCnt-1]*2  -LineBuffer0[VtcHCnt]))/4;
		 else
		 DOUT_reg <= (LineBuffer0[VtcHCnt-2]+LineBuffer0[VtcHCnt-1]*2  +LineBuffer0[VtcHCnt]-(S_Window0 + S_Window1*2  + S_Window2))/4;
	    end
		end
	default:	begin
	       DOUT_reg <= DOUT_reg;
			 LineBuffer0[VtcHCnt] <= LineBuffer0[VtcHCnt];
		    LineBuffer1[VtcHCnt] <= LineBuffer1[VtcHCnt];	
		    LineBuffer2[VtcHCnt] <= LineBuffer2[VtcHCnt];	
			 end
	endcase

end 









  • 9
    点赞
  • 58
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
FPGA图像处理中的高斯滤波是一种常用的图像处理算法,可以用于去除图像中的高频噪声,并平滑图像,使得图像更加清晰和易于分析。这种滤波算法可以通过FPGA技术来实现,以提高图像处理的效率和实时性。 针对传统高斯滤波在保留图像边缘细节方面的不足,研究人员提出了一种基于FPGA的改进高斯滤波算法。这种算法可以在滤除高频噪声的同时,保留图像的边缘信息,并且能够实现高速实时的图像处理。该算法通过对当前图像的像素点与由图像全局求取的梯度阈值进行比对,决定是否对该像素点进行滤波处理。这样可以在保留图像边缘细节的同时,有效地滤除高频噪声。 另外一种方法是采用两个一维的高斯滤波进行两次滤波。首先对图像的行进行一维滤波,然后再对图像的列进行一维滤波。这种方法计算简单,降低了复杂度,同时也可以实现高斯滤波的效果。 综上所述,FPGA图像处理中的高斯滤波是一种有效的图像处理算法,可以提高图像质量和清晰度。同时,通过改进算法和优化计算方式,可以实现高速实时的图像处理。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [FPGA设计——图像处理(高斯滤波)](https://blog.csdn.net/weixin_34220834/article/details/92310397)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [基于FPGA的图像边缘保护高斯滤波算法实现](https://download.csdn.net/download/weixin_38737335/16690867)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [简谈FPGA实现高斯滤波](https://blog.csdn.net/qq_40310273/article/details/113360987)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值