中值滤波算法可以形象的用上述表格来描述,即对于每个3*3的阵列而言,中间像素的值,等于边缘8个像素的平均值,算法的理论很简单,对于C语言或者matlab而言,一副640*480图像的均值滤波,可以很方便的通过数组获得3*3的阵列,但对于Verilog而言,确实不是一件容易的事儿,想不明白呀,硬件和软件确实不是一个思路。
知名FPGAer Crazybingo 老湿,在他的VIP_mini_board配套教程里面提到了三种方法,但是最被认可接受且最方便的就是shift_ram,用他的话来说就是shift_ram就是为实现3*3矩阵而生的。
首先介绍一下Shift_ram,宏定义模块如下图所示:
Shift_ram可以定义输入输出数据宽度,每行的宽度, 移位的行数,这里我们需要8bit的数据位宽,每行的宽度640,移位2行即可,(原因稍后分析,其实很简单,画个图很容易理解)。下面的示意图有助于更好的理解Shift_ram。
每个时钟周期输入一个移位数据shift_in_data,同时输出一个数据shift_out_data,而存储器内部是每个clk周期移位一次,每个tap的输出直接移位到下一个tap的输入,每个tap的最后一个w位宽的数据都能出现在对外接口中供用户逻辑使用(通过.taps0x( ),.taps1x( )输出)。
Shift_ram中存2行数据,同时与当前输入行的数据组成3行的阵列,实现8bit宽度的3*3像素阵列功能,具体的实现步骤如下:
在我看来首先应当明确3*3矩阵生成器的输入:
对于来自sensor的图像数据,图像重构需要以下数据:
1 per_frame_vsync //帧同步信号
2 per_frame_href //行有效信号
3 per_frame_clken // 这是移位寄存器存储数据的使能 时钟信号(数据在clk的监督下进来了,但是能不能存下来还要看
per_frame_clken )
4 clk //像素时钟
5 rst_n //全局复位信号
6 img_Y //图像数据
步骤:
1: 首先,将输入的信号用像素使能时钟(per_frame_clken)同步一拍,以保证数据与Shift_ram输出的数据保持同步,如下:
2:接着,例化并输入row3_data
3:row_data读取信号的分析及生成
这里有一个问题,就是数据进入shift_ram存储耗费了一个时钟,一次3*3阵列的读使能与时钟,需要进行一个clock的偏移,如下所示:
4:根据行同步信号read_frame_href 与read_frame_clken信号,直接读取3*3像素阵列,读取的verilog代码如下
matrix中的p11—p33即为得到的3*3像素阵列。
5.bingo老师把这一步放在了最后,看来基本理解到位了,哈哈哈。
shift_register的时钟使能输入怎么产生的,在bingo的代码中一直没有仔细的去看,现在有必要在这里整理一下了。
代码还是要多看多写才能达到快速理解别人代码的功力,不用说自己的代码能力也会快速提升,说白了时钟使能信号就是在图像传感器已经输出了10帧图像以后,再开始采样,时钟使能保持与行有效信号同步。最终在打一拍之后时钟使能信号有效。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)