【数字图像处理实验】中值滤波、均值滤波、灰度图像的锐化处理(包括Sobel、Prewitt、Roberts、Laplace、Canny边缘检测)(MATLAB实现)


文中附上的代码可能有缺失,建议通过该 GitHub仓库访问代码。

1 原理

1.1 中值滤波

主要用来处理椒盐噪声。椒盐噪声的出现使得该点像素比周围的像素亮(暗)很多,而如果在某个模板中对像素由小到大进行重新排列,那么最亮的或者最暗的点一定被排在两侧。这时取模板中排在中间位置上的像素的灰度值替代待处理像素的值,就可以达到滤除噪声的目的。

  1. 将模板中心与像素位置重合
  2. 读取模板下各对应像素的灰度值
  3. 将这些像素从小到大排成1列
  4. 找出这些值里排在中间的1个
  5. 将这个中间值赋给模板中心位置像素。

1.2 均值滤波

采用邻域平均法。基本思想是用几个像素灰度的平均值来代替每个像素的灰度。如使用一个3*3大小的模板对图像进行滤波,每次移动模板后,对模板范围内的所有像素灰度值相加再除以系数9,四舍五入后作为模板中心像素的灰度值。

1.3 图像锐化

图像锐化的目的是为了突出图像的边缘信息,加强图像的轮廓特征,便于人眼或者机器的识别。图像中边缘和轮廓往往出现于图像中灰度图片的地方,而检查这些图片可以用微分实现,因而图像锐化主要是通过微分方法进行的。
由于处理的对象是数字图像,其像素是离散的,对微分形式进行一些近似处理,得到离散的模板矩阵,称为算子。常见的算子诸如Laplacians、Roberts、Sobel等。用这些算子作为模板对图像进行处理,就能得到图像的轮廓图。将轮廓图与原图像相加即可得到原图像的锐化结果。

1.4 边缘检测

在图像锐化得到的轮廓图的基础上,根据轮廓图的灰度直方图设立阈值(一般在两峰一谷之间),对其进行二值化处理即可。

2 实现源代码(MATLAB)

2.1 中值滤波

function res = medianfilter(mat, width, height)
% res = medianfilter(img, width, height)
% -- res        the result of the median filter process
% -- img        the input image matrix(should be 2 dimensions)
% -- width      the width of template
% -- height     the height of template
% e.g.:
%   filename='noise.jpg';
%   img=imread(filename);
%   width=3;height=3;
%   res = medianfilter(img, width, height);
%   imshow(res);
%   mkdir('results/medianfilter');
%   imwrite(res,['./results/medianfilter/',filename]);
 
res=im2uint8(zeros(size(mat)));
[rows,cols]=size(mat);
 
for i = 1:(rows-height + 1)
    for j = 1:(cols-width + 1)
        temp = mat(i:i+height-1, j:j+width-1);
        temp = sort(temp(:));
        res((i+i+height-1)/2, (j+j+width-1)/2) = temp((length(temp)+1)/2);
    end
end

2.2 均值滤波

function res = meanfilter(mat, width, height)
% res = medianfilter(img, width, height)
% -- res        the result of the median filter process
% -- img        the input image matrix(should be 2 dimensions)
% -- width      the width of template
% -- height     the height of template
% e.g.:
%   filename='noise.jpg';
%   img=imread(filename);
%   width=3;height=3;
%   res = meanfilter(img, width, height);
%   imshow(res);
%   mkdir('results/meanfilter');
%   imwrite(res,['./results/meanfilter/',filename]);
 
res=im2uint8(zeros(size(mat)));
[rows,cols]=size(mat);
 
for i = 1:(rows-height + 1)
    for j = 1:(cols-width + 1)
        temp = mat(i:i+height-1, j:j+width-1);
        res((i+i+height-1)/2, (j+j+width-1)/2) = round(mean(temp(:)));
    end
end

2.3 锐化处理

2.3.0 说明

在分别实现使用Sobel、Prewitt、Roberts、Laplace算子的滤波函数后,希望实现一个“万能滤波函数”。
搜索得知MATLAB内置的滤波函数为imfilter,支持输入图像、模板等参数,输出滤波后结果。其对“最外面一圈像素”的处理方式是在最外层“加一圈0像素”,并对全图像进行处理。
仿照其功能实现myfilter函数,代码如下:

function res=myfilter(I,H)
% function res=myfilter(I,H)
% -- res    the result of the filter process
% -- I      the input image
% -- H      the input template matrix(should be 2 dimensions)
% e.g.:
%   filename='锐化及边缘检测用途.jpg';
%   I=imread(filename);
%   H=[1,1,1;1,-8,1;1,1,1];
%   res=myfilter(I,H);
%   imshow(res);
%   mkdir('results/myfilter');
%   imwrite(res,['./results/myfilter/',filename]);
I=im2uint8(I);
H=int16(H);
[rows,cols,channels]=size(I);
res=uint8(zeros(rows,cols,channels));
[height,width]=size(H);
hh=(height+1)/2;
hw=(width+1)/2;
for k=1:channels
    chan=int16(zeros(rows+hh,cols+hw));
    chan(hh:rows+hh-1,hw:cols+hw-1)=I(:,:,k);
    for i=1:rows
        for j=1:cols
            temp=chan(i:i+hh,j:j+hw);
            res(i,j,k)=sum(sum(H.*temp));
        end
    end
