实验四 图像轮廓线提取技术
一、 实验目的与要求:
1、 能熟练应用matlab 去分析问题、解决问题;
2、 熟悉对matlab 的图像处理的功能,掌握基本的图像处理的若干命令;
3、 在应用matlab 进行图像处理方面具备一定的编程能力。
4、 掌握figure ,imread ,image ,colormap ,imshow ,imwrite ,subplot ,title ,rgb2gray ,imfinfo 等语句的基本使用方法。
5、 掌握图像轮廓线提取的简单方法并上机实现。
6、 掌握matlab 自带的一些常用边界检测算子的使用,提高对复杂图像处理的能力。
二、 问题描述
“图像轮廓线提取”是数字图像处理中对图像进行处理和分析之前的一项非
常重要的工作。指的是从原始图像中,以手动或自动的方法,将图片中的人物、动物、植物或者其他任何对象的(特征)轮廓线提取出来,使之成为一幅独立的黑白线条图。从而达到将物体与背景分开,物体与物体分开的效果。提取轮廓线被应用于许多方面,例如人脸检测和跟踪。它结合了认知科学、图象处理、计算机图形学、机器视觉和模式识别等多个研究领域。
三、 问题分析
既然“图像轮廓线提取”的黑白线条图所在位置往往是图像中两区域交界位
置,则可以通过图像特征(如形状、颜色、纹理等)变化情况来检测两区域交界处。最简单的方法就是采用阈值检测法,即将当前检测点的特征与周围点的特征进行比较,若发现有较大的差异,则认为当前检测点属于两区域的交界点,否则,认为同一区域内的点。
四、 背景知识介绍
首先介绍几种基本的图像格式,再介绍一下matlab 中常见的图像处理命令
及其用法。
常见图像格式
1. 二值图
单色图像则是带有颜色的图像中比较简单的格式,它一般由黑色区域和白色
区域组成,可以用一个比特表示一个像素,“1”表示黑色,“0”表示白色,当然也可以倒过来表示,这种图像称之为二值图像。
2. 灰度图
我们也可以用8个比特(一个字节)表示一个像素,相当于把黑和白等分为
256个级别,“0”表示为黑,“255”表示为白,该字节的数值表示相应像素值的
灰度值或亮度值,数值越接近“0”,对应像素点越黑,相反,则对应像素点越白,
此种图像我们一般称之为灰度图像。单色图像和灰度图像又统称为黑白图像。
3. 彩色图
与黑白图像对应,就存在着彩色图像,这种图像要复杂一些,表示图像时,
常用的图像彩色模式有RGB 模式、CMYK 模式和HIS 模式,一般情况下我们只
使用RGB 模式,R 对应红色,G 对应绿色,B 对应蓝色,它们统称为三基色,
这三中色彩的不同搭配,就可以搭配成各种现实中的色彩,此时彩色图像的每一
个像素都需要3个样本组成的一组数据表示,其中每个样本用于表示该像素的一
个基本颜色。基于三刺激理论(Tristimulus Theory ),我们的眼睛通过三种可见
光对视网膜的锥状细胞的刺激来感受颜色。这些光的波长为630nm (红色)、
530nm (绿色)和450nm (蓝色)时的刺激达到高峰。通过光源中的强度比较,
我们感受到光的颜色。这种视觉理论是使用三种颜色基色:红、绿和蓝在视频监
视器上显示彩色的基础,称为RGB 颜色模型。以一个常见的例子来说明:Windows
环境下主要的图像格式之一,BMP 灰度图像,以其格式简单,适应性强而倍受
欢迎。这种文件格式就是每一个像素用8bit 表示,显示出来的图像是黑白效果,
最黑的像素的灰度(也叫作亮度)值为“0”,最白的像素的灰度值为“255”,整
个图像各个像素的灰度值随机的分布在“0”到“255”的区间中,越黑的像素,
其灰度值越接近于“0”,越白(既越亮)的像素,其灰度值越接近于“255”;与
此对应的是在该文件类型中的颜色表项的各个RGB 分量值是相等的,并且颜色
表项的数目是256个。每一个像素颜色由其红、绿、蓝三色的强度值联合决定。
4.
常用图像处理命令
1. 图像文件的读取
i=imread(文件名, ’图像文件格式’) 。将文件名指定的图像文件读入数组I ,I
的数据类型为无符号8位整数(uint8)。对于灰度图像,I 是一个二维数组;对
于真彩色图像,I 是一个三维数组(n ×m ×3)。文件名是指定图像文件名称的字
符串,’图像文件格式’是指定图像文件格式的字符串。
如:i=imread('C:\Documents and Settings\ My Documents\My Pictures\a','jpg');
或直接在第一个参数上加扩展名:
i=imread('C:\Documents and Settings\ My Documents\My Pictures\a.jpg');
注意:后面最好加上“;”号,因为图像若大则需时间较长。
2. 图像的显示
image(i):将矩阵I 作为图像显示,I 中的每一个元素在图像中表示为一个颜
色块,I 可以是n ×m 阶矩阵或者n ×m ×3的数组,其元素为double 或uint8数
据类型。
imshow:是在图像显示中最常用,也是功能最强的图像显示函数,常用的格
式为:imshow(i,n),使用n 个灰度等级显示图像I 。如果默认n ,则使用256级或
64级灰度显示图像。
3. 显示灰度直方图
imhist(i), 显示灰度图像I 的灰度直方图。其中I 是一个二维矩阵,imhist 用
柱状图形式显示图像中每个灰度出现的频率,即矩阵中每一个元素对应的数值在
整个矩阵中出现的频率。
如:先获取r 颜色的二维矩阵:j=i(:,:,1);
再运行:imhist(j);
4. 获取像素点信息
pixval, 在使用image 或imshow 显示图像后,在执行pixval 指令,便可以读
取光标所指向的像素点的坐标和灰度值;如果按住鼠标,在图像中拖曳,便可以
显示光标所移动的距离。
再次运行pixval 则是关闭获取像素点信息。
5. 求矩阵的规模
D=size(i),函数size 用来求矩阵的规模。如果I 是n ×m 的矩阵,则D 是包含
两个元素的向量:D=[n, m ];同样道理,如果I 是n ×m ×3的矩阵,则D=[n,m,3]。
如果我们事先知道矩阵的维数,也可以直接用这样的方法求得矩阵的规
模:[n,m]=size(i)或[n, m, k]=size(i)等。
6. 数据类型转换
i=uint8(X),这个函数实现将矩阵X 中的所有元素转换为无符号8位整形数
据,把转换的结果保存在矩阵I 中。这个函数对所有类型的数据都适用,转换后
数值都落在0到255之间。
i=double(X),这个函数与uint8()相似,实现的功能是将矩阵X 中的所有元
素转换为double 类型(16位双精度类型)。
五、 实验过程
根据分析,图像中位于轮廓线上的点,它与其相邻的点的灰度值差有一定的
跳跃,故通过值的对比,就可以将那些边缘点提取出来。
考虑到图像边框上的像素点对于轮廓线获取的结果影响不大,且为了代码的
简单实用,首先去掉图像的边框上的所有像素点,即:去掉灰度值矩阵的第一行、
第一列、最后一行和最后一列。这样做的好处是显而易见的,因为可以保证每一
个待比较的点其周围都有8个供比较的点,如图示:
在算法中,将中心被检测点依次与其上下、左右、左上、右下,和右上、左
下8个点做比较,若差值大于规定值,则该检测点就是轮廓线上的点,反之不是。
算法关键的地方是对IMREAD 生成的矩阵进行了非线性变换。
算法流程如下:
首先,将这个矩阵从8位无符号型变成双精度的数值存储;
然后才能进行下一步的将其每个值都除以255,这样就把每个数值都调整为
0~1之间的小数;
再用正弦sin 函数将这些值做变换,并取求得的结果放大40倍。这样一来,
本来是在0~255之间的正整数,就被变换到0~1之间的小数,然后再离散成0~
40之间的双精度数值。其目的是为了在进行比较灰度值的时候,方便自定义各
种差值。
最后,用户给定一个差值,根据这个值来比较检测点与其周围8个点的灰度
值,若大于给定差值,则认为检测点位于轮廓线上,否则,不在轮廓线上。
灰度图的源代码(.m 文件)如下:
function graydrawout(pix,n) %灰度图的轮廓线提取
A=imread(pix); %读取指定的灰度图
[a,b]=size(A); %a,b分别等于矩阵A 的行数和列数
B=double(A); %将矩阵A 变为双精度矩阵
D=40*sin(1/255*B); %将矩阵B 进行线性变换
T=A; %新建与A 同等大小矩阵
for p=2:a-1 %处理图片边框内的像素点
for q=2:b-1
if (D(p,q)-D(p,q+1))>n|(D(p,q)-D(p,q-1))>n|
(D(p,q)-D(p+1,q))>n|(D(p,q)-D(p-1,q))>n|
(D(p,q)-D(p-1,q+1))>n|(D(p,q)-D(p+1,q-1))>n|
(D(p,q)-D(p-1,q-1))>n|(D(p,q)-D(p+1,q+1))>n
T(p,q)=0; %置边界点为黑色
else
T(p,q)=255; %置非边界点为白色
end;
end;
end;
subplot(2,1,1); %将窗口分割为两行一列,下图显示于第一行
image(A); %显示原图像
title('灰度图原图'); %图释
axis image; %保持图片显示比例
subplot(2,1,2); %下图显示于第二行
image(T); %显示提取轮廓线后的图片
title('提取轮廓线'); %图释
axis image; %保持图片显示比例
注释:pix -为要提取轮廓线的灰度图名(带路径),由单引号括住。
n -自定义的灰度值差值,超过该值就是轮廓线上的点,反之不然。
这是一个最重要的参数,通过调节它的值,修整轮廓线的效果,取范
围在0~40之间的任何有理数。
A -MATLAB 读取原图片后返回的数据矩阵,2维(M N )
T -新建的与A 矩阵同等行列数的矩阵,待放入比较后结果,代码的主体
是if -else -end 部分,其原理就是将中心点与其周围的8个点依次比较,发现
有一个差值大于自定义的值时,就判断其为轮廓线上的点并将之置为黑色;若其
与周围8个点的比较值都小于自定义值时,则其不在轮廓线上,置白色。灰度图
提取轮廓线示例(n=20):
3. 彩色图提取图像轮廓线
彩色图片经过IMREAD 函数读取后,由于它的每一个像素点都是由红、绿、
蓝三色的强度值一起定义其颜色的,所以,生成的是一个3维的(M N 3)
矩阵。矩阵平面(:,:,1)代表对应像素点的红色强度值,矩阵平面(:,:,2)
是绿色强度值,矩阵平面(:,:,3)则是蓝色强度值。在每一个矩阵平面中强度
值的范围是[0,255]的正整数。位于轮廓线上的点,它的红、绿、蓝三色的强度值
与其周围的点必然有一定的差值,也正式利用这些差值的比较,可以将那些位于
边缘的点提取出来。
在算法上,彩色图与灰度图不同的是,彩图的每一个单色矩阵可以单独用
来判定该点是否位于轮廓线上。其算法与灰度图的原理非常相似。
在彩色图的算法中,加入了对判定矩阵的选择,即提供使用者自由选择用
图片的哪一个单色矩阵进行轮廓线提取。因为根据图片本身的特点,选择更适合
于进行提取的矩阵,其效果是十分不同的,在下面的讨论中将会再次提到这个问
题。
算法关键的地方同样是对IMREAD 生成的矩阵进行了线性变换。首先,将
这个矩阵从8位无符号型变成双精度的数值存储;然后才能进行下一步的将其每
个值都除以255,这样就把每个数值都调整为0~1之间的小数;再用正弦sin 函
数将这些值做变换,并取求得的结果放大40倍。这样一来,本来是在0~255
之间的正整数,就被变换到0~1之间的小数,然后再离散成0~40之间的双精
度数值。其目的是为了在进行比较单色强度值的时候,方便自定义各种带小数的
差值。彩色图轮廓线提取的源代码(.m 文件)如下:
function colordrawout(pix,n) %彩色图片轮廓线提取函数
A=imread(pix); %读取指定彩色图片
B=A(:,:,1); %红色强度值矩阵
C=A(:,:,2); %绿色强度值矩阵
D=A(:,:,3); %蓝色强度值矩阵
for i=1:3 %依次从三个矩阵中提取轮廓线
if i==1 %从红色矩阵提取
E=B;
else if i==2 %从绿色矩阵提取
E=C;
else E=D; %从蓝色矩阵提取
end;
end;
H=double(E); %将选择的矩阵变为双精度矩阵
F=40*sin(1/255*H); %进行非线性变换
[k,j]=size(B); % k,j分别为矩阵D 的行数和列数
T=A;
for p=2:k-1
for q=2:j-1
if (F(p,q)-F(p,q+1))>n|(F(p,q)-F(p,q-1))>n|
(F(p,q)-F(p+1,q))>n|(F(p,q)-F(p-1,q))>n|
(F(p,q)-F(p-1,q+1))>n|(F(p,q)-F(p+1,q-1))>n|
(F(p,q)-F(p-1,q-1))>n|(F(p,q)-F(p+1,q+1))>n
T(p,q,1)=0;T(p,q,2)=0;T(p,q,3)=0; %置边界点黑色
else
T(p,q,1)=255;T(p,q,2)=255;T(p,q,3)=255;%置非边界点白色
end;
end;
end;
subplot(2,2,i+1); %将窗口分割为两行两列,下图显示于第i +1位置
image(T); %显示轮廓线
title(i); %图释
axis image; %保持图片显示比例
end;
subplot(2,2,1); %下图显示于第1位置
image(A); %显示原彩色图片
title('彩色图原图'); %图释
axis image; %保持图片显示比例
注释:pix -为要提取轮廓线的灰度图名(带路径),由单引号括住。
n -自定义的强度值值差值,超过该值就是轮廓线上的点,反之不然。
这是一个最重要的参数,通过调节它的值,修整轮廓线的效果
范围为0~40之间的任何有理数。
A -MATLAB 读取原图片后返回的数据矩阵,3维(M N 3)
T -新建的与A 矩阵同等行列数的矩阵,待放入比较后结果。
代码中加入的部分是对单色强度值矩阵的选择。从比较中可以看出,选择
彩色图片中最大程度的颜色矩阵,可以提高提取轮廓线的效果。譬如:图片以红
色为主,就选择1-红色矩阵。
代码的主体同样是if -else -end 部分。其原理仍是将中心点与其周围的8
个点依次比较,发现有一个差值大于自定义的值时,就判断其为轮廓线上的点并
将T 矩阵中对应点置为黑色;若其与周围8个点的比较值都小于自定义值时,
则其不在轮廓线上,T 矩阵对应点置白色。
彩色图提取轮廓线示例:
注:n 值为1.6时, 1)由红色矩阵提取的轮廓线;2)由绿色矩阵提取的轮廓线;
3)由蓝色矩阵提取的轮廓线。
六、 结论与应用
在前面的算法中,在逐行逐列扫描比较各个象素点是否属于轮廓线上的点的
过程中,事先预设除去边框的所有点,这是为了得到比较精简实用的算法。否则,
算法会相对复杂,首先需将图像的边框引入,在算法中便多了四条特殊的线和四
个特殊点,就是上下左右的边线及图像的四个顶点。拿四个顶点而言,可供它们
进行比较的参考点只有三个,而且对于每个点而言,三个参考点的位置都不相同,
这样就造成了算法的累赘冗余。同理,边线也是,边线上的点只有五个参考点,
也是各边方向不同,需要大量相似的代码。
实验证明,提取轮廓线时,加上边框与不加边框的区别非常不明显,故采用
后者的精简算法。在灰度图和彩色图的算法中,对读取生成的图片数据矩阵进行
了线性变换,为的是更好的调节自定义强度值的差值,从而得到令人满意的结果。
选择三角函数sin ,用其进行变换后,可以保证结果值都落到0~1之间,从而控
制扩大后的数值都在0~40的范围。其实这个函数也可以使用其他离散函数,譬
如log ,它的离散作用更加明显,可以将值都变换到[0,+ ) 区间上。)
由于噪声和模糊的存在,轮廓线可能会变宽或在某些点处发生间断。在算法
中,发现图片出现断点,可以通过减小n 值来提高轮廓线的精度从而减少断点。
但是,轮廓线变粗的同时,弊处是也使原有的清晰的其他线条变得更加粗,甚至
出现了模糊的散点。为此,只能寻找一个合适的n 值,使断点不至于太多,轮廓
线也不会太黑糊。
在MATLAB 的图像处理中,导数算子具有突出灰度变化的作用,对图像运
用导数算子,灰度变化较大的点处算得的值比较高,
因此可将这些导数值作为相
应点的边界强度,通过设置门限的方法,提取边界点集。
一阶导数与是最简单的导数算子,它们分别求出了灰度在x 和y 方向上的变化率,而方向α上的灰度变化率可以用相应公式进行计算; 对于数字图像,应该采用差分运算代替求导,差分公式参考相关教材。
函数f 在某点的方向导数取得最大值的方向是,方向导数的最大值是称为梯度模。利用梯度模算子来检测边缘是一种很好的方法,它不仅具有位移不变性,还具有各向同性。为了运算简便,实际中采用梯度模的近似形式。另外,还有一些常用的算子,如Roberts 算子和Sobel 算子。 由于Sobel 算子是滤波算子的形式,用于提取边缘。也可以利用快速卷积函数,简单有效,因此应用很广泛。
拉普拉斯高斯(loG )算法是一种二阶边缘检测方法。它通过寻找图像灰度值中二阶微分中的过零点(Zero Crossing)来检测边缘点。其原理为,灰度级变形成的边缘经过微风算子形成一个单峰函数,峰值位置对应边缘点;对单峰函数进行微分,则峰值处的微分值为0,峰值两侧符号相反,而原先的极值点对英语二阶微分中的过零点,通过检测过零点即可将图像的边缘提取出来。
MATLAB 的图像处理工具箱中提供的edge 函数可以实现检测边缘的功能,其语法格式如下:
1:采用Sobel 算子进行边缘检测
BW = edge(I,'sobel')
2:指定算子方向的Sobel 算子边缘检测
BW = edge(I,'sobel',direction) 其中:
direction=‘horizontal ’,为水平方向;
direction=‘vertical ’,为垂直方向;
direction=‘both ’,为水平和垂直两个方向。
3:Roberts 算子
BW = edge(I,'roberts')
4:拉普拉斯高斯算子
BW = edge(I,'log')
七、 练习
1.任意选取一个灰度图像和彩色图像,对算法中若干关键语句中的参数进行调整,得出不同的实验结果,并对这些结果进行分析。
2.根据自己所学知识,提出自己的轮廓线提取方法,与简单阈值法进行比较分析。
3.练习matlab 自带算子的检测结果。
4.写出图像轮廓线提取的实验报告。