针对这学期学习fpga开发,主要做了图像采集、预处理和显示部分,本次实验采用spartan6板子,通过ov5640将采集到的图像数据发送给片上SDRAM,生成行列地址存入ram中并读取给lcd显示,图像预处理部分主要针对边缘检测sobel算子、灰度变换和膨胀腐蚀算法,不过板子的不同除了接口处略有不同外,功能实现大致略同,可在任何一个板子上进行测试,在实验过程中出现了一些问题比如:
1、根据算法原理中3*3矩阵卷积部分进行实现的过程中调用了vivado的shift_ram的IP核,设置为数据位宽大小,一行图像的深度,调用两个IP核和一个正在读取的一行数据,并行组成3行数据依次传递到矩阵中,具体操作代码如下
下面展示一些 。
//矩阵模块
reg [7:0] matrix_p11,matrix_p12,matrix_p13;
reg [7:0] matrix_p21,matrix_p22,matrix_p23;
reg [7:0] matrix_p31,matrix_p32,matrix_p33;
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
{matrix_p11,matrix_p12,matrix_p13} <= 24'h0;
{matrix_p21,matrix_p22,matrix_p23} <= 24'h0;
{matrix_p31,matrix_p32,matrix_p33} <= 24'h0;
end
//矩阵开始
else if(i_hsync_valid_delay_1)
begin
{matrix_p11,matrix_p12,matrix_p13} <= {matrix_p12,matrix_p13,row1_data};
{matrix_p21,matrix_p22,matrix_p23} <= {matrix_p22,matrix_p23,row2_data};
{matrix_p31,matrix_p32,matrix_p33} <= {matrix_p32,matrix_p33,data_in};
end
else
begin
{matrix_p11,matrix_p12,matrix_p13} <= 24'h0;
{matrix_p21,matrix_p22,matrix_p23} <= 24'h0;
{matrix_p31,matrix_p32,matrix_p33} <= 24'h0;//(依次送入)
end
end
2、当时对一个问题非常头疼,就是对于sobel边缘检测模板在遍历矩阵的过程中何处为开始的第一个点,对于每一行最后和新一行开始应该如何衔接卷积过程,才能使得在卷积过程中保证图像边界点处理的准确性,经过演算,发现当最后一行有数据进入,也就是说当lcd显示所需要的行同步扫描信号拉高准备从ram中提取data_in数据,且有第一个数据进入shift_ram时,data_in的第一个数据即可当作需要处理的一个矩阵的所有值,不需要延迟一行加一个数据的时钟,这样做的好处就是可以保证时钟延迟少,且保持数据流的形式对图像像素进行处理,可以以lcd读取的行同步信号为sobel开始的起始信号,(此处需要注意如果采集到的图像为rgb或者其他格式。需要将其通过rgb转灰度等算法对其进行处理,而且注意变换所需要的时钟数,进行延迟后作为sobel建立3*3矩阵的其实信号和sobel开始处理的起始信号),最后将因为处理所消耗的行场同步时钟数延迟,接到lcd显示模块即可实现图像采集实时显示边缘检测图像。处理后的结果如图所示: