一、任务描述

基础版:图像处理小工具。

需包含以下基本功能:

  • 导入图片(或从摄像头加载图片 ); 
  • 彩色图像灰度化; 
  • 灰度图像二值化; 
  • 两幅图像叠加; 
  • 目标检测(即两幅图像相减); 
  • 图像的灰度变换(包括指数变换、对数变换); 
  • 显示原图像直方图;将原图像直方图均衡化,显示处理后图像和处理后图像直方图;处理前后对比效果显示在一张图中
  • 对图像分别添加高斯噪声和椒盐噪声,并分别用均值滤波器、中值滤波器、高斯滤波器处理,并将处理结果显示在一张图中;
  • 分别采用robert和二阶算子提取图像边缘,并将处理结果显示在一张图中; 
  • 从频域对图像做平滑处理和提取边缘,并将处理结果显示在一张图中; 
  • 对原图做运动模糊,并进行图像复原处理,将原图、模糊图、恢复后的模糊图显示在一张结果图中; 
  • 对图像进行腐蚀、膨胀、开运算、闭运算处理,并将处理结果显示在一张图中; 
  • 主要要求:提取红苹果

建议方法:

  1. 将已知图像进行消噪处理
  2. 对彩色图像进行目标和背景分析
  3. 通过阈值法(检测红色)将图像进行分割
  4. 进行形态学处理,提取目标
  • 硬币检测及计数

建议方法:

  1. 图像分割;
  2. 边缘检测、滤波去噪;
  3. 连通区域检测,判断硬币个数;
  • 检测特定形状
  1. 检测矩形
  2. 检测圆形

二、设计思路

用GUIDE实现图像化交互界面

三、功能模块

1 图像导入 

1.1 算法原理

此模块采用Matlab中的uigetfile和fullfile函数实现图像导入

[FileName,PathName,FilterIndex]= = uigetfile(FilterSpec,DialogTitle,DefaultName)

FileName:返回的文件名

PathName:返回的文件的路径名

FilterIndex:选择的文件类型

FilterSpec:文件类型设置

DialogTitle:打开对话框的标题

DefaultName:默认指向的文件名

fullfile的用法如下:f = fullfile(pathname,filename)

1.2 算法实现(代码)

[file,path] = uigetfile('*.*','select a picture','multiselect','on','.\'); 
file_path=fullfile(path,file);
img=imread(file_path);
handles.img=img;
guidata(hObject, handles)
axes(handles.axes1);
imshow(img);
save('img.mat','img')

1.3 实验结果及对比分析

2 彩色图像灰度化

2.1 算法原理

此模块采用Matlab中的rgb2gray函数实现彩色图像灰度化

调用格式:I=rgb2gray(RGB)

  以R、G、B为轴建立空间直角坐标系,则RGB图的每个象素的颜色可以用该三维空间的一个点来表示,

而Gray图的每个象素的颜色可以用直线R=G=B上的一个点来表示。于是rgb转gray图的本质就是寻找一个三维空间到一维空间的映射,最容易想到的就是射影(即过rgb空间的一个点向直线R=G=B做垂线),

在Matlab中,有Gray = 0.29900 * R + 0.58700 * G + 0.11400 * B。

2.2 算法实现(代码)

function pushbutton9_Callback(hObject, eventdata, handles)
img=handles.img;
imgf=rgb2gray(img);
axes(handles.axes2);
handles.imgf=imgf;
guidata(hObject, handles)
imshow(imgf);

2.3 实验结果及对比分析

3 灰度图像二值化

3.1 算法原理

此模块采用Matlab中的imbinarize函数实现彩色图像灰度化,其参数必须为灰度图

调用格式:BW=imbinarize(I)

  通过用1s替换全局确定的阈值之上的所有值并将所有其他值设置为0s,从2D或3D灰度图像I创建二进制图像。 默认情况下,inbinarize使用Otsu方法,该方法选择阈值以最小化阈值黑白像素的类内方差。

3.2 算法实现(代码)

function pushbutton10_Callback(hObject, eventdata, handles)
img=handles.img;
if numel(img)>2
img = rgb2gray(img);
else
img = img;
end
imgf1=imbinarize(img);
axes(handles.axes2);
imshow(imgf1);

3.3 实验结果及对比分析

4 两幅图像叠加

4.1 算法原理

此模块采用Matlab中的imadd函数实现实现两幅图像相加

调用格式: C=imadd(A,B)

1)A、B均为图像,则要求B和A的尺寸相等;若B是一个标量,则C表示对图像A整体加上某个值(对小数部分取整)。

2)假如A和B对应运算和大于255,C仍取255,即截断处理;为避免截断,可以将C存储为uint16,即C=imadd(A,B,’uint16’)。

此函数将相应矩阵X中的元素与相应矩阵 Y 中的元素进行叠加,返回一个叠加结果作为输出数列 Z 中对应的元素。 X 和 Y 都是实数,且两者是大小相同,类型相同的非稀疏矩阵,或者 Y 是一个双精度标量。

4.2 算法实现(代码)

function pushbutton12_Callback(hObject, eventdata, handles)
img=handles.img;
img2=handles.img2;
img = imresize(img,[350 350]);
img2=imresize(img2,[350 350]);
result1= imadd(img,img2);%图像相加
axes(handles.axes2);
imshow(result1);
save('img2.mat','img2')

4.3 实验结果及对比分析

5 两幅图像相减

5.1 算法原理

此模块采用Matlab中的imsubtract函数实现图像相减

调用格式:C=imsubtract(A,B)

差值结果小于0的赋值为0,对A、B的要求同imadd相同。

该函数从数组 X 中的每个元素中减去数组 Y 中的对应元素,并在输出数组 Z 的对应元素中返回绝对差。

