基于FPGA的局部自适应分割

目录

  • 局部自适应阈值分割原理
    • 算法转换
    • FPGA结构设计
    • 子模块设计
      • 窗口缓存模块win_buf
      • 数据累加模块add_tree
      • 均值滤波模块设计
    • 福利

局部自适应阈值分割原理

全局阈值分割算法简单,对于双峰直方图图像有很好的分割效果。但对于图像噪声和光照不均匀性十分敏感。图6-1是图像的OTSU分割效果。可见,由于边缘光照不均匀性,造成边缘分割失败。图像边缘光线较暗的地方被分割为0,中间较亮的地方分割成功。
基于FPGA的局部自适应分割_第1张图片
如何规避光线不均匀带来的影响?一种典型的处理方法就是采用局部自适应阈值分割。根据像素邻域块的像素值分布来确定该像素位置上的二值化阈值。这样做的好处在于每个像素位置处的二值化阈值不是固定不变的,而是由其周围邻域像素的分布来决定的。亮度较高的图像区域二值化阈值通常较高,而亮度较低的图像区域二值化阈值则会相应地变小。不同亮度、对比度、纹理的局部图像区域将会拥有相对应的局部二值化阈值。

常用的局部自适应阈值是局部邻域块的均值和局部邻域块的高斯加权和。将处理窗口设为矩形移动窗,设r为处理窗口的半径,μ为窗口内像素均值,σ2为窗口内像素方差,I(x,y)为输入像素值,g(x,y)为分割后的像素值,K为一个大于0的常数。有如下定义:
基于FPGA的局部自适应分割_第2张图片
基于FPGA的局部自适应分割_第3张图片
基于FPGA的局部自适应分割_第4张图片
基于FPGA的局部自适应分割_第5张图片

算法转换

基于FPGA的局部自适应分割_第6张图片

FPGA结构设计

为了充分利用FPGA的并行特性,采用流水线结构来实现上诉设计。需要完成以下计算工作:

(1) 计算当前窗口内的像素均值μ。
(2) 计算当前窗口中心像素与均值之差的平方(din-μ)2。
(3) 将上式与225相乘,完成不等式左边的计算。
(4) 计算当前窗口内225个所有像素值与均值之差的平方和,完成不等式右边的计算。
(5) 将第(3)和(4)的结果进行比较,完成图像分割。
(6) 完成行列对齐与边界处理。
基于FPGA的局部自适应分割_第7张图片
average_filter模块是均值滤波模块,其内部使用了win_buf和add_tree。共消耗11拍,为了均值与窗口缓存电路win_buf时序对齐,din输入到win_buf需要延时11拍。

得到了窗口均值μ和当前窗口的像素队列225个像素数据din_buf,需要做的是把窗口内225个din_buf分别于均值相减后计算平方。从图6-4可以看出,减法消耗一拍,平方也消耗一拍,计算完后再将他们拼接在一起,组成新的向量,方便输入到add_tree模块进行加法计算(模块端口不能是数组,只能将他们拼接成一个向量,然后再输入到模块端口中,其他和数组的效果是一样的!)。加法电路消耗了8拍。

中心像素与均值之差的平方值可以直接从新向量中取出,无需重新计算,然后进行乘255,乘法电路需要消耗两拍,为了与add_tree输出的数据对齐,乘法电路输出的数据还需要延时8-2=6拍。至此左边不等式和右边不等式都已经计算完毕。将不等式进行比较,利用比较结果对原图进行分割即可。最后的根据有效数据标志清零是为了将边界清零。至少对上边界清零。左右两边没有考虑(左右边界清零比较麻烦,以后可能会更新左右边界清零!)。

子模块设计

窗口缓存模块win_buf

本模块不做任何算法上的处理,只是负责将当前输入像素的二维窗口元素缓存并组成一个一维的向量输出。

模块的构建非常简单,对图像分别做行列方向的延迟即可。对于行方向上的延时,可以采用行FIFO来实现,对于列方向上的延迟,则采用寄存器来实现。

设需要缓存的窗口尺寸为KSZ,则需要KSZ-1行FIFO,以及KSZ*KSZ个寄存器来实现。

我们将以7*7的窗口缓存模块为例来说明,其设计框图如下:
基于FPGA的局部自适应分割_第8张图片
我们不难把这个电路扩展到尺寸15x15的窗口中,在图中也重点标注出了窗口中心像素点。这个中心像素点就代表当前处理的像素中心。此电路也可以用来实现图像的卷积运算,例如排序、sobel算子、高斯滤波或者均值滤波等。

数据累加模块add_tree

数据累加模块负责将窗口内所有元素与均值之差的平方相加。每个加法器限制两个输入,这样,对于225个数据,在第一个时钟,共有112对数据进行相加。同时把剩余的一个数据进行缓存,第二个时钟有56个数据进行相加,同时将之前的数据缓存,依次类推,如下图所示:
基于FPGA的局部自适应分割_第9张图片
问题的关键在于如何描述这个电路,当然可以使用最笨的方法:将上诉电路中所有的寄存器及加法器和中间信号均描述出来。这样带来的工作量是非常大的,还容易出错,代码可维护性和可读性极差。

如果在仔细发泄上诉框图,就很容易发现规律:除了最后一个时钟直接完成两个数的相加,在其他的每个时钟内,加法运算电路都是相似的,不同的只是待加的数目不同。

为了总结出这个规律,我们列出几个时钟如下:

第一个时钟:需完成225个数据相加,共需112个加法器,113个寄存器。
第二个时钟:需完成113个数据相加,共需56个加法器,57个寄存器。
第三个时钟:需完成57个数据相加,共需28个加法器,29个寄存器。
……
最后一个时钟:需完成2个数据相加,共需1个加法器,1个寄存器。
为此,我们总结出以下规律:

设定本次待相加的数目为n,则下次需要相加的数目为n/2+n%2。

本次需要的加法器数目为n/2,寄存器数目为n/2+n%2。

每次的计算开销是1个时钟。

很明显,可以通过利用数学上的递归运算来解决这个问题。实际上,在数学上也把这种方法称为二分递归调用。
数学公式推导如下:

递归求和电路框图如下所示:
基于FPGA的局部自适应分割_第10张图片
图6-7中的input_vector为当前窗口的并行像素向量(由win_buf模块得到),new_vector为第一次递归运算之后获得的新向量,作为下一次递归的input_vector。

均值滤波模块设计

前面章节已经设计好win_buf模块和add_tree模块,在此基础上很容易设计出均值模块。其设计框图如下:
在这里插入图片描述
从图6-4顶层模块中可以看出,顶层也使用了win_buf模块用来缓存窗口,所以本教程以win_buf模块为起始点,可以看出均值模块共消耗了11拍,所以在顶层模块需要先将输入数据延时11拍后再输入给win_buf,目的就是为了时序对齐。

福利

微信扫描下面的二维码关注[春哥笔记]公众号,回复“局部自适应分割”即可Get教程的获取方式。

你可能感兴趣的:(FPGA,图像处理,局部自适应分割,OTSU)