end

通过如下代码实现两者效果对比:

I=imread('锐化及边缘检测用途.jpg');
H=[1,1,1;1,-8,1;1,1,1];
imres=imfilter(I,H);
myres=myfilter(I,H);
cmp=(imres==myres);
length(cmp(cmp==0))

得到结果为:

ans =

     0

于是复用myfilter函数,以另一种方式实现了Sobel、Prewitt、Roberts、Laplace算子滤波函数,在原命名后添加了“2”以区分。
需要注意的是,myfilter最多算是imfilter的一个弱化版本,运行速度远不及imfilter。另外,经查阅,imfilter默认使用的是’corr’参数,而不是’conv’,即默认使用的不是卷积运算。但本实验遇到的算子(Sobel、Prewitt、Laplace)模板都可以认为是对称的,实验得知本实验中对这三类算子在’conv’和’corr’两种参数下结果是完全一致的,故myfilter也没有提供诸如’corr’和’conv’之类参数的支持(即不支持模板矩阵不对称的卷积运算,仅支持相关运算)。

2.3.1 Laplace算子

采用的laplacian operator为[1,1,1;1,-8,1;1,1,1],故若要得到锐化图像,应该使用原图像减去该函数计算结果再输出。

function laplacian=laplacianfilter(image)
% function laplacian=laplacianfilter(image)
% -- laplacian      the result of the laplacian operator filter process
% -- image          the input image
% e.g.:
%   filename='锐化及边缘检测用途.jpg';
%   img=imread(filename);
%   res=laplacianfilter(img);
%   imshow(res);
%   mkdir('results/laplacianfilter');
%   imwrite(res,['./results/laplacianfilter/',filename]);
 
image=im2uint8(image);
[rows,cols,channels]=size(image);
laplacian=uint8(zeros(rows,cols,channels));
 
for k=1:channels
    chan=int16(zeros(rows+2,cols+2));
    chan(2:rows+1,2:cols+1)=image(:,:,k);
    for i=1:rows
        for j=1:cols
            temp=chan(i:i+2, j:j+2);
            laplacian(i,j,k)=sum(temp(:))-9*chan(i+1,j+1);
        end
    end
end

复用myfilter函数实现:

function laplacian=laplacianfilter2(image)
% function laplacian=laplacianfilter2(image)
% -- laplacian      the result of the laplacian operator filter process
% -- image          the input image
% e.g.:
%   filename='锐化及边缘检测用途.jpg';
%   img=imread(filename);
%   res=laplacianfilter2(img);
%   imshow(res);
%   mkdir('results/laplacianfilter');
%   imwrite(res,['./results/laplacianfilter/',filename]);
laplacianoperator=[1,1,1;1,-8,1;1,1,1];
laplacian=myfilter(image,laplacianoperator);

2.3.2 Sobel算子

function sobel=sobelfilter(image)
% function sobel=sobelfilter(image)
% -- sobel          the result of the sobel operator filter process
% -- image          the input image
% e.g.:
%   filename='锐化及边缘检测用途.jpg';
%   img=imread(filename);
%   res=sobelfilter(img);
%   imshow(res);
%   mkdir('results/sobelfilter');
%   imwrite(res,['./results/sobelfilter/',filename]);
sobeloperator1=int16([-1,0,1;-2,0,2;-1,0,1]);
sobeloperator2=int16([-1,-2,-1;0,0,0;1,2,1]);
image=im2uint8(image);
[rows,cols,channels]=size(image);
sobel1=uint8(zeros(rows,cols,channels));
sobel2=uint8(zeros(rows,cols,channels));
 
for k=1:channels
    chan=int16(zeros(rows+2,cols+2));
    chan(2:rows+1,2:cols+1)=image(:,:,k);
    for i=1:rows
        for j=1:cols
            temp=chan(i:i+2,j:j+2);
            sobel1(i,j,k)=sum(sum(sobeloperator1.*temp));
            sobel2(i,j,k)=sum(sum(sobeloperator2.*temp));
        end
    end
end
sobel=abs(sobel1)+abs(sobel2);

复用myfilter函数实现:

function sobel=sobelfilter2(image)
% function sobel=sobelfilter2(image)
% -- sobel          the result of the sobel operator filter process
% -- image          the input image
% e.g.:
%   filename='锐化及边缘检测用途.jpg';
%   img=imread(filename);
%   res=sobelfilter2(img);
%   imshow(res);
%   mkdir('results/sobelfilter');
%   imwrite(res,['./results/sobelfilter/',filename]);
sobeloperator1=[-1,0,1;-2,0,2;-1,0,1];
sobeloperator2=[-1,-2,-1;0,0,0;1,2,1];
sobel=myfilter(image,sobeloperator1)+myfilter(image,sobeloperator2);

2.3.3 Prewitt算子