5.2 算法实现(代码)

function pushbutton13_Callback(hObject, eventdata, handles)
img=handles.img;
img2=handles.img2;
img = imresize(img,[350 350]);
img2=imresize(img2,[350 350]);
result2=imabsdiff(img,img2);
axes(handles.axes2);
imshow(result2);
save('result2.mat','result2');

5.3 实验结果及对比分析

6 图像的灰度化

6.1 算法原理

对数变换基于该表达式实现:g=c*log[1+(f,y)],其中,c是常数,f是浮点数,“+1”避免对0求对数。可对低灰度区作较大拉伸;高灰度区做压缩。

指数变换基于该表达式实现:g(x,y)=bc*[f(x,y)-a]-1,其中,a用于决定指数变换函数曲线的初始位置。可对高灰度区作较大拉伸;低灰度区做压缩。

6.2 算法实现(代码)

指数变换:

function pushbutton4_Callback(hObject, eventdata, handles)

img=handles.img;

fm=rgb2gray(img);

imgh= double(fm)/255;

c=255;

if(get(handles.number1,'value')==1)

m1=0.5;

elseif(get(handles.number1,'value')==2)

m1=3;

elseif(get(handles.number1,'value')==3)

m1=4;

elseif(get(handles.number1,'value')==4)

m1=5;

end

f1 = c/255*(imgh.^m1);

axes(handles.axes2);

imshow(f1);

save('f1.mat','f1');

对数变换:

function pushbutton5_Callback(hObject, eventdata, handles)

img=handles.img;

fm=rgb2gray(img);

Image=double(fm)/255;

if(get(handles.number2,'value')==1)

mh=7;

elseif(get(handles.number2,'value')==2)

mh=3;

elseif(get(handles.number2,'value')==3)

mh=2;

elseif(get(handles.number2,'value')==4)

mh=4;

elseif(get(handles.number2,'value')==5)

mh=5;

elseif(get(handles.number2,'value')==6)

mh=6;

end

h1 = log2(1+Image)/log2(mh);

axes(handles.axes2);

imshow(h1);

save('f1.mat','fm');

 6.3 实验结果及对比分析

7 直方图及直方图均衡化

7.1 算法原理

以从图像灰度直方图中提取信息为基础的灰度变换函数在增强、压缩、分割、描述等方面的图像处理中起重要作用,有时利用归一化的直方图是必要的。

工具箱中用于处理图像直方图的核心函数是imhist,基本语法如下:

h=imhist(f,b)

其中,f为输入图像,h为直方图,b是用来形成直方图的“统计堆栈”的数目,如果我们处理一幅uint8类的图像且设b=2,然后灰度范围会被分成两部分:0至127和128至255。所得到的直方图将有两个值:h(1)等于图像在[0,127]间隔内的像素数,h(2)等于图像在[128,255]间隔内的像素数。

假设灰度级为归一化在[0,1]范围内的连续量,让p(r rr)代表一副给定图像的灰度级的概率密度函数。假设我们对输入灰度进行下列变换,得到处理之后的灰度级s:

其中w是积分虚变量,前面的变换生成一幅图像,这幅图像的灰度级是等概率的。此外,灰度覆盖了整个[0,1]范围。

直方图均衡化由工具箱中的histeq函数实现,语法如下:

g=histeq(f,nlev)

其中,f为输入图像,nlev为输出图像设定的灰度级数。若nlev与L(输入图像中可能灰度级的总数)相等,则histeq直接执行变换函数

7.2 算法实现(代码)

% --- Executes on button press in pushbutton17.

function pushbutton17_Callback(hObject, eventdata, handles)

img=handles.img;

if numel(img)>2

fm = rgb2gray(img);

else

fm=img;

end

axes(handles.axes5);

imhist(fm,64)

save('fm','fm');



% hObject handle to pushbutton17 (see GCBO)

% eventdata reserved - to be defined in a future version of MATLAB

% handles structure with handles and user data (see GUIDATA)





% --- Executes on button press in pushbutton18.

function pushbutton18_Callback(hObject, eventdata, handles)

img=handles.img;

if numel(img)>2

fm = rgb2gray(img);

else

fm=img;

end

% 读入原图像

J=histeq(fm);

handles.J=J;

guidata(hObject, handles);

%对原图像进行直方图均衡化处理

axes(handles.axes6);

imhist(J,64)%将均衡化后图像的直方图显示为64级灰度

% hObject handle to pushbutton18 (see GCBO)

% eventdata reserved - to be defined in a future version of MATLAB

% handles structure with handles and user data (see GUIDATA)





% --- Executes on button press in pushbutton19.

function pushbutton19_Callback(hObject, eventdata, handles)

J=handles.J;

axes(handles.axes2);

imshow(J);

set(handles.change,'string')

% hObject handle to pushbutton19 (see GCBO)

% eventdata reserved - to be defined in a future version of MATLAB

% handles structure with handles and user data (see GUIDATA)

7.3 实验结果及对比分析

灰度级为64

8 噪声的添加与去除

8.1 算法原理

  • 椒盐噪声:

椒盐噪声(salt & pepper noise)是数字图像的一个常见噪声,所谓椒盐,椒就是黑,盐就是白,椒盐噪声就是在图像上随机出现黑色白色的像素。椒盐噪声是一种因为信号脉冲强度引起的噪声,产生该噪声的算法也比较简单。

椒盐噪声的概率密度函数为:

  • 高斯噪声:

高斯噪声是指它的概率密度函数服从高斯分布(即正态分布)的一类噪声

与椒盐噪声相似(Salt And Pepper Noise),高斯噪声(gauss noise)也是数字图像的一个常见噪声。

椒盐噪声是出现在随机位置、噪点深度基本固定的噪声,高斯噪声与其相反,是几乎每个点上都出现噪声、噪点深度随机的噪声。

