实验2华工电信数学实验大二下.docx
《实验2华工电信数学实验大二下.docx》由会员分享,可在线阅读,更多相关《实验2华工电信数学实验大二下.docx(11页珍藏版)》请在冰豆网上搜索。
实验2华工电信数学实验大二下
实验名称:
图像轮廓线提取技术
专业:
电子科学与技术
班级:
姓名:
序号:
36
提交日期:
2011年5月1日
一、实验目的与要求:
1、了解对matlab的图像处理功能,掌握基本的图像处理方式;
2、掌握imread,imshow,imwrite,subplot,title等的基本使用方法。
3、掌握图像轮廓线提取的简单方法并上机实现。
4、了解matlab自带的边界检测算子的使用,提高对复杂图像处理的能力。
二、问题描述
1.任意选取一幅灰度图像和一幅彩色图像,对算法中若干关键语句中进行调整,得出不同的实验结果,对这些结果进行分析,并与MATLAB自带的边缘检测做对比。
2.提出其它的轮廓线提取方法,与简单阈值法进行比较分析。
三、问题解决
练习一:
任意选取一幅灰度图像和一幅彩色图像,对算法中若干关键语句中进行调整,得出不同的实验结果,对这些结果进行分析,并与MATLAB自带的边缘检测做对比。
解:
我从网上下载一幅彩色照片,用Photoshop将其转成灰白色调。
得到两幅JPG格式图片。
灰色图:
首先用函数IMREAD用来读取图形文件。
A=IMREAD(FILENAME,FMT)格式用以读取由字符串FILENAME所指定的一张灰度图,而字符串FMT用以详细说明该文件的格式。
如果该文件不在当前MATLAB的工作目录或MATLAB其他指定路径中,需指明该图在系统中的完整路径。
IMREAD返回该图像的数据值给数组A。
如果该文件包含的是一张灰度图,A是一个二维(MN)的数组。
如果该文件包含的是一张彩色图,A则是一个三维(MN3)的数组。
其返回数组的类型是根据该文件所使用的格式而定的。
IMAGE用来显示图片或者图形。
IMAGE(C)将矩阵C显示为一幅图像。
C中的每一个元素指明了该图中对应点的颜色。
矩阵C可以是MN维或者MN3维的,它的数据可以是双精度,8位无符号整型,或者16位无符号整型的。
SIZE用以求数组的大小
D=SIZE(X),对于MN的矩阵X,它返回一个含有两个元素的行向量D=[M,N],其M和N分别代表该矩阵的行数和列数。
对于矩阵X而言,[M,N]=SIZE(X)返回行和列数。
灰度图经过IMREAD函数读取后,生成的是一个2维(MN)矩阵,其每一个数值都代表着原图片中对应象素点的色彩的灰度值,范围[0,255],并且都是正整数。
其中,0表示黑,255表示白。
位于轮廓线上的点,它与其相邻的点的灰度值差有一定的跳跃,故通过值的对比,就可以将那些边缘点提取出来。
但是,为了代码的简单实用,首先我去掉了图像的边框上的所有象素点,即:
去掉灰度值矩阵的第一行、第一列、最后一行和最后一列。
这样做的好处是显而易见的,因为可以保证每一个待比较的点其周围都有8个供比较的点,如图示:
在算法中,将中心那个点依次与其上下、左右、左上、右下,和右上、左下8个点做比较,若差值大于规定值,则其就是轮廓线上的点,反之不是。
算法关键的地方是对IMREAD生成的矩阵进行了非线性变换。
首先,将这个矩阵从8位无符号型变成双精度的数值存储;然后才能进行下一步的将其每个值都除以255,这样就把每个数值都调整为0~1之间的小数;再用正弦sin函数将这些值做变换,并取求得的结果放大40倍。
这样一来,本来是在0~255之间的正整数,就被变换到0~1之间的小数,然后再离散成0~40之间的双精度数值。
其目的是为了在进行比较灰度值的时候,方便自定义各种差值。
灰度图的源代码(.m文件)如下:
functiongraydrawout('H:
\狗(灰).jpg',n)%灰度图的轮廓线提取
A=imread('H:
\狗(灰).jpg');%读取指定的灰度图
[a,b]=size(A);%a,b分别等于矩阵A的行数和列数
B=double(A);%将矩阵A变为双精度矩阵
D=40*sin(1/255*B);%将矩阵B进行线性变换
T=A;%新建与A同等大小矩阵
forp=2:
a-1%处理图片边框内的像素点
forq=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('灰度图原图');%图释
axisimage;%保持图片显示比例
subplot(2,1,2);%下图显示于第二行
image(T);%显示提取轮廓线后的图片
title('提取轮廓线');%图释
axisimage;%保持图片显示比例
代码的主体是if-else-end部分,我们来分析它。
其原理就是将中心点与其周围的8个点依次比较,发现有一个差值大于自定义的值时,就判断其为轮廓线上的点并将之置为黑色;若其与周围8个点的比较值都小于自定义值时,则其不在轮廓线上,置白色。
灰度图提取轮廓线示例
运行结果:
n=1
n=2
n=3
彩色图:
彩色图片经过IMREAD函数读取后,由于它的每一个象素点都是由红、绿、蓝三色的强度值一起定义其颜色的,所以,生成的是一个3维的(MN3)矩阵。
矩阵平面(:
,:
,1)代表对应象素点的红色强度值,矩阵平面(:
,:
,2)是绿色强度值,矩阵平面(:
,:
,3)则是蓝色强度值。
在每一个矩阵平面中强度值的范围是[0,255]的正整数。
位于轮廓线上的点,它的红、绿、蓝三色的强度值与其周围的点必然有一定的差值,也正式利用这些差值的比较,可以将那些位于边缘的点提取出来。
在算法上,彩色图与灰度图不同的是,彩图的每一个单色矩阵可以单独用来判定该点是否位于轮廓线上。
其算法与灰度图的原理非常相似。
在彩色图的算法中,加入了对判定矩阵的选择,即提供使用者自由选择用图片的哪一个单色矩阵进行轮廓线提取。
因为根据图片本身的特点,选择更适合于进行提取的矩阵,其效果是十分不同的,在下面的讨论中将会再次提到这个问题。
算法关键的地方同样是对IMREAD生成的矩阵进行了线性变换。
首先,将这个矩阵从8位无符号型变成双精度的数值存储;然后才能进行下一步的将其每个值都除以255,这样就把每个数值都调整为0~1之间的小数;再用正弦sin函数将这些值做变换,并取求得的结果放大40倍。
这样一来,本来是在0~255之间的正整数,就被变换到0~1之间的小数,然后再离散成0~40之间的双精度数值。
其目的是为了在进行比较单色强度值的时候,方便自定义各种带小数的差值。
彩色图轮廓线提取的源代码(.m文件)如下:
functioncolordrawout(‘F:
\狗(彩).jpg’,n)%彩色图片轮廓线提取函数
A=imread(‘F:
\狗(彩).jpg’);%读取指定彩色图片
B=A(:
:
1);%红色强度值矩阵
C=A(:
:
2);%绿色强度值矩阵
D=A(:
:
3);%蓝色强度值矩阵
fori=1:
3%依次从三个矩阵中提取轮廓线
ifi==1%从红色矩阵提取
E=B;
elseifi==2%从绿色矩阵提取
E=C;
elseE=D;%从蓝色矩阵提取
end;
end;
H=double(E);%将选择的矩阵变为双精度矩阵
F=40*sin(1/255*H);%进行非线性变换
[k,j]=size(B);%k,j分别为矩阵D的行数和列数
T=A;
forp=2:
k-1
forq=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);%图释
axisimage;%保持图片显示比例
end;
subplot(2,2,1);%下图显示于第1位置
image(A);%显示原彩色图片
title('彩色图原图');%图释
axisimage;%保持图片显示比例
注释:
pix-为要提取轮廓线的灰度图名(带路径),由单引号括住。
n-自定义的强度值值差值,超过该值就是轮廓线上的点,反之不然。
这是一个最重要的参数,通过调节它的值,修整轮廓线的效果
范围为0~40之间的任何有理数。
A-MATLAB读取原图片后返回的数据矩阵,3维(MN3)
T-新建的与A矩阵同等行列数的矩阵,待放入比较后结果。
代码中加入的部分是对单色强度值矩阵的选择。
从比较中可以看出,选择彩色图片中最大程度的颜色矩阵,可以提高提取轮廓线的效果。
譬如:
图片以红色为主,就选择1-红色矩阵。
代码的主体同样是if-else-end部分。
其原理仍是将中心点与其周围的8个点依次比较,发现有一个差值大于自定义的值时,就判断其为轮廓线上的点并将T矩阵中对应点置为黑色;若其与周围8个点的比较值都小于自定义值时,则其不在轮廓线上,T矩阵对应点置白色。
彩色图提取轮廓线示例:
n=1
n=1.5
n=2
注:
1)由红色矩阵提取的轮廓线;2)由绿色矩阵提取的轮廓线;3)由蓝色矩阵提取的轮廓线。
练习二:
提出其它的轮廓线提取方法,与简单阈值法进行比较分析。
算法:
将指针在像素矩阵上依次移动,每到达一点时,取出其自身及其周围共9个像素点进行分析。
利用std函数计算这9个灰度值的标准差,当该值大于预设阈值n时,判断该点为边界点。
源代码:
A=imread('H:
\狗(灰).jpg');
[a,b]=size(A);
B=double(A);
D=40*sin(1/255*B);
T=A;
n=0.5;
fori=2:
a-1
forj=2:
b-1
c=[D(i-1,j-1:
j+1),D(i,j-1:
j+1),D(i+1,j-1:
j+1)];%将九个像素点排成一行
s=std(double(c));%计算九个像素点的标准差
ifs>n%比较标准差与阈值n
T(i,j)=0;
elseT(i,j)=255;
end
end;
end;
subplot(2,1,1);
image(A);
title('灰度图原图');
axisimage;
subplot(2,1,2);
image(T);
title('提取轮廓线');
axisimage;
n=1
n=2
算法分析与比较:
从处理结果来看,用此算法得到的图像中噪声点较少,线条清晰连续。
噪声点少主要是因为此算法运用标准差运算,通过计算9个像素点的差异大小来判定某点是否分界点,而不是像原算法,仅仅通过比较相邻两点之间的差异大小来判定是否分界点,因此本结果零散的点(误判的分界点)更少。
但是计算的时间明显要更长,计算机处理起来更为繁琐。