1、知识点
(1)边缘检测
边缘是图像的基本特征,包含了用于图像识别的有用信息,在计算机视觉、图像分析和图像处理等应用中起着重要作用。所谓边缘是指其周围像素灰度急剧变化的那些象素的集合,它是图像最基本的特征。边缘存在于目标、背景和区域之间,所以,它是图像分割所依赖的最重要的依据。由于边缘是位置的标志,对灰度的变化不敏感,因此,边缘也是图像匹配的重要的特征。
边缘检测,针对的是灰度图像,顾名思义,检测图像的边缘,是针对图像像素点的一种计算,目的是标识数字图像中灰度变化明显的点,图像的边缘检测,在保留了图像的重要结构信息的同时,剔除了可以认为不相关的信息,大幅度减少了数据量,便于图像的传输和处理。图像属性中的显著变化通常反映了属性的重要事件和变化。 这些包括(i)深度上的不连续、(ii)表面方向不连续、(iii)物质属性变化和(iv)场景照明变化。
边缘检测和区域划分是图像分割的两种不同的方法,二者具有相互补充的特点。在边缘检测中,是提取图像中不连续部分的特征,根据闭合的边缘确定区域。而在区域划分中,是把图像分割成特征相同的区域,区域之间的边界就是边缘。由于边缘检测方法不需要将图像逐个像素地分割,因此更适合大图像的分割。边缘大致可以分为两种,一种是阶跃状边缘,边缘两边像素的灰度值明显不同;另一种为屋顶状边缘,边缘处于灰度值由小到大再到小的变化转折点处。边缘检测的主要工具是边缘检测模板。
边缘检查的方法大致可以分为两类:基于查找的一类,通过寻找图像一阶导数中最大值和最小值来检测边界,包括 Sobel 算法、 Roberts Cross 算法、Prewitt 算法,Kirsch 算法,罗盘算法等;基于零穿越的一类,通过寻找图像二阶导数零穿越来寻找边界,包括 Canny 算法, Laplacian 算法、Marr-Hildreth算法等。
(2) Sobel 算法
Sobel 边缘检测算法比较简单,虽然准确度较低,但在实际应用中效率较高,在很多实际应用场合,Sobel 算法却是首选,尤其是对效率要求较高,对纹理不太关心的时候。在技术上,它是一离散性差分算子,用来运算图像亮度函数的灰度之近似值。在图像的任何一点使用此算子,将会产生对应的灰度矢量或是其法矢量。
所谓的Sobel算法,就是将得到像素点乘以一个3*3矩阵(Sobel算子)得到一个该点的灰度矢量值或者其法矢量值。Sobel算子根据像素点上下、左右邻点灰度加权差,在边缘处达到极值这一现象检测边缘。所以整个算法的核心就是Sobel算子,下面简单介绍下该算子。
索贝尔算子(Sobel operator)主要用作边缘检测, 在技术上,它是一离散性差分算子,用来运算图像亮度函数的灰度之近似值。
Sobel 卷积因子为:
对于图像而言,取 3 行 3 列的图像数据,将图像数据与对应位置的算子的值相乘再相加,得到 x 方向的 Gx ,和 y 方向的 Gy , Gx 及 Gy 分别代表经横向及纵向边缘检测的图像灰度值。将得到的 Gx 和 Gy ,平方后相加,再取算术平方根,得到 Gxy ,近似值为 Gx 和 Gy 绝对值之和, Gxy 代表该点灰度的大小。将计算得到的 Gxy 与我们设定的阈值相比较,Gxy 如果大于阈值,表示该点为边界点,此点显示黑点,否则显示白点。
2、实战演练
要实现Sobel算法首先要利用FIFO 3行数据求和,其次掌握上述的边缘检测和算法的具体理论,结合这两个部分来实现算法就比较简单了。我们把整个过程分为下面四个步骤:
1)通过Gx、Gy的计算公式结合FIFO求和算法求取Gx、Gy的值。
2)求得Gx、Gy的绝对值。
3)将Gx、Gy带入Gxy计算公式,求得Gxy的值。
4)将求得的Gxy与设定的阈值相比较,当Gxy大于等于阈值,赋值rgb为黑色,否则赋值rgb为白色。
需要注意的是,图片经过Sobel算法之后,输出的图片相比输入的图片会少2行2列数据,这是因为使用FIFO求和算法时这一算法只有当第2行或第2列数据输入时才开始执行。所以会丢失。 将图像用软件转成灰度图像,然后将灰度图像的高三位取出进行保存,通过串口将图像数据传给FPGA,随后FPGA通过Sobel算法检测图像轮廓,然后将处理后的图片通过VGA显示640*480@60,图像大小为100*100。
图片预处理:
在Sobel算法之前我们首先要把彩色图片转化为灰度图,之后将灰度图的高三位取出来存放到txt中,这一个预处理选择用matlab来实现,相关.m文件代码如下
clc; %清理命令行窗口
clear all; %清理工作区
image = imread('tupian.png'); %使用imread函数读取图片数据
figure;
imshow(image); %窗口显示图片
R = image(:,:,2); %提取图片中的红色层生成灰度图像
figure;
imshow(R); %窗口显示灰色图像
[ROW,COL] = size(R); %灰色图像大小参数
data = zeros(1,ROW*COL); %定义一个初值为0的数组,存储转换后的图片数据
for r = 1:ROW
for c = 1 : COL
data((r-1)*COL+c) = bitshift(R(r,c),-5); %红色层数据右移5位
end
end
fid = fopen('tupian.txt','w+'); %打开或新建一个txt文件
for i = 1:ROW*COL;
fprintf(fid,'%02x ',data(i)); %写入图片数据
end
fclose(fid);
原始图片:灰度图像:
整体框图:
Sobel算法进行边缘检测的整个实验工程如下图所示,其中clk_gen为PLL IP核产生25MHz和50MHz的时钟,rx和tx为uart串口通信部分,VGA为显示部分,sobel_ctrl为整个工程的核心部分包含了Sobel算法的具体实现。
具体工作流程:
1)开发板系统时钟为25Mhz,系统上电后,时钟信号传入PLL分频产生25Mhz和50Mhz的时钟,其中50Mhz的时钟用于串口收发、Sobel求和、RAM写的工作时钟;25MHz时钟用于图像生成模块和VGA时序控制模块的工作时钟。
2)PC 机将图片数据通过串口 RS232 传输给 FPGA,数据在 uart_rx 模块中完成拼接传给 sobel_ctrl 模块进行 Sobel 运算,输出结果同时传给 vga 模块和 uart_tx 模块;vga 模块将接收到的经 sobel 算法处理后的图像数据存入图像数据生成模块中的RAM 中;uart_tx 模块将输出结果回传给 PC 机验证数据完整性。
3)图像数据生成模块以 VGA 时序控制模块传入的像素点坐标(pix_x,pix_y)为约束条件,生成待显示图像的色彩信息(pix_data),图像色彩信息包括彩条背景和经 sobel算法处理后的图片信息。
4)图像数据生成模块生成的图像色彩信息传入VGA时序控制模块,在模块内部使用使能信号滤除掉非图像显示有效区域的图像数据,产生RGB色彩信息(rgb),在行、场同步信号(hsync、vsync)的同步作用下,将RGB色彩信息扫描显示到VGA显示器,显示出经Sobel算法处理过的图像。
sobel_ctrl控制模块:
这个模块的设计主要包含两个部分:
- 图片数据自输入模块到数据写入fifo
- 数据从FIFO读出经过Sobel运算进行输出
第一个部分(参考FIFO三行求和的工程)
本功能模块的作用是对输入的图片进行 sobel 算法处理并输出处理后的数据,由前文可知,要实现 sobel 算法的求解,要使用 sobel 算子求出 Gx、Gy,进而求出 Gxy,求解后的 Gxy 与设定阈值比较,确定图像边界,完成 sobel 算法处理。
Gx、Gy 的求解分别是对图形 3 行、3 列图形数据的处理,我们可以参考FIFO 求和实验对 3 行数据的处理方式,实现 Gx、Gy 数据的求解。
与 FIFO 求和实验类似,sobel_ctrl 模块内部同样调用两个 FIFO 用作数据缓存。使用同样的方式将串口接收模块传入的图片数据按要求暂存到两个 FIFO 中。
两 FIFO 的时钟信号为系统时钟 sys_clk 与串口接收模块时钟相同;我们需要在模块内部声明 FIFO 写使能信号,声明 fifo1 写使能信号为 wr_en1,数据输入信号为 data_in1,声明 fifo2 写使能信号为 wr_en2,数据输入信号为 data_in2;声明两 FIFO 共用读使能信号rd_en。
1)wr_en1:当第 0 行数据输入,wr_en1 写使能信号由数据标志信号 pi_flag 赋值,滞后
pi_flag 信号 1 个时钟周期,第 1 行数据输入时,wr_en1 写使能信号保持无效,自第 2 行数据输入到数据输入结束,wr_en1 写使能信号由数据标志信号 dout_flag 赋值,滞后dout_flag 信号 1 个时钟周期;
2)data_in1:当第 0 行数据输入且写使能有效时, 将第 0 行数据写入 fifo1:当第 2-98 行数据写入且写使能有效时,将 fifo2 读出的 1-97 行数据写入 fifo1;
3)wr_en2:当第 1-98 行数据输入时,wr_en2 写使能信号由数据标志信号 pi_flag 赋值,滞后 pi_flag 信号 1 个时钟周期,其他时刻写使能信号 wr_en2 均无效;
4)data_in2:当 fifo2 的写使能信号 wr_en2 有效时,将传入的 pi_data 赋值给 data_in2,数据写入 fifo2,写使能无效时,data_in2 保持原有状态;
5)rd_en:fifo1 和 fifo2 共用读使能信号,该使能信号在第 0 行和第 1 行数据输入是始终保持无效状态,自第 2 行数据开始输入到数据输入完成,读使能信号 rd_en 由 pi_flag 赋值,滞后 pi_flag 信号 1 个时钟周期;
6)dout_flag 信号只有在 wr_en2 信号和 rd_en 信号均有效时才有效,其他时刻均无效,目的是赋值给在第 2 行数据输入后的 wr_en1 使能信号。
时序图如下:
第二个部分
实现 sobel 算法就要求出 Gxy,Gxy 由 Gx、Gy 运算得到,Gx、Gy 由 sobel算子与图像数据运算得到。参与运算的图像数据要包含图像 3 行 3 列的像素信息。这就表示只有在图像的第 2 行的第 2 个数据传入模块时,才能开始 Gx、Gy 的运算。要准确定位运算开始的时刻,我们需要声明计数器,用来计数读出数据个数,判断 Gx、Gy 的运算时刻,之后根据公式来进行运算。