高斯随机变量x的概率密度如下所示:

常见的滤波方式有均值滤波、中值滤波、高斯滤波等。

  • 均值滤波—mean_image:

均值滤波又称作邻域平均法,是典型的线性滤波算法,理想的均值滤波是用每个像素和它周围像素计算出来的平均值替换图像中每个像素。

从频率域观点来看均值滤波是一种低通滤波器(让图像的低频部分通过,通常弱化边缘,会得到比较平缓的图像),高频信号将会去掉,因此可以帮助消除图像尖锐噪声,实现图像平滑,模糊等功能。因为此方法不能很好地保护图像细节,在图像去噪的同时也破坏了图像的细节部分,从而使图像变得模糊。采样Kernel数据通常是3X3的矩阵,如下表示:

从左到右从上到下计算图像中的每个像素,最终得到处理后的图像。均值滤波可以加上两个参数,即迭代次数,Kernel数据大小。一个相同的Kernel,但是多次迭代就会效果越来越好。同样,迭代次数相同,Kernel矩阵越大,均值滤波的效果就越明显。

优势:消除尖锐噪声,实现图像平滑,模糊等功能。

  • 中值滤波—median_Image,适用于椒盐噪声:

中值滤波也是消除图像噪声最常见的手段之一,特别是消除椒盐噪声,中值滤波的效果要比均值滤波更好。它的基本原理是计算出数字图像中的一点的一个邻域中的各点值的中值(中间值),并使用该中值将将该点原值代替。可以理解为使用一个窗口沿图像移动,用窗口内所有象素灰度的中值来代替窗口中心位置的象素灰度。窗口根据需要定义,可以是3* 3,5 *5的方形、十字形或者圆形等。

  • 优势:消除椒盐噪声。

  • 高斯滤波—gauss_image,适用于高斯噪声

高斯滤波是一种线性平滑滤波,适用于消除高斯噪声,广泛应用于图像处理的减噪过程。通俗的讲,高斯滤波就是对整幅图像进行加权平均的过程,每一个像素点的值,都由其本身和邻域内的其他像素值经过加权平均后得到。可以理解为用一个模板(或称卷积、掩模)扫描图像中的每一个像素,用模板确定的邻域内像素的加权平均灰度值去替代模板中心像素点的值。

优势:消除高斯噪声。

8.2 算法实现(代码)

添加噪声:

function pushbutton20_Callback(hObject, eventdata, handles)

img=handles.img;

if numel(img)>2

img = rgb2gray(img);

else

img = img;

end



if (get(handles.zs,'value')==2)

fa= imnoise(img,'gauss',0.02);

elseif (get(handles.zs,'value')==1)

fa= imnoise(img,'salt & pepper',0.02);

end

axes(handles.axes8);

imshow(fa);

handles.fa=fa;

guidata(hObject, handles)

save('fa.mat','fa');

去除噪声:

function pushbutton21_Callback(hObject, eventdata, handles)

n=str2num(get(handles.ed,'string'));

fa=handles.fa;

if(get(handles.rb1,'value')==1)

M=medfilt2(fa,[n n]); % 中值滤波n×n模板

elseif(get(handles.rb2,'value')==1)

ave1=fspecial('average',n); % 产生5×5的均值模板

M=filter2(ave1,fa)/255; % 5×5均值滤波器

elseif(get(handles.rb3,'value')==1)

W = fspecial('gaussian',[n,n],1); % 高斯滤波器

M = imfilter(fa, W, 'replicate');

end

axes(handles.axes2);

imshow(M);

8.3 实验结果及对比分析

添加噪声:

去除噪声:

  • 椒盐噪声

中值滤波器 N=3

均值滤波器 N=3

高斯滤波器 N=3

  • 高斯噪声

中值滤波器 N=3

均值滤波器 N=3

高斯滤波器 N=3

9 边缘提取

9.1 算法原理

Roberts算子

在(i+1/2,j+1/2)处差分

转化为模板即为

Roberts算子是一种最简单的算子,是一种利用局部差分算子寻找边缘的算子。采用对角线方向相邻两象素之差近似梯度幅值检测边缘。检测垂直边缘的效果好于斜向边缘,定位精度高,对噪声敏感,无法抑制噪声的影响。

Roberts算子检测方法对具有陡峭的低噪声的图像处理效果较好,但是提取边缘的结果是边缘比较粗,因此边缘的定位不是很准确。

Sobel算子

Sobel算法是一个离散的一阶差分算子,用来计算图像亮度函数的一阶梯度之近似值。在图像的任何一点使用此算子,将会产生该点对应的梯度矢量或是其法矢量。

Prewitt算子

Prewitt算子是一种一阶微分算子的边缘检测,利用像素点上下、左右邻点的灰度差,在边缘处达到极值检测边缘,去掉部分伪边缘,对噪声具有平滑作用。

其原理是在图像空间利用两个方向模板与图像进行邻域卷积来完成的,这两个方向模板一个检测水平边缘,一个检测垂直边缘。

Prewitt算子检测方法对灰度渐变和噪声较多的图像处理效果较好。但边缘较宽,而且间断点多。

对数字图像f(x,y),Prewitt算子的定义如下:

G(i)={[f(i-1,j-1)+f(i-1,j)+f(i-1,j+1)]-[f(i+1,j-1)+f(i+1,j)+f(i+1,j+1)]}

G(j)={[f(i-1,j+1)+f(i,j+1)+f(i+1,j+1)]-[f(i-1,j-1)+f(i,j-1)+f(i+1,j-1)]}

则P(i,j)=max[G(i),G(j)]或 P(i,j)=G(i)+G(j)

9.2 算法实现(代码)

