一、主程序介绍
本次程序共分为10个功能点:
第一个功能点是实现彩色图像的灰度化、灰度图像的二值化及图像的灰度变化。
第二个功能点是实现图像的代数运算及逻辑运算。
第三个功能点是基于直方图修正的图像增强。
第四个功能点是基于空间域去实现图像平滑和提取图像边缘。
第五个功能点是基于频域去实现图像平滑及提取图像边缘。
第六个功能点是图像复原。
第七个功能点是图像的膨胀运算、腐蚀运算、开运算及闭运算。
第八个功能点是提取图像中的红苹果。
第九个功能点是检测图像中硬币的数量。
第十个功能点是检测图像中的矩形与圆形。
二、功能模块
1 图像的灰度化与二值化
1.1 算法原理
彩色图像的灰度化:让彩色图像中的R,G,B三分量值相等。
1、最大值法:取R,G,B三个分量中数值最大的分量,并让每个分量都等于最大值。
2、平均值法:取R,G,B三个分量中的平均值,并让每个分量都等于平均值。
3、加权值法:赋予R,G,B不同的权值并使R,G,B的值加权平均。
灰度图像的二值化:确定一个阈值,当灰度值大于阈值时将其灰度值设定为255,当灰度值小于阈值时将其灰度值设定为0。这样就可以得到一个只有黑白像素的二值化图像。
图像的灰度变换:借助变换函数将图像的像素值映射成一个新的像素值,通过改变像素的亮度值实现图像增强。
1、对数变换:通过改变对数函数来改变图像的像素值,以达到图像的灰度变换。
2、指数变换:通过改变指数函数来改变图像的像素值,以达到图像的灰度变换。
3、幂次变换:通过改变幂次函数来改变图像的像素值,以达到图像的灰度变换。
1.2算法实现
彩色图像的灰度化:
在这里插入代码片a=imread("a.jpg")
[x,y,z]=size(a)
s=ones(x,y)
R=im2double(a(:,:,1))
G=im2double(a(:,:,2))
B=im2double(a(:,:,3))
%提取图像的RGB三色分量
for i=1:x
for j=1:y
s(i,j)=max(a(i,j,:));
end
end
%通过遍历找到最大的像素值
var=get(handles.popupmenu1,'value')
%获取弹出式菜单的value值
switch var
case 1
axes(handles.axes2)
%将图片显示在坐标区axes2中
a(:,:,1)=s
a(:,:,2)=s
a(:,:,3)=s
%使分个分量值等于最大值
imshow(a),title("最大值法")
case 2
i1=round((R*0.30+B*0.59+G*0.11)/3*255)
axes(handles.axes2)
a(:,:,1)=i1
a(:,:,2)=i1
a(:,:,3)=i1
%使分个分量值等于加权平均后的值
imshow(a),title("加权值法")
case 3
axes(handles.axes2)
i=round((R+B+G)/3*255)
a(:,:,1)=i
a(:,:,2)=i
a(:,:,3)=i
%使分个分量值等于平均值
imshow(a)
imwrite(a,"1.jpg") ,title("平均值法")
end
灰度图像的二值化:
val=get(handles.slider1,'Value')
%获取滑动条的值
set(handles.text10,'String',num2str(val))
%将此值在静态文本中显示
I=imread("1.jpg")
[a,b]=size(I)
for x=1:a
for y=1:b
if I(x,y)>val
%将滑动条的值设置为阈值
I(x,y)=255;
else I(x,y)=0;
end
end
end
axes(handles.axes3)
%将图片显示在坐标区axes3中
imshow(I),title("二值化图像")
图像的灰度变换:
I=imread("1.jpg")
I=I(:,:,1)
%将三位矩阵变换为二维矩阵
a1=double(I)
var=get(handles.popupmenu3,'value')
%获取弹出式菜单的value值
switch var
case 1
axes(handles.axes5)
%将图片显示在坐标区axes5中
a2=10*log(a1+1)
%以10为底的对数变换
imshow(a2,[]),title("对数变换")
case 2
axes(handles.axes5)
a3=100*exp(0.325*(a1-220)/30)-1
%以e为底的指数函数
imshow(a3,[]),title("指数变换")
case 3
axes(handles.axes5)
a3=a1.^3
%以像素值为底,3为指数的幂次函数
imshow(a3,[]),title("幂数变换")
case 4
axes(handles.axes5)
a4=a1.^0.3
%以像素值为底,3为指数的幂次函数
imshow(a4,[]),title("幂数变换")
end
1.2结果分析
通过上图的对比我们可以看出最大值法会形成一个亮度较高的灰度图像。平均值法会形成一个相对柔和的灰度图像。而加权值法形成了一个相对较暗的灰度图像。我们可以根据自己的需求去选择不同的方法来实现彩色图像的灰度变换。
通过上图我们可以看出不同的阈值会使二值化后的图像达到不同的效果,我们可以通过设定不同的阈值来达到最终想要的二值化图像也可以用此方法来实现图像分割。
通过上图我们可以看出对数变换可以对图像起到提亮的效果,所以我们可以用对数变换来处理较暗的图像。指数变换将图像整体变暗,所以我们可以用指数变换来处理较亮的图像。而幂次函数的指数小于1时能使图像变亮,指数大于1能使图像变暗。我们可以根据自己的需求来选择不同的方法对图像进行灰度变化。
2.图像的代数运算与逻辑运算
2.1 算法原理
加法运算:将两张大小相等的图片对应的像数值相加,若像素值超出灰度值范围则采用以下两种方法处理。
1、截断处理:让大于255的像素值等于255。Imadd函数采用此方法
2、加权求和:让图像A的像素值乘以a(a的范围在0到1之间),让图像B的像素值乘以(1-a),最后将他们想加这样就保证了像数值不会超过255。
减法运算:将两张大小相等的图片对应的像数值相减,若像数值小于0则采用以下两种方法处理。
1、截断处理:让小于0的像素值等于0。Imsubtract函数采用此方法
2、取绝对值:将两张大小相等的图片对于的像数值相减,将结果取绝对值这样就可以保证像素值不会小于0。Imabsdiff函数采用此方法
乘法运算:将两张大小相等的图片对应的像数值相乘,若像数值超过255则采用截断处理,让大于255的像数值等于255。
除法运算:将两张大小相等的图片对应的像数值相除,若像数值小于0则采用截断处理,让小于0的像素值等于0。
非运算:用255减去图像的每个像素值得到的新像素值就构成了新的图像,此图像就是原图像的补图像。
与运算:两个图片对应的像素值同时为1时输出新像素值为1,否则输出新像素值为0。
或运算:两个图片对应的像素值有一个为1输出的新像素值就为1,否则输出新像素值为0。
异或运算:当两个图片对应的像素值相同时输出的新像素值为1,否则输出新像素值为0。
2.2 算法实现
a=imread("bird.jpg")
a1=imread("bird1.bmp")
var=get(handles.popupmenu4,'value')
%获取弹出式菜单的value值
switch var
case 1
i1=imread("a.jpg")
i2=imopen(i1,strel('disk',15))
axes(handles.axes4)
imshow(i1)
axes(handles.axes5)
imshow(i2)
axes(handles.axes7)
i5=imadd(i1,i2)
%用imadd函数实现加法运算
imshow(i5)
case 2
i3=imread("camema.jpg")
i4=imopen(i3,strel('disk',15))
axes(handles.axes4)
imshow(i3)
axes(handles.axes5)
imshow(i4)
axes(handles.axes7)
i6=imsubtract(i3,i4)
%用imsubtract函数实现减法运算
imshow(i6)
case 3
axes(handles.axes4)
imshow(a)
axes(handles.axes5)
imshow(a1)
axes(handles.axes7)
c=immultiply(im2double(a1),im2double(a))
%用immultiply函数实现乘法运算
imshow(c)
case 4
a2=imread("flower.tif.jpg")
a3=a2*0.3+90
axes(handles.axes4)
imshow(a2)
axes(handles.axes5)
imshow(a3)
axes(handles.axes7)
c1=imdivide(double(a2),double(a3))
%用imdivide函数实现除法运算
imshow(c1)
case 5
axes(handles.axes4)
imshow(a)
axes(handles.axes5)
c0=bitcmp(a)
%用bitcmp函数实现非运算
imshow(c0)
axes(handles.axes7)
a=imread("pi.png")
imshow(a)
case 6
axes(handles.axes4)
imshow(a)
axes(handles.axes5)
imshow(a1)
axes(handles.axes7)
c2=bitand(a1,a)
%用bitand函数实现与运算
imshow(c2)
case 7
axes(handles.axes4)
imshow(a)
axes(handles.axes5)
imshow(a1)
axes(handles.axes7)
c3=bitor(a1,a)
%用bitor函数实现或运算
imshow(c3)
case 8
axes(handles.axes4)
imshow(a)
axes(handles.axes5)
imshow(a1)
axes(handles.axes7)
c4=bitxor(a1,a)
%用bitxor函数实现异或运算
imshow(c4)
end
2.3 实验结果及分析
通过以上的图片对比我们可以知道:
加法运算可以将一幅图像的内容叠加到另一幅图像中,达到改善图像视觉效果的作用。也可用于图像的合成与图像拼接方向。
减法运算可以显示两幅图像之间的差异,检测同一场景两幅图像之间的变换。
乘法运算可以对图像的局部进行显示和提取。
除法运算可以用来检测相同图像不同像数值之间的像素值比率变换。
非运算可以用来求取图像的补图像。
与运算可以求两幅图像相交的部分,提取出他们的相同元素。
或运算可以将两幅图像进行合并。
异或运算可以得到两幅图像中不相交的部分。
3.直方图均衡化
3.1 算法原理
灰度直方图的绘制:通过遍历找到每一灰度级的像素总数,在将此灰度级的像素数除以总的像素数即可找到该灰度值的出现频数。最后用横坐标表示灰度级纵坐标表示灰度级出现的频数,再通过一个可以绘制二维条形图的函数即可绘制出灰度直方图。
直方图均衡化:先找到原图像每个灰度级所对应的p值(每个灰度级对应的像素总数除以总像素数),在将p值进行累加(每个灰度级等于前面灰度级的累加值),再将每一灰度级的累加值修正为合理的灰度级,若此灰度级只存在一个则此灰度级的r(与p值意义相同)值即为对应原图像灰度级的p值,若此灰度值存在多个相等的值则将这些灰度级所对应的原图像的p值相加得到最后的r值。最后根据每个新的灰度级与他们对应的r值即可得到均衡化的直方图和均衡化后的图像。
3.2算法实现
a=imread("1zhifangtu.png")
[x,y]=size(a)
h=zeros(1,256)
for i=1:256
h(i)=length(find(a==(i-1)))/(x*y);
%用find依次找到a数组中0到255灰度值的向量,在用length计算出0到255灰度值向量所对应的个数,
%在除以像素总个数,最后将得到的数值p依次存入矩阵h
end
axes(handles.axes2)
bar(0:255,h)
%绘制原图像的直方图
s1=zeros(1,256)
s2=zeros(1,256)
t=0
for i=1:256
t=t+h(i);
s1(i)=t;
%对数值p进行累加计算出新的灰度级
end
s2=round(s1*255)
%将s1中的灰度级修正为合理的灰度级
s3=zeros(1,256)
for i=1:256
s3(i)=sum(h(find(s2==(i-1))));
%在h矩阵中找到与修正后的灰度级对应的灰度级所对应的比重值,如原始灰度级对应同样修正后的灰度级则将他们相加。
end
axes(handles.axes4)
bar(0:255,s3)
%绘制均衡化后图像的直方图
c=a
for i=1:256
c(find(a==(i-1)))=s2(i);
%将均衡化后的灰度值值一一对应给图像c,从而获得直方图均衡化后的图像
end
axes(handles.axes3)
imshow(c)
3.3结果分析
通过上图我们可以看出均衡化前的直方图只占有少部分的灰度级,而均衡化后的直方图占有大部分灰度级且分布均匀。所以直方图均衡化是把原图像的直方图变换为均匀分布的形式,通过增加像素灰度值的动态范围来达到增强图像整体对比度的效果,从而达到图像增强。
4.基于空间域的图像平滑与边缘提取
4.1 算法原理
基于空间域使图像平滑:基于图像空间的邻域模板运算去消除图像中的噪音从而使图像变得平滑。
均值滤波:以图像中某一像素为中心,在它的周围选择一邻域,将邻域中的所有灰度值相加求出其平均值,用此平均值去代替原来的像素值。
中值滤波:以图像中某一像素为中心,在它的周围选择一邻域,将邻域中的所有灰度值进行排序求出中值,用此中值去代替原来的像素值。
高斯滤波:以图像中的某一像素为中心,在它的周围选择一邻域,将邻域内的所有灰度值按高斯正态分布曲线进行统计,分配相应的权值系数,然后算出邻域内所有点的加权平均值,用此加权平均值代替原来的像素值。
基于空间域的边缘提取:基于图像空间的模板运算去提取图像中的边缘与轮廓。
Robert算子、Sobel算子、Prewitt算子、二阶微分算子原理一致只是模板并不相同。
原理:遍历图像中的每一个像素值用其对应的模板进行运算,用运算后的像素值代替原像素值。最后得到全新的像素值图像级是边缘提取后的图像。
4.2算法实现
添加噪音:
a=imread("1zao.png")
[height,width,channel]=size(a);
if channel==3
a=a(:,:,1);
% 将三位矩阵变为二维矩阵
end
J=imnoise(a,'gauss',0.02)
% 添加高斯噪声
J1= imnoise(a,'salt & pepper')
% 添加椒盐噪声
var=get(handles.popupmenu3,'value')
%获取弹出式菜单的value值
switch var
case 1
axes(handles.axes8)
imshow(J),title("高斯噪声")
imwrite(J,'1zao1.png')
case 2
axes(handles.axes8)
imshow(J1),title("椒盐噪声")
imwrite(J1,'1zao1.png')
imwrite(J1,'1zao1.jpg')
end
图像平滑:
i=imread("1zao1.png")
var=get(handles.popupmenu2,'value')
switch var
case 1
axes(handles.axes7)
a=fspecial('average',3)
%生成3*3模板的均值滤波
a1=uint8(filter2(a,i))
%进行中值滤波运算
imshow(a1),title('均值滤波')
b1=uint8(medfilt2(i,[3 3]))
%对图像进行3*3模板的中值滤波计算
axes(handles.axes10)
imshow(b1),title('中值滤波')
c=fspecial('gaussian',3)
%生成3*3模板的高斯滤波
c1=uint8(filter2(c,i))
%进行高斯滤波运算
axes(handles.axes11)
imshow(c1),title('高斯滤波')
case 2
axes(handles.axes7)
a=fspecial('average',5)
%生成5*5模板的均值滤波
a1=uint8(filter2(a,i))
%进行中值滤波运算
imshow(a1),title('均值滤波')
b1=uint8(medfilt2(i,[5 5]))
%对图像进行5*5模板的中值滤波计算
axes(handles.axes10)
imshow(b1),title('中值滤波')
c=fspecial('gaussian',5)
%生成5*5模板的高斯滤波
c1=uint8(filter2(c,i))
%进行高斯滤波运算
axes(handles.axes11)
imshow(c1),title('高斯滤波')
end
边缘提取:
I=imread("1zao.png")
var=get(handles.popupmenu1,'value')
switch var
case 1
h=[1 0;0 -1];h1=[0 1;-1 0]
%Roberts算子模板
t=imfilter(I,h);t1=imfilter(I,h1)
%对图像进行相应滤波运算
J=abs(t)+abs(t1)
%将结果取绝对值后相加
axes(handles.axes6)
imshow(J),title("Robert算子 ")
c=imread("button.png")
axes(handles.axes8)
imshow(c)
axes(handles.axes7)
imshow(c)
axes(handles.axes10)
imshow(c)
axes(handles.axes11)
imshow(c)
case 2
h2=[-1 -2 -1;0 0 0;1 2 1];h3=[-1 0 1;-2 0 2;-1 0 1]
%Sobel算子模板
t2=imfilter(I,h2);t3=imfilter(I,h3)
%对图像进行相应滤波运算
J1=abs(t2)+abs(t3)
%将结果取绝对值后相加
axes(handles.axes8)
imshow(J1),title("Sober算子")
case 3
H1=[-1 -2 -1;0 0 0;1 2 1];
H2=[0 -1 -2;1 0 -1; 2 1 0];
H3=[1 0 -1;2 0 -2;1 0 -1];
H4=[2 1 0;1 0 -1;0 -1 -2];
H5=[1 2 1;0 0 0;-1 -2 -1];
H6=[0 1 2;-1 0 1;-2 -1 0];
H7=[-1 0 1;-2 0 2;-1 0 1];
H8=[-2 -1 0;-1 0 1;0 1 2];
%Sobel算子扩展
%对图像进行Sobel每个扩展模板的运算
R1=imfilter(I,H1);
R2=imfilter(I,H2);
R3=imfilter(I,H3);
R4=imfilter(I,H4);
R5=imfilter(I,H5);
R6=imfilter(I,H6);
R7=imfilter(I,H7);
R8=imfilter(I,H8);
f1=max(max(R1,R2),max(R3,R4));
f2=max(max(R5,R6),max(R7,R8));
%找到每行的最大值
a=max(f1,f2)
axes(handles.axes7)
imshow(a),title("8模板Sobel算子")
case 4
h=[-1 -1 -1;0 0 0;1 1 1];h1=[-1 0 1;-1 0 1;-1 0 1]
%Prewitt算子模板
t=imfilter(I,h);t1=imfilter(I,h1)
%对图像进行相应滤波运算
J2=abs(t)+abs(t1)
axes(handles.axes10)
imshow(J2),title("Prewitt算子 ")
case 5
h=[0 -1 0;-1 4 -1;0 -1 0]
%Laplacian算子模板
b=imfilter(I,h)
%对图像进行相应滤波运算
axes(handles.axes11)
imshow(b),title("Laplacian算子")
end
4.3结果分析
通过对比以上图片我们可以知道:
均值滤波更适合用来处理高斯噪声,因为高斯噪声的幅值是正态分布的且高斯噪声会让图片的每一点都成为污染点,用中值滤波去处理并不能选择合适的点去去代替污染点,而使用均值滤波时当噪声正态分布的均值为0时就可以消除(减弱)噪声。
中值滤波更适合用来处理椒盐噪声,因为椒盐噪声点出现的位置是随机的还会有一些未被污染的点存在,而中值滤波可以选择合适的点来代替污染点的值,从而消除(减弱)噪声。
选择不同的模板也会对图像的平滑起到不同的效果,当邻域模板越大时图像会变得更加模糊。所以当我们去消除噪声时不仅要考虑消除噪声效果也要考虑到图像的模糊程度,从而去选择合适的模板大小。
Sobel算子与Prewitt算子提取的边缘比Roberts算子更加粗和亮,这是因为Prewitt算子和Roberts算子的模板是相隔两行或两列求差分,而Soberts算子的模板是相隔一行或一列求差分。8模板的Sobel算子检测相比单模板Sobel算子检测到的边缘信息更加丰富。
5.基于频域的图像平滑与边缘提取
5.1算法原理
频率域滤波原理:通过滤波器函数以某种方式修改图像变换,然后通过取结果的反变换来获得处理后的图片。
基于频域的图像平滑:对图像进行正交变换,利用噪声对应高频信息的特点去消除噪声。
低通滤波器:让低频通过而使高频衰减的滤波器,因噪声是高频信息所以采用低通滤波器可实现基于频域的图像平滑。
理想低通滤波器:选定一个截止频率D0,找到图像中的每一点到频率域原点的距离b(定义为D(x,y)=(x2+y2)(1/2)),如果b值大于D0则设定该点的h值为0,如果该点的距离小于D0则设定该点的h值为1,最后用h值乘以该点像素值得到像素值即为该点的新像素。
巴特沃斯低通滤波器:选定一个截止频率D0、阶n,找到图像中的每一点到频率域原点的距离b,计算出1/(1+(b/D0)2n)的值,用此值去乘以没点对应的像素值,得到的即为新像素值。
高斯低通滤波器:选定一个截止频率D0,找到图像中的每一点到频率域原点的距离b,计算出exp(-(bb)/(2(D0^2)))的值,用此值去乘以每点对应的像素值,得到的值即为新像素值。
基于频域的边缘提取:对图像进行正交变换,利用边缘对应高频信息的特点去提取边缘。
高通滤波器:让高频通过而使低频衰减的滤波器,因边缘对应高频信息所以可以采用高通滤波器可实现基于频域的边缘提取。
理想高通滤波器:选定一个截止频率D0,找到图像中的每一点到频率域原点的距离b(定义为D(x,y)=(x2+y2)(1/2)),如果b值小于D0则设定该点的h值为0,如果该点的距离大于D0则设定该点的h值为1,最后用h值乘以该点像素值得到像素值即为该点的新像素。
巴特沃斯低通滤波器:选定一个截止频率D0、阶n,找到图像中的每一点到频率域原点的距离b,计算出1/(1+(D0/b)2n)的值,用此值去乘以没点对应的像素值,得到的即为新像素值。
高斯低通滤波器:选定一个截止频率D0,找到图像中的每一点到频率域原点的距离b,计算出1-exp(-(bb)/(2(D0^2)))的值,用此值去乘以每点对应的像素值,得到的值即为新像素值。
5.2算法实现
Is=imread('1pinyu.png');
I=double(Is);
I=fftshift(fft2(I));
%傅里叶变换及频谱中心化
[a,b]=size(I);
g=zeros(a,b);
a0=round(a/2);
b0=round(b/2);
D0=val;
var=get(handles.popupmenu1,'value')
switch var
case 1
for i=1:a
for j=1:b
H=sqrt((i-a0)^2+(j-b0)^2);
%找到图像中每一点到频率域原点的距离
if H<=D0
h=1;
else
h=0;
end
g(i,j)=h*I(i,j);
end
end
axes(handles.axes2)
I0=uint8(real(ifft2(ifftshift(g))));
%转换为原来的频谱之后进行反傅里叶变换
imshow(I0);title("理想低通滤波器");
n=6
for i=1:a
for j=1:b
h=sqrt((i-a0)^2+(j-b0)^2)
h1=exp(-(h*h)/(2*(D0^2)));
%计算高斯低通转移函数h
h2=1/(1+(h/D0)^(2*n));
%计算巴特沃斯低通函数h
g1(i,j)=h1*I(i,j);
g2(i,j)=h2*I(i,j);
end
end
axes(handles.axes3)
I1=uint8(real(ifft2(ifftshift(g1))));
imshow(I1);title("高斯低通滤波器");
I2=uint8(real(ifft2(ifftshift(g2))));
axes(handles.axes4)
imshow(I2); title("巴特沃斯低通滤波器")
case 2
for i=1:a
for j=1:b
H=sqrt((i-a0)^2+(j-b0)^2);
if H<=D0
h=0;
else
h=1;
end
gg(i,j)=h*I(i,j);
end
end
axes(handles.axes2)
I0=uint8(real(ifft2(ifftshift(gg))));
imshow(I0);title("理想高通滤波器");
n=6
for i=1:a
for j=1:b
h=sqrt((i-a0)^2+(j-b0)^2);
h1=1-exp(-(h*h)/(2*(D0^2)));
%计算高斯高通转移函数h
h2=1/(1+(D0/h)^(2*n));
%计算巴特沃斯高通转移函数h
gg1(i,j)=h1*I(i,j);
ggg1(i,j)=h2*I(i,j);
end
end
axes(handles.axes3)
I1=uint8(real(ifft2(ifftshift(gg1))));
imshow(I1);title("高斯高通滤波器");
axes(handles.axes4)
I1=uint8(real(ifft2(ifftshift(ggg1))));
imshow(I1); title("巴特沃斯高通滤波器")
end
5.3结果分析
通过以上的图片我们可以看出:
低通滤波器可以消除图像中的噪音使图像变得平滑,而高通滤波器可以提取图像边缘。
在低通滤波器中截止频率越小意味着低通滤波器就越窄,消除的低频成分就越多,使的图像会变得更加模糊。且我们可以看出高斯低通滤波器没有振铃现象,而理想低通滤波器相比于巴特沃斯滤波器振邻现象更加严重。
在高通滤波器中截止频率越小意味着高通滤波器越窄,提取到的高频成分就越多,边缘提取的效果就更好。
6.图像复原
6.1算法原理
图像退化:图像退化是指原图像在一个退化系统及噪声的影响下使图片质量下降的过程。
图像复原:图像复原是尽可能让退化后的图像恢复成原图像,最优情况就是我们能知道图像的退化过程,从而使用退化过程的逆过程去实现图像的复原。其流程就是先找到图像退化的原因,根据退化原因去建立退化模型,在反向推演让图像恢复成原图像。
为纳滤波复原:为纳滤波是一种能很好处理有噪声的图片,它是一种代表性的约束复原方法,是使原图像和复原图像之间均方误差最小的方法。
6.2算法实现
a=imread("1yund.png")
PSF=fspecial ('motion',25,11);
% 生成运动模糊滤波
a1=imfilter (a,PSF, 'conv' , 'circular') ;
% 生成运动模糊图像
axes(handles.axes3)
imshow(a1)
imwrite(a1,"1yund.png")
a=imread("1yund.png")
J=imnoise(a,'gauss',0.02)
% 添加高斯噪声
J1= imnoise(a,'salt & pepper')
% 添加椒盐噪声
var=get(handles.popupmenu2,'value')
switch var
case 1
axes(handles.axes5)
imshow(J),title("高斯噪声")
imwrite(J,'1Z.png')
case 2
axes(handles.axes5)
imshow(J1),title("椒盐噪声")
imwrite(J1,'1Z.png')
end
a=imread("1Z.png")
var=get(handles.togglebutton1,'value')
% 获取切换按钮的value值
switch var
case 0
J=imnoise(a,'gauss',0.02)
% 高斯噪声
case 1
J= imnoise(a,'salt & pepper')
% 椒盐噪声
end
PSF=fspecial ('motion',25,11);
q=abs(fft2(J)).^2;
计算噪声功率谱
q1=sum(q(:))/prod(size(J));
%计算噪声的平均功率
q2=abs(fft2(a)).^2;
%计算图像功率谱
q3=sum(q2(:))/prod(size(a));
%计算图像平均功率
NSR=q1/q3;
%计算信噪比
axes(handles.axes6)
a1=deconvwnr(a,PSF,NSR)
%使用维纳滤波对图像进行复原
imshow(a1);title('图像复原')
6.3结果分析
通过以上图片我们可以看出:
通过已知的图像退化过程再用逆过程对图像进行复原能让图像大概接近原图像,但是却并没有达到完全相同的效果。代码中我用的是维纳滤波复原是因为我可以计算出原始图像的噪声功率和图像的功率,从而对图像进行复原。但当我们不知道这些时我们在采用为纳滤波时效果就并没有那么好了,这个时候我们需要使用约束最小二乘方法。而当我们的图像中没有噪声影响时我们可以采用逆滤波去对图像进行复原。
7.图像的形态变换
7.1算法原理
膨胀运算:选取一个结构元素,对结构元素作关于原点的映射得到新的集合,若此集合与原图像集合相交不为空集时,记录结构元素参考点的位置,最后得到的集合即为原图像被结构元素腐蚀的结果。
腐蚀运算:选取一个结构元素,对结构元素作关于原点的映射得到新的集合,若此集合完全包括在原图像集合中,记录结构元素参考点的位置,最后得到的集合即为原图像被结构元素腐蚀的结果。
开运算:先对图像进行腐蚀运算,在进行膨胀运算。
闭运算:先对图像进行膨胀运算,在进行腐蚀运算。
7.2算法实现
global a
%定义全局变量a
b=get(handles.edit1,'String')
%获取可编辑文本框中的内容
a=str2double(b)
%将字符串转换为数值
global a1
b1=get(handles.edit2,'String')
a1=str2double(b1)
c=imread("1fushi.png")
SE=strel('rectangle',[a a1]);
%定义一个结构元素
i2=imdilate(c,SE)
%膨胀运算
axes(handles.axes2)
imshow(i2);title('二值图像膨胀');
i3=imerode(c,SE);
%腐蚀运算
axes(handles.axes3)
,imshow(i3);title('二值图像腐蚀');
a=i3
%得到腐蚀后的图像
a1=imdilate(a,SE)
%对腐蚀后的图像进行膨胀运算
axes(handles.axes4)
imshow(a1);title(二值图像的开运算');
b=i2
%得到膨胀后的图像
b1=imerode(b,SE);
%对膨胀后的图像进行腐蚀运算
axes(handles.axes5)
imshow(b1);title('二值图像的闭运算');
7.3结果分析
通过以上的图片我们可以看出:
膨胀运算:放大目标,也可填补目标中的空洞
腐蚀运算:缩小目标,也可以消除小于结构元素的噪声点从而达到平滑效果。
通过对比215与152的矩形结构元素的腐蚀与膨胀运算我们可以看出横向的结构元素会让数字的膨胀与腐蚀朝着横向的方向进行,对比原始图像膨胀会加宽数字的横向宽度而腐蚀会减少数字的横向宽度。而我们竖向的结构元素会让数字的膨胀与腐蚀朝着竖向的方向进行,加宽与减少图像的竖向长度。
通过对比横向结构元素与竖向结构元素的腐蚀运算,我们可以看到图像中略小的数字在横向的腐蚀后只保留了横线而我们的竖线被其腐蚀掉了,而竖向的腐蚀保留了我们的竖线而我们的横线被其腐蚀掉了。
开运算:平滑图像的轮廓且不会使图像的大小有太大的改变,能削弱图像的狭窄部分并去掉其细长的突出部分、边缘的毛刺和孤立的斑点。
闭运算:也能平滑图像的轮廓并可以去融合图像中窄的缺口和细长的弯口,能够填补图像的裂缝及破洞,实现连通补缺作用。
8.图像分割-提取红苹果
8.1算法原理
基于颜色的图像分割:观察其直方图,查看此提取颜色的大概灰度级范围,选定合适的阈值将图像变为二值化图像,从而将提取颜色与背景分开,在运用开运算消除掉提取颜色形状以外的形状,从而实验基于颜色的图像分割。
8.2算法实现
a=imread("pinguo.jpg")
var=get(handles.popupmenu1,'value')
% 获取弹出式菜单的value值
switch var
case 1
axes(handles.axes1)
imshow(a)
% 显示原图像
case 2
axes(handles.axes2)
R=a(:,:,1);
%提取图像的R通道图
imshow(R)
imwrite(R,"1r.png")
case 3
axes(handles.axes3)
R2=imread("1r.png")
R3=medfilt2(R2,[3 3])
%对图像的R通道图进行消噪处理
imshow(R3)
imwrite(R3,"1r.png")
case 4
R4=imread("1r.png")
axes(handles.axes4)
imhist(R4)
%显示图像的R通道的直方图
End
global a1
%定义全局变量a1
b=get(handles.edit4,'String')
%获取可编辑文本4的内容
a1=str2double(b)
%将字符串转换为数值
R=imread("1r.png")
[a,b]=size(R)
for x=1:a
for y=1:b
if R(x,y)<a1
R(x,y)=0;
%当小于阈值时使其像素值为0
else R(x,y)=255;
end
end
end
axes(handles.axes5)
imshow(R)
global g
%定义全局变量g
p=get(handles.edit2,'String')
%获取可编辑文本3的内容
g=str2double(p)
%将字符串转换为数值
global g1
p1=get(handles.edit3,'String')
g1=str2double(p1)
SE=strel('rectangle',[g g1]);
%定义一个结构运算
R1=imread("11r.png")
i2=imerode(R1,SE);
%腐蚀运算
i3=imdilate(i2,SE)
%膨胀运算
axes(handles.axes6)
imshow(i3)
8.3结果分析
通过以上图片我们可以知道:
在R通道图像中红色的苹果呈现的颜色明显要亮与背景颜色,在直方图中我们可以大概确定出阈值,通过此阈值对图像进行二值化,从而将苹果与背景进行分割,在对图像进行开运算去除掉处苹果以外的形状,最后就能提取处苹果形状。
因为图像中苹果下部分的灰度值偏暗,若想将这部分提取出来只能降低阈值,但是降低阈值后,图像中会出现很多除苹果以外的形状,若想消除他们只能选取较大的结构元素。我们可以根据自己想要的效果来设定阈值和结构元素,从而提取到自己想要的苹果形状。
9.图像分割-检测硬币数量
9.1算法原理
基于灰度直方图阈值选择的图像分割:若图像的灰度直方图为双峰分布,说明图像的内容大致分为两部分,选择阈值为两峰间的谷底点对应的灰度值,将此图像进行二值化即可将图像分割成两部分。
分割后的图像已经将硬币的形状完整的分割出来,在通过Bwlabel函数几个检测出图像中硬币的数量。
Bwlabel函数:查找图像中的四连通域或八连通域,就是查找黑色背景下一共有多少白色的块。
9.2算法实现
a=imread("yinbi.png")
axes(handles.axes1)
imshow(a),title("原图像")
a=imread("yinbi.png")
axes(handles.axes2)
imhist(a),title("直方图")
global g
p=get(handles.edit1,'String')
%获取可编辑文本1的内容
g=str2double(p)
%将字符串转换为数字
a1=imread("yinbi.png")
axes(handles.axes3)
b1=a1;
[a,b]=size(b1)
for x=1:a
for y=1:b
if a1(x,y)<g
b1(x,y)=0;
else b1(x,y)=255;
end
end
end
imshow(b1)
imwrite(b1,"1yinbi.png"),title("二值化图像")
global g2
p1=get(handles.edit2,'String')
%获取可编辑文本2的内容
g2=str2double(p1)
global g3
p2=get(handles.edit3,'String')
%获取可编辑文本3的内容
g3=str2double(p2)
SE=strel('rectangle',[g2 g3]);
%定义结构元素
a=imread("1yinbi.png")
i2=imerode(a,SE);
%腐蚀运算
i3=imdilate(i2,SE)
%膨胀运算
axes(handles.axes4)
imshow(i3),title("开运算后图像")
imwrite(i3,"11yinbi.png")
a=imread("11yinbi.png")
[L, NUM] = bwlabel(a, 4)
s=sprintf('检测到硬币的数量为:%d',NUM)
set(handles.text4,'String',s)
%设置静态文本的内容为s
9.3结果分析
通过上面的图片我们可以知道:
基于直方图的阈值选择能将选取内容与图像较好的分割开来。但是这种几率很少因为很多图像的直方图并没有呈现双峰分布。
经过二值化后的图像有一些我们看不到的白块,若我们直接忽略它不进行开运算消除掉他们,采用bwlabel函数时这些白块也会被算在硬币数量中,因为bwlabel函数只是查找黑色背景中有多少的白块,并不区分这些白块是否是硬币的形状,所以我们必须使用开运算去消除掉处硬币以外的白块,从而检测出正确的硬币数量。
10.检测特定形状-矩形与圆形
10.1算法原理
1、先使用Canny算子提取出图像中各个形状的边缘
2、对图像进行闭运算,从而将不连续的边缘变的连续起来。
3、使用imfill函数对图像进行区域填充,从而达到将各个图像形状与背景分割的效果。
4、基于矩形度与圆形度来检测图像形状。
矩形度:物体的面积与最小外接矩形的面积之比。当物体为矩形时矩形度的值为1,当物体为圆形时矩形度的值为π/4。
圆形度:面积与周长平方的比值。当物体为圆形时圆形度的值为1,当物体越偏离与圆形圆形度的值就越小。
10.2算法实现
a=rgb2gray(imread("shape.png"))
%将图像进行二值化
var=get(handles.popupmenu1,'value')
%获取弹出式菜单的value
switch var
case 1
axes(handles.axes1)
imshow(a),title("原图像")
case 2
axes(handles.axes2)
a1=edge(a,'canny')
%使用canny算子提取边缘图像
imshow(a1)
imwrite(a1,"1qux.png"),title("边界图像")
case 3
axes(handles.axes3)
b=imread("1qux.png")
SE=strel('disk',5)
%定义一个半径为5的平面圆形结构元素
b1=imclose(b,SE)
imshow(b1)
imwrite(b1,"1qux.png"),title("闭运算")
case 4
axes(handles.axes4)
k=imread("1qux.png")
k1=imfill(k,'holes')
%填充灰度图像中的所以空洞区域
imshow(k1)
imwrite(k1,"1qux.png"),title("区域填充")
case 5
axes(handles.axes5)
a=imread("1qux.png")
[B,L]=bwboundaries(a);
%获取二值图像对象的轮廓
imshow(L) ,title("检测结果")
STATS = regionprops(L,'Area', 'Centroid','BoundingBox');
%获取图像各个区域的像素总个数、质心和最小矩阵
len=length(STATS);
hold on
for i=1:len
R=STATS(i).Area/(STATS(i).BoundingBox(3)*STATS(i).BoundingBox(4));
%求出矩形度
boundary=fliplr(B{i});
%对矩阵进行翻转
everylen=length(boundary);
F=4*pi*STATS(i).Area/(everylen^2);
%求出圆度
dis=pdist2(STATS(i).Centroid,boundary,'euclidean');
miu=sum(dis)/everylen;
%求出区域性心到边界点的平均距离
sigma=sum((dis-miu).^2)/everylen;
%求出区域性心到边界点的距离方差之比
C=miu/sigma;
%求出圆形性
if R>0.9 && F<1
%判断矩形 rectangle('Position',STATS(i).BoundingBox,'edgecolor','b','linewidth',2);
%将矩形的外围设置为蓝色
end
if R>pi/4-0.1 && R<pi/4+0.1 && F>0.9 && C>10
%判断圆形 rectangle('Position',[STATS(i).Centroid(1)-miu,STATS(i).Centroid(2)-miu,2*miu,2*miu],...
'Curvature',[1,1],'edgecolor','r','linewidth',2);
%将圆形的外围设置为红色
end
end
end
10.3结果分析
通过上面的图片我们可以知道:
通过canny算子提取的图像边缘并不是连续的,而闭运算可以起联通补缺的作用使这些边缘变的连续起来,在通过区域填充即可将这些形状与背景分割出来。当然一些特殊的图片可直接通过阈值法将形状与背景分割。分割后的图像再通过对比各形状的矩形度、圆形度、圆形性即可区分出圆形与矩形。
三、创新点(使用GUI界面)
打开GUI界面:在命令行窗口输入guide
新建GUI
常用按键(使用方法可参考代码):
在对应按键的回调函数实现按键功能:
修改GUI界面的背景:
handles.output = hObject;
%设置背景
ha=axes('units','normalized','pos',[0 0 1 1]);
uistack(ha,'bottom');
%置于底部用buttom
ii=imread('beij3.png');
image(ii);
colormap gray
set(ha,'handlevisibility','off','visible','off');
修改按钮背景:文章来源:https://www.toymoban.com/news/detail-454621.html
a=imread("u5.png");
set(handles.pushbutton1,'CData',a);
GUI界面的跳转:文章来源地址https://www.toymoban.com/news/detail-454621.html
function pushbutton1_Callback(hObject, eventdata, handles)
% hObject handle to pushbutton1 (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
close
%关闭当前界面
run("XS")
%跳转到XS界面
到了这里,关于数字图像处理MATLAB大作业:基础版的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!