先简单介绍一下基本的图像处理算法,比如均值滤波,中值滤波是典型的线性滤波算法,它是指在图像上对目标像素给一个模板,该模板包括了其周围的临近像素(以目标像素为中心的周围8哥像素,构成一个滤波模板,即去掉目标像素本身),再利用模板中的全体像素的平均值来代替原来像素值。
![](https://i-blog.csdnimg.cn/blog_migrate/bee714fc9c45f085061ce785da9e363b.png)
中值滤波算法可以形象的用上述表格来描述,即对于每个3*3的阵列而言,中间像素的值,等于边缘8个像素的平均值,算法的理论很简单,对于C语言或者matlab而言,一副640*480图像的均值滤波,可以很方便的通过数组获得3*3的阵列,但对于Verilog而言,确实不是一件容易的事儿,想不明白呀,硬件和软件确实不是一个思路。
知名FPGAer Crazybingo 老湿,在他的VIP_mini_board配套教程里面提到了三种方法,但是最被认可接受且最方便的就是shift_ram,用他的话来说就是shift_ram就是为实现3*3矩阵而生的。
首先介绍一下Shift_ram,宏定义模块如下图所示:
![](https://i-blog.csdnimg.cn/blog_migrate/372a7634e589f8efdc5b908870d954d1.png)
Shift_ram可以定义输入输出数据宽度,每行的宽度,
移位的行数,这里我们需要8bit的数据位宽,每行的宽度640,移位2行即可,(原因稍后分析,其实很简单,画个图很容易理解)。下面的示意图有助于更好的理解Shift_ram。
![](https://i-blog.csdnimg.cn/blog_migrate/c0ced513a1932223f50ab9ef4e422bc7.png)
![](https://i-blog.csdnimg.cn/blog_migrate/d5917db9e22c8fccfc8f4a7fa1da18c7.png)
每个时钟周期输入一个移位数据shift_in_data,同时输出一个数据shift_out_data,而存储器内部是每个clk周期移位一次,每个tap的输出直接移位到下一个tap的输入,每个tap的最后一个w位宽的数据都能出现在对外接口中供用户逻辑使用(通过.taps0x( ),.taps1x( )输出)。
![](https://i-blog.csdnimg.cn/blog_migrate/6a03829b2e48683ee2d2a2df7b39416d.png)
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输出的数据保持同步,如下:
![](https://i-blog.csdnimg.cn/blog_migrate/0d8e6af7d36e2960e7aafe5cd326ece6.png)
2:接着,例化并输入row3_data
![](https://i-blog.csdnimg.cn/blog_migrate/40829e065475d080f7671d5afd79de1c.png)
3:row_data读取信号的分析及生成
这里有一个问题,就是数据进入shift_ram存储耗费了一个时钟,一次3*3阵列的读使能与时钟,需要进行一个clock的偏移,如下所示:
![](https://i-blog.csdnimg.cn/blog_migrate/9a18713dfe4f72430b8e2e80154ec5e0.png)
4:根据行同步信号read_frame_href 与read_frame_clken信号,直接读取3*3像素阵列,读取的verilog代码如下
![](https://i-blog.csdnimg.cn/blog_migrate/d4ff913c562fcdc7e1c03b5042449fcf.png)
![](https://i-blog.csdnimg.cn/blog_migrate/4375d9c9af70f3f1f65eaf14ec9bfaa4.png)
matrix中的p11—p33即为得到的3*3像素阵列。
5.bingo老师把这一步放在了最后,看来基本理解到位了,哈哈哈。
![](https://i-blog.csdnimg.cn/blog_migrate/43b31628f4ebc886393e451c127e96a5.png)
shift_register的时钟使能输入怎么产生的,在bingo的代码中一直没有仔细的去看,现在有必要在这里整理一下了。
代码还是要多看多写才能达到快速理解别人代码的功力,不用说自己的代码能力也会快速提升,说白了时钟使能信号就是在图像传感器已经输出了10帧图像以后,再开始采样,时钟使能保持与行有效信号同步。最终在打一拍之后时钟使能信号有效。