function pushbutton22_Callback(hObject, eventdata, handles)

img=handles.img;

if numel(img)>2

img = rgb2gray(img);

else

img = img;

end

if(get(handles.roberts,'value')==1)

bw= edge(img,'roberts');

elseif(get(handles.sobel,'value')==1)

bw= edge(img,'sobel') ;

elseif(get(handles.prewitt,'value')==1)

bw= edge(img,'prewitt') ;

elseif(get(handles.log,'value')==1)

bw= edge(img,'log') ;

end

axes(handles.axes2);

imshow(bw);

9.3 实验结果及对比分析

10 频域的平滑与锐化

10.1 算法原理

低通滤波器

低通滤波器的应用实例:模糊、平滑等

  • 理想低通滤波器

在以原点为圆心、D0为半径的园内,通过所有的频率,而在圆外截断所有的频率。(圆心的频率最低,为变换的直流(dc)分量)。理想低通滤波器的过渡非常急剧,会产生振铃现象。函数如下:

  • Butterworth低通滤波器

阶数越高,滤波器的过度越剧烈,振铃现象将越明显。函数表达式如下,其中n称为Butterworth低通滤波器的阶数

  • 高斯低通滤波器

过度特性非常平坦,因此不会产生振铃现象。函数表达式如下:

高通滤波器

  • 理想高通滤波器

作用:保留频谱图中圆外高频分量,截断频谱图中圆内低频分量

截止频率距原点的距离为 D0 的 IHPF 定义为:

其中D0为理想高通滤波器的截止频率,注意与理想高通滤波器的表达式区别在于将0和1交换而条件不变。

  • Butterworth高通滤波器

巴特沃斯高通滤波器的产生公式为:

其中D0为巴特沃斯高通滤波器的截止频率,注意与巴特沃斯低通滤波器的表达式区别在于将分母的D0和D(u,v)交换位置。

  • 高斯高通滤波器

高斯高通滤波器的产生公式为:

其中D0为高斯高通滤波器的截止频率,注意与高斯低通滤波器的表达式区别在于使用1减去表达式。

10.2 算法实现(代码)

  • 低通滤波器
% --- Executes on button press in pushbutton26.

function pushbutton26_Callback(hObject, eventdata, handles)

I = handles.img;

if numel(I)>2

I = rgb2gray(I);

else

I = I;

end

D0=str2num(get(handles.D0,'string'));

Ih = func_ihpf_l(I,D0);

axes(handles.axes2);

imshow(Ih );

% hObject handle to pushbutton26 (see GCBO)

% eventdata reserved - to be defined in a future version of MATLAB

% handles structure with handles and user data (see GUIDATA)





% --- Executes on button press in pushbutton27.

function pushbutton27_Callback(hObject, eventdata, handles)

I = handles.img;

if numel(I)>2

I = rgb2gray(I);

else

I = I;

end

D0=str2num(get(handles.D0,'string'));

Ih = func_bhpf_l(I,D0);

axes(handles.axes2);

imshow(Ih );

% hObject handle to pushbutton27 (see GCBO)

% eventdata reserved - to be defined in a future version of MATLAB

% handles structure with handles and user data (see GUIDATA)





% --- Executes on button press in pushbutton28.

function pushbutton28_Callback(hObject, eventdata, handles)

I = handles.img;

if numel(I)>2

I = rgb2gray(I);

else

I = I;

end

D0=str2num(get(handles.D0,'string'));

Ih = func_ghpf_l(I,D0);

axes(handles.axes2);

imshow(Ih );

% hObject handle to pushbutton28 (see GCBO)

% eventdata reserved - to be defined in a future version of MATLAB

% handles structure with handles and user data (see GUIDATA)
  • 理想低通滤波器
function gimage = func_ihpf_l(I,D0)

if numel(I)>2

I = rgb2gray(I);

else

I = I;

end%把原始图像转为灰度图像

I=im2double(I);%把原始图像的数据类型由uint8转化为double类型,防止出现数据截断

M=2*size(I,1); %滤波器行数

N=2*size(I,2); %滤波器列数

u=-M/2:(M/2-1);

v=-N/2:(N/2-1);

[U,V]=meshgrid(u,v);

D=sqrt(U.^2+V.^2);

H=double(D<=D0); %理想低通滤波器

J=fftshift(fft2(I, size(H, 1), size(H, 2))); %转换到频域并移到频谱的中间

K=J.*H; %滤波处理

gimage=ifft2(ifftshift(K)); %傅里叶反变换

gimage=gimage(1:size(I,1), 1:size(I, 2)); %滤波后图像

巴特沃斯低通滤波器
function gimage = func_bhpf_l(I,D0)

if numel(I)>2

I = rgb2gray(I);

else

I = I;

end%把原始图像转为灰度图像

I=im2double(I);%把原始图像的数据类型由uint8转化为double类型,防止出现数据截断

M=2*size(I,1); %滤波器行数 读入图像宽度和列数的2倍 因为需要进行隔行隔列处理

N=2*size(I,2); %滤波器列数

u=-M/2:(M/2-1);

v=-N/2:(N/2-1);

[U,V]=meshgrid(u,v);

D=sqrt(U.^2+V.^2);

n=6; %滤波器阶数,n越大滤波器形状越陡峭

H=1./(1+(D./D0).^(2*n)); %构造巴特沃斯低通滤波器

J=fftshift(fft2(I,size(H,1),size(H,2))); %转换到频域并移到频谱的中间

K=J.*H;%滤波处理

gimage=ifft2(ifftshift(K)); %傅立叶反变换

gimage=gimage(1:size(I,1),1:size(I,2)); %改变图像大小
  • 高斯低通滤波器
function gimage = func_ghpf_l(I,D0)

if numel(I)>2