function prewitt=prewittfilter(image)
% function prewitt=prewittfilter(image)
% -- prewitt        the result of the prewitt operator filter process
% -- image          the input image
% e.g.:
%   filename='锐化及边缘检测用途.jpg';
%   img=imread(filename);
%   res=prewittfilter(img);
%   imshow(res);
%   mkdir('results/prewittfilter');
%   imwrite(res,['./results/prewittfilter/',filename]);
image=im2uint8(image);
[rows,cols,channels]=size(image);
prewitt1=uint8(zeros(rows,cols,channels));
prewitt2=uint8(zeros(rows,cols,channels));
for k=1:channels
    chan=int16(zeros(rows+2,cols+2));
    chan(2:rows+1,2:cols+1)=image(:,:,k);
    for i=1:rows
        for j=1:cols
            temp=chan(i+2,j:j+2)-chan(i,j:j+2);
            prewitt1(i,j,k)=sum(temp(:));
            temp=chan(i:i+2,j+2)-chan(i:i+2,j);
            prewitt2(i,j,k)=sum(temp(:));
        end
    end
end
 
prewitt=prewitt1+prewitt2;

复用myfilter函数实现:

function prewitt=prewittfilter2(image)
% function prewitt=prewittfilter2(image)
% -- prewitt        the result of the prewitt operator filter process
% -- image          the input image
% e.g.:
%   filename='锐化及边缘检测用途.jpg';
%   img=imread(filename);
%   res=prewittfilter2(img);
%   imshow(res);
%   mkdir('results/prewittfilter');
%   imwrite(res,['./results/prewittfilter/',filename]);
prewittoperator1=[-1,-1,-1;0,0,0;1,1,1];
prewittoperator2=[-1,0,1;-1,0,1;-1,0,1];
prewitt=myfilter(image,prewittoperator1)+myfilter(image,prewittoperator2);

2.3.4 Roberts算子

为方便计算,将Roberts算子修改为3*3矩阵,复用myfilter函数实现:

function roberts=robertsfilter2(image)
% function roberts=robertsfilter2(image)
% -- roberts        the result of the laplacian operator filter process
% -- image          the input image
% e.g.:
%   filename='锐化及边缘检测用途.jpg';
%   img=imread(filename);
%   res=robertsfilter2(img);
%   imshow(res);
%   mkdir('results/robertsfilter2');
%   imwrite(res,['./results/robertsfilter2/',filename]);
robertsoperator1=[0,0,0;0,-1,0;0,0,1];
robertsoperator2=[0,0,0;0,0,-1;0,1,0];
roberts=myfilter(image,robertsoperator1)+myfilter(image,robertsoperator2);

2.4 边缘检测

同样地,参考MATLAB内置边缘检测函数edge实现了其一个简化版本myedge:支持直接输入模板矩阵,或者输入字符串以调用对应模板矩阵;没有自动阈值选择,需要手动输入)。代码如下:

function res=myedge(img,operator,threshold)
% function res=myedge(img,operator,threshold)
% -- res        the edge result of the input image
% -- image      the input image
% -- operator   the input operator(should be 2 dimensional odd-order matrix) or string like 'laplacian'/'sobel'/'prewitt'/'roberts'
% -- threshold  threshold to decide whther a pixel on the edge should be black or white 
% e.g.:
%   filename='锐化及边缘检测用途.jpg';
%   img=imread(filename);
%   operator='laplacian';
%   threshold=233;
%   res=myedge(img,operator,threshold);
%   imshow(res);
%   mkdir(['results/myedge/',operator]);
%   imwrite(res,['./results/myedge/',operator,'/',filename]);
if ischar(operator)
    switch operator
        case 'laplacian'
            res=laplacianfilter2(img);
        case 'sobel'
            res=sobelfilter2(img);
        case 'prewitt'
            res=prewittfilter2(img);
        case 'roberts'
            res=robertsfilter2(img);
    end
else
    res=myfilter(img,operator);
end
res(res<threshold)=0;res(res>=threshold)=255;

3 实验结果

3.1 中值滤波(使用3*3大小模板)

在这里插入图片描述在这里插入图片描述

编写了通用函数,可以在输入参数中指定模板大小。

3.2 均值滤波(使用3*3大小模板)

在这里插入图片描述在这里插入图片描述

编写了通用函数,可以在输入参数中指定模板大小。

3.3 锐化处理(注:锐化效果未叠加到原图,展示图为轮廓图)

3.3.0原图

在这里插入图片描述

3.3.1 Laplace算子

在这里插入图片描述

3.3.2 Sobel算子

在这里插入图片描述

3.3.3 Prewitt算子

在这里插入图片描述

3.3.4 Roberts算子

在这里插入图片描述

3.4 边缘检测

以laplacian operator为模板矩阵,阈值为233。其余结果类似,可参照help myedge中的例子,调用myedge函数生成。
在这里插入图片描述

注:遇到的一个问题是,边缘检测应当是只有0和255两种灰度的图像,在MATLAB中生成以后使用imshow查看没有问题,但保存为.jpg格式后出现了其他灰色。再次读取该.jpg图片,数值上与原来MATLAB生成图像并不一致,猜测可能是压缩编码为.jpg格式时出现了损失。

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值