I = rgb2gray(I);

else

I = I;

end%把原始图像转为灰度图像

I=im2double(I);%把原始图像的数据类型由uint8转化为double类型,防止出现数据截断

M=2*size(I,1); %滤波器行数

N=2*size(I,2); %滤波器列数

u=-M/2:(M/2-1);

v=-N/2:(N/2-1);

[U,V]=meshgrid(u,v);

D=sqrt(U.^2+V.^2);

H=exp(-0.5*(D.^2)/D0^2); %高斯低通滤波器

J=fftshift(fft2(I, size(H, 1), size(H, 2))); %转换到频域并移到频谱的中间

K=J.*H; %滤波处理

gimage=ifft2(ifftshift(K)); %傅里叶反变换

gimage=gimage(1:size(I,1), 1:size(I, 2)); %滤波后图像
  • 高通滤波
% --- Executes on button press in pushbutton23.

function pushbutton23_Callback(hObject, eventdata, handles)

I=handles.img;

D0=str2num(get(handles.D0,'string'));

Ie = func_ihpf(I,D0);

axes(handles.axes2);

imshow(Ie );



% hObject handle to pushbutton23 (see GCBO)

% eventdata reserved - to be defined in a future version of MATLAB

% handles structure with handles and user data (see GUIDATA)





% --- Executes on button press in pushbutton24.

function pushbutton24_Callback(hObject, eventdata, handles)

I=handles.img;



D0=str2num(get(handles.D0,'string'));

Ie = func_bhpf(I,D0);

axes(handles.axes2);

imshow(Ie );





% hObject handle to pushbutton24 (see GCBO)

% eventdata reserved - to be defined in a future version of MATLAB

% handles structure with handles and user data (see GUIDATA)





% --- Executes on button press in pushbutton25.

function pushbutton25_Callback(hObject, eventdata, handles)

I=handles.img;



D0=str2num(get(handles.D0,'string'));

Ie = func_ghpf(I,D0);

axes(handles.axes2);

imshow(Ie );

% hObject handle to pushbutton25 (see GCBO)

% eventdata reserved - to be defined in a future version of MATLAB

% handles structure with handles and user data (see GUIDATA)

  • 理想高通滤波器
function gimage = func_ihpf(I,D0)

if numel(I)>2

I = rgb2gray(I);

else

I = I;

end

I=im2double(I);%把原始图像的数据类型由uint8转化为double类型,防止出现数据截断

M=2*size(I,1); %滤波器行数

N=2*size(I,2); %滤波器列数

u=-M/2:(M/2-1);

v=-N/2:(N/2-1);

[U,V]=meshgrid(u,v);

D=sqrt(U.^2+V.^2);

H=double(D>D0); %理想高通滤波器

J=fftshift(fft2(I, size(H, 1), size(H, 2))); %转换到频域并移到频谱的中间

K=J.*H; %滤波处理

gimage=ifft2(ifftshift(K)); %傅里叶反变换

gimage=gimage(1:size(I,1), 1:size(I, 2)); %滤波后图像
  • 巴特沃斯高通滤波器
function gimage = func_bhpf(I,D0)

if numel(I)>2

I = rgb2gray(I);

else

I = I;

end%把原始图像转为灰度图像

I=im2double(I);%把原始图像的数据类型由uint8转化为double类型,防止出现数据截断

M=2*size(I,1); %滤波器行数

N=2*size(I,2); %滤波器列数

u=-M/2:(M/2-1);

v=-N/2:(N/2-1);

[U,V]=meshgrid(u,v);

D=sqrt(U.^2+V.^2);

n=6;%滤波器阶数

H=1./(1+(D0./D).^(2*n)); %构造巴特沃斯高通滤波器

J=fftshift(fft2(I,size(H,1),size(H,2))); %转换到频域并移到频谱的中间

K=J.*H;

gimage=ifft2(ifftshift(K)); %傅立叶反变换

gimage=gimage(1:size(I,1),1:size(I,2)); %改变图像大小

  • 高斯高通滤波器
    function gimage = func_ghpf(I,D0)
    
    if numel(I)>2
    
    I = rgb2gray(I);
    
    else
    
    I = I;
    
    end%把原始图像转为灰度图像
    
    I=im2double(I);%把原始图像的数据类型由uint8转化为double类型,防止出现数据截断
    
    M=2*size(I,1); %滤波器行数
    
    N=2*size(I,2); %滤波器列数
    
    u=-M/2:(M/2-1);
    
    v=-N/2:(N/2-1);
    
    [U,V]=meshgrid(u,v);
    
    D=sqrt(U.^2+V.^2);
    
    H=1-exp(-0.5*(D.^2)/D0^2); %高斯高通滤波器
    
    J=fftshift(fft2(I, size(H, 1), size(H, 2))); %转换到频域并移到频谱的中间
    
    K=J.*H; %滤波处理
    
    gimage=ifft2(ifftshift(K)); %傅里叶反变换
    
    gimage=gimage(1:size(I,1), 1:size(I, 2)); %滤波后图像

10.3 实验结果及对比分析

11 运动模糊及图像复原

11.1 算法原理

该模块所用的算法有:

  • fspecial()

定义:创建预定义的二维过滤器

形式:h = fspecial('motion',len,theta)

描述:h = fspecial('motion',len,theta),返回一个过滤器,使其在与图像卷积后近似相机的线性运动。len指定运动的长度,theta指定逆时针方向的运动角度(以度为单位)。过滤器将成为水平和垂直运动的矢量。默认的len是9,默认的theta是0,这对应于9个像素的水平运动。

  • imfilter()

定义:多维图像的N-D滤波

形式:B = imfilter(A,h,options,...)

描述:根据一个或多个指定选项执行多维筛选。其中本实验代码中Blurred1 = imfilter(imgrgb,PSF1,'circular','conv');指的是加入了运动模糊。

SNR-信噪比

定义:信号的平均功率和噪声的平均功率之比

形式:信噪比(dB)= 10 * log10(S/N) (dB), 单位(db)作为度量单位。

  • deconvwnr()

定义:基于维纳滤波的去模糊图像

形式:J = deconvwnr(I,psf,nsr);J = deconvwnr(I,psf,ncorr,icorr);J = deconvwnr(I,psf)

描述:其中J = deconvwnr(I,psf,nsr),使用维纳滤波算法对图像I进行解卷积,返回去模糊图像J。psf是对I进行卷积的点扩展函数(psf)。nsr是加性噪声的噪声与信号功率比。该算法在估计图像和真实图像之间的最小均方误差意义下是最优的。

11.2 算法实现(代码)

  • 运动模糊:
function pushbutton33_Callback(hObject, eventdata, handles)

img=handles.img;

M=str2num(get(handles.M,'string'));

N=str2num(get(handles.N,'string'));

PSF=fspecial ('motion',M,N);%运动模糊函数,运动位移是25像素,角度是11

Blurred=imfilter (img,PSF, 'conv' , 'circular') ;

handles.Blurred=Blurred;

handles.PSF=PSF;

guidata(hObject, handles)

axes(handles.axes9);

imshow(Blurred);
  • 维纳滤波复原图像
function pushbutton34_Callback(hObject, eventdata, handles)

PSF=handles.PSF;

Blurred = handles.Blurred;

WI1=deconvwnr(Blurred, PSF) ;%不带参数的维纳滤波(逆滤波)复原

axes(handles.axes2);

imshow(WI1);

11.3 实验结果及对比分析

12 图像的形态学运算

12.1 算法原理

在形态学运算中,图像中的每个像素都基于其邻域中其他像素的值进行调整。通过选择邻域的大小和形状,可以构造对输入图像中的特定形状敏感的形态学运算。

创建形态学结构元素:strel()

  1. SE = strel(nhood) 创建一个具有指定邻域 nhood 的平面结构元素。
  2. SE = strel('diamond', r) 创建一个菱形结构元素,其中 r 指定从结构元素原点到菱形各点的距离。
  3. SE = strel('disk', r, n) 创建一个盘形结构元素,其中 r 指定半径,n 指定用于逼近盘形的线条结构元素的数量。
  4. SE = strel('octagon', r) 创建一个八边形结构元素,其中 r 指定从结构元素原点到八边形边的距离,沿水平和垂直轴测量。r 必须为 3 的非负倍数。
  5. SE = strel('line', len, deg) 创建一个关于邻域中心对称的线性结构元素,长度约为 len,角度约为 deg。
  6. SE = strel('rectangle', [m n]) 创建一个大小为 [m n] 的矩形结构元素。
  7. SE = strel('square', w) 创建一个宽度为 w 个像素的正方形结构元素。
  8. SE = strel('cube', w) 创建一个宽度为 w 个像素的三维立方体结构元素。
  9. SE = strel('cuboid', [m n p]) 创建一个大小为 [m n p] 的三维立方体结构元素。
  10. SE = strel('sphere', r) 创建一个半径为 r 个像素的三维球面结构元素。
  • 腐蚀运算 imerode()

    如上图所示,设A,B均为正方形。B集合平移z单位后的集合在A集合的四角都有3/4的点不被A集合包含。则A必缩小至紫色阴影面积。称A被B腐蚀。

    J = imerode(I, SE) 使用结构元素 SE 腐蚀灰度、二值或压缩二值图像 I。

    J = imerode(I, nhood) 腐蚀图像 I,其中 nhood 是由指定结构元素邻域的 0 和 1 组成的矩阵。

    此语法等效于 imerode(I, strel(nhood))。

    J = imerode(___, packopt, m) 指定输入图像 I 是否为压缩二值图像。m 指定原始未压缩图像的行维度。

    J = imerode(___, shape) 指定输出图像的大小。

    腐蚀运算是一种消除边界点,使边界点向内部收缩的过程。因此,腐蚀运算常用来消除图像中一些小且无意义的物体;使用腐蚀运算消除图像的背景部分,也可以产生滤波器的效果。

  • 膨胀运算 imdilate()

    如上图所示,设A,B均为正方形,则其反射图形不变。B的反射集合A集合在A集合的四个角处都有3/4的点与A的交集为空,若要保证所有交集都不为空,则A必膨胀至蓝色阴影面积。称A被B膨胀。

    J = imdilate(I, SE) 使用结构元素 SE 膨胀灰度、二值或压缩二值图像 I。

    J = imdilate(I, nhood) 对图像 I 执行扩张运算,其中 nhood 是由 0 和 1 组成的矩阵,用于指定结构元素邻域。

    此语法等效于 imdilate(I, strel(nhood))。

    J = imdilate(___, packopt) 指定 I 是否为压缩二值图像。

    J = imdilate(___, shape) 指定输出图像的大小。

    膨胀运算是将与物体接触的所有背景合并到该物体中,使边界向外扩张的过程。因此,膨胀运算可以用来填补物体中的空洞及消除目标物体中的小颗粒噪声。在处理上面一张字迹不清的图片时,用膨胀运算填补字迹的空洞,从而使字迹更加清晰。

  • 开运算 imopen()

    J = imopen(I, SE) 使用结构元素 SE 对灰度或二值图像 I 执行形态学开运算。形态学开运算是先腐蚀后膨胀,这两种运算使用相同的结构元素。

     

    J = imopen(I, nhood) 对图像 I 执行开运算,其中 nhood 是由 0 和 1 组成的矩阵,用于指定结构元素邻域。

    此语法等效于 imopen(I,strel(nhood))。

    开运算对图像先腐蚀后膨胀。开运算去除了白点,能够除去孤立的小点,毛刺和粘连,而总的位置和形状不变。开运算是一个基于几何运算的滤波器。结构元素大小的不同将导致滤波效果的不同。不同的结构元素的选择导致了不同的分割,即提取出不同的特征。

  • 闭运算 imclose()

    J = imclose(I,SE) 使用结构元素 SE 对灰度或二值图像 I 执行形态学闭运算。形态学闭运算是先膨胀后腐蚀,这两种运算使用相同的结构元素。

    J = imclose(I,nhood) 对图像 I 执行闭运算,其中 nhood 是由指定结构元素邻域的 0 和 1 组成的矩阵。

    此语法等效于 imclose(I,strel(nhood))。

    闭运算对图像先膨胀后腐蚀。闭运算去除了黑点,能够填平目标物中的小孔,弥合小裂缝,而总的位置和形状不变。闭运算是通过填充图像的暗块来滤波图像的。结构元素大小的不同将导致滤波效果的不同。不同结构元素的选择导致了不同的弥合。

    12.2 算法实现(代码)

    % --- Executes on button press in pushbutton29.
    
    function pushbutton29_Callback(hObject, eventdata, handles)
    
    I=handles.img;
    
    level=graythresh(I);%得到合适的阈值
    
    bw = im2bw(I,level);%二值化
    
    if(get(handles.rb8,'value')==1)
    
    se=strel('square',3);%创建方形结构元素
    
    elseif(get(handles.rb9,'value')==1)
    
    se=strel('disk',3);
    
    elseif(get(handles.rb10,'value')==1)
    
    se=strel('diamond',3);%创建菱形结构元素
    
    end
    
    result=imerode(bw,se); %腐蚀运算
    
    axes(handles.axes2);
    
    imshow(result);
    
    
    
    % hObject handle to pushbutton29 (see GCBO)
    
    % eventdata reserved - to be defined in a future version of MATLAB
    
    % handles structure with handles and user data (see GUIDATA)
    
    
    
    
    
    % --- Executes on button press in pushbutton30.
    
    function pushbutton30_Callback(hObject, eventdata, handles)
    
    I=handles.img;
    
    level=graythresh(I);%得到合适的阈值
    
    bw = im2bw(I,level);%二值化
    
    if(get(handles.rb8,'value')==1)
    
    se=strel('square',3);%创建方形结构元素
    
    elseif(get(handles.rb9,'value')==1)
    
    se=strel('disk',3);
    
    elseif(get(handles.rb10,'value')==1)
    
    se=strel('diamond',3);%创建菱形结构元素
    
    end
    
    result=imdilate(bw,se); %膨胀运算
    
    axes(handles.axes2);
    
    imshow(result);
    
    % hObject handle to pushbutton30 (see GCBO)
    
    % eventdata reserved - to be defined in a future version of MATLAB
    
    % handles structure with handles and user data (see GUIDATA)
    
    
    
    
    
    % --- Executes on button press in pushbutton31.
    
    function pushbutton31_Callback(hObject, eventdata, handles)
    
    I=handles.img;
    
    level=graythresh(I);%得到合适的阈值
    
    bw = im2bw(I,level);%二值化
    
    if(get(handles.rb8,'value')==1)
    
    se=strel('square',3);%创建方形结构元素
    
    elseif(get(handles.rb9,'value')==1)
    
    se=strel('disk',3);
    
    elseif(get(handles.rb10,'value')==1)
    
    se=strel('diamond',3);%创建菱形结构元素
    
    end
    
    result=imdilate(imerode(bw,se),se);
    
    axes(handles.axes2);
    
    imshow(result);
    
    
    
    % hObject handle to pushbutton31 (see GCBO)
    
    % eventdata reserved - to be defined in a future version of MATLAB
    
    % handles structure with handles and user data (see GUIDATA)
    
    
    
    
    
    % --- Executes on button press in pushbutton32.
    
    function pushbutton32_Callback(hObject, eventdata, handles)
    
    I=handles.img;
    
    level=graythresh(I);%得到合适的阈值
    
    bw = im2bw(I,level);%二值化
    
    if(get(handles.rb8,'value')==1)
    
    se=strel('square',3);%创建方形结构元素
    
    elseif(get(handles.rb9,'value')==1)
    
    se=strel('disk',3);
    
    elseif(get(handles.rb10,'value')==1)
    
    se=strel('diamond',3);%创建菱形结构元素
    
    end
    
    result=imerode(imdilate(bw,se),se);
    
    axes(handles.axes2);
    
    imshow(result);
    
    % hObject handle to pushbutton32 (see GCBO)
    
    % eventdata reserved - to be defined in a future version of MATLAB
    
    % handles structure with handles and user data (see GUIDATA)

    12.3 实验结果及对比分析

13 提取红苹果

13.1 算法原理

此模块采用基于RGB分量分割使用灰度整合二值化方法得到二值化后的图像然后颜色叠加部分采用了这个链接中的方法,将得到的二值图像分别和原图提取出来的RGB分量相乘。在灰度处理的时候添加填充洞和删掉小块噪点的函数,使图像更加完整

13.2 算法实现(代码)

% --- Executes on button press in pushbutton35.

function pushbutton35_Callback(hObject, eventdata, handles)

pic1=handles.img;

%分别提取RGB三个通道(也就是三个二维矩阵)

R=pic1(:,:,1);

G=pic1(:,:,2);

B=pic1(:,:,3);

%获取图像的矩阵

[y,x,z]=size(pic1);

%使用灰度整合二值化方法

%循环每个像素

for i=1:x

for j=1:y

%改变灰度值,系数可以自己调整

pic2(j,i)=(1*R(j,i)-0.3*G(j,i)-0.3*B(j,i));

end

end

t=graythresh(pic2); %确定二值化阈值

pic3=im2bw(pic2,t); %二值化

pic3=imfill(pic3,'holes'); %填充洞

pic3=bwareaopen(pic3,10); %删掉一些小块噪点

%由于二值图元素的类型都是 logical型(逻辑型),在进行运算处理时不符合要求,所以转为 uint8

a1=im2uint8(pic3)/255;

R1=R.*a1; %各个通道的矩阵乘以二值图,中心的蝴蝶矩阵数值不变,背景变为0

G1=G.*a1;

B1=B.*a1;

b1(:,:,1)=R1; %三个通道叠加,组成一个三维的RGB图

b1(:,:,2)=G1;

b1(:,:,3)=B1;

%显示结果环节

axes(handles.axes2);

imshow(b1);

% hObject handle to pushbutton35 (see GCBO)

% eventdata reserved - to be defined in a future version of MATLAB

% handles structure with handles and user data (see GUIDATA)

13.3 实验结果及对比分析

14 硬币的检测与计数

14.1 算法原理

此模块采用Matlab中的bwlabel函数实现二值图像中连通域的个数的检测,从而检测硬币的个数

调用格式:L = bwlabel(BW,n)

返回一个和BW大小相同的L矩阵,包含了标记了BW中每个连通区域的类别标签,这些标签的值为1、2、num(连通区域的个数)。n的值为4或8,表示是按4连通寻找区域,还是8连通寻找,默认为8。

[L,num] = bwlabel(BW,n)这里num返回的就是BW中连通区域的个数。

14.2 算法实现(代码)

% --- Executes on button press in pushbutton36.

function pushbutton36_Callback(hObject, eventdata, handles)

Image=handles.img;



BW=im2bw(Image);

SE=strel('square',6);



result1=imopen(imclose(BW,SE),SE); %先闭后开



[L, NUM] = bwlabel(result1, 4) %检测二值图像中连通域的个数

set(handles.numberf,'string',NUM);

%[L, NUM] = bwlabel(BW, N)

% BW 为输入二值化图像;

% N 可取值为4或8表示连接四连通或八连通区域;

% NUM 为找到的连通区域数目;

% L 为输出图像矩阵,其元素值为整数,背景被标记为0,第一个连通区域被标记为1,第二个连通区域被标记为2,依此类推.所以你不明白的1,2,3即为第1,2,3个连通区域的标记

%S=sprintf('检测到的硬币个数为:%d',NUM);msgbox(S);%弹窗显示运行结果

% hObject handle to pushbutton36 (see GCBO)

% eventdata reserved - to be defined in a future version of MATLAB

% handles structure with handles and user data (see GUIDATA)

14.3 实验结果及对比分析

15 检测矩形与圆形

15.1 算法原理

  • 矩形检测:

从理论上看,矩形连通区域与其最小边界矩形的像素比是1,所以可自定义设置阈值大于0.95判断。

  • 圆形检测:

从理论上看,设圆形半径为R,最小边界矩形即正方形边长为2R,圆形连通区域与其最小边界矩形的面积比

所以可自定义设置阈值介于[ 0.76 , 0.80 ] [0.76,0.80][0.76,0.80]判断。

15.2 算法实现(代码)

% --- Executes on button press in pushbutton38.

function pushbutton38_Callback(hObject, eventdata, handles)

pic=handles.img;

gray_pic = rgb2gray(pic);

binary_img=1-im2bw(gray_pic,0.73); %灰度图转换成二值图像,直接进行灰度反转,让图形区域置1

for i=202:265

binary_img(188,i)=1;

end

fill_hole=imfill(binary_img,'holes'); %区域填充

fill_hole=bwareaopen(fill_hole,10);

[B,L]=bwboundaries(fill_hole,'noholes');



out_result=regionprops(fill_hole,'Extent','Centroid','boundingbox'); %Extent:各连通区域像素点与最小边界像素点比值

centroids = cat(1, out_result.Centroid); %各连通区域质心

draw_rect=cat(1,out_result.BoundingBox); %各连通区域最小边界矩形



axes(handles.axes2)

imshow(fill_hole,[]);

hold on;

for i=1:size(out_result)

rectangle('position',draw_rect(i,:),'EdgeColor','y','LineWidth',2); %绘出各连通区域最小边界矩形

if out_result(i).Extent>0.95

text(centroids(i,1)-20, centroids(i,2)-10,'矩形','Color','b','FontSize',9);

text(centroids(i,1)-32, centroids(i,2)+10,num2str(out_result(i).Extent),'Color','b','FontSize',8);

elseif out_result(i).Extent>0.76&&out_result(i).Extent<0.80

text(centroids(i,1)-20, centroids(i,2)-10,'圆形','Color','b','FontSize',9);

text(centroids(i,1)-32, centroids(i,2)+10,num2str(out_result(i).Extent/(pi/4)),'Color','b','FontSize',8);

end 

end

hold on;

for j=1:length(B)

boundary=B{j};

plot(boundary(:,2),boundary(:,1),'r','LineWidth',2);

end

hold off;

% hObject handle to pushbutton38 (see GCBO)

% eventdata reserved - to be defined in a future version of MATLAB

% handles structure with handles and user data (see GUIDATA)

15.3 实验结果及对比分析

16 实现图形化界面

16.1 算法原理

托取控件到界面合适的位置,完成GUI界面设计后,右键点击用于实现功能的控件写回调方法,通过handles.xx获取控件,通过get(handles.xx,’string’)获取用户输入内容,通过set(handles.xx,’string’)展示图像处理结果以实现交互

16.2 实现效果

其余略

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