图像滤波:即在尽量保留图像细节特征的条件下对目标图像的噪声进行抑制,是图像预处理中不可缺少的操作,其处理效果的好坏将直接影响到后续图像处理和分析的有效性和可靠性。消除图像中的噪声成分叫作图像的平滑化或滤波操作。信号或图像的能量大部分集中在幅度谱的低频和中频段是很常见的,而在较高频段,感兴趣的信息经常被噪声淹没。因此一个能降低高频成分幅度的滤波器就能够减弱噪声的影响。
图像滤波的目的有两个:一是抽出对象的特征作为图像识别的特征模式;另一个是为适应图像处理的要求,消除图像数字化时所混入的噪声。
而对滤波处理的要求也有两条:一是不能损坏图像的轮廓及边缘等重要信息;二是使图像清晰视觉效果好。
关于滤波器,一种形象的比喻法是:我们可以把滤波器想象成一个包含加权系数的窗口,当使用这个滤波器平滑处理图像时,就把这个窗口放到图像之上,透过这个窗口来看我们得到的图像。举一个滤波在我们生活中的应用:美颜的磨皮功能。如果将我们脸上坑坑洼洼比作是噪声的话,那么滤波算法就是来取出这些噪声,使我们自拍的皮肤看起来很光滑。
中值滤波是一种典型的非线性滤波,是基于排序统计理论的一种能够有效抑制噪声的非线性信号处理技术,基本思想是用像素点邻域灰度值的中值来代替该像素点的灰度值,让周围的像素值接近真实的值从而消除孤立的噪声点。该方法在取出脉冲噪声、椒盐噪声的同时能保留图像的边缘细节。这些优良特性是线性滤波所不具备的。中值滤波首先也得生成一个滤波模板,将该模板内的各像素值进行排序,生成单调上升或单调下降的二维数据序列,二维中值滤波输出为
g(x, y)=medf{f(x-k, y-1),(k, l∈w)}
其中f(x,y)和g(x,y)分别是原图像和处理后图像, w为输入的二维模板,能够在整幅图像上滑动,通常尺寸为33或55区域,也可以是不同的形状如线状、圆形、十字形、圆环形等。通过从图像中的二维模板取出奇数个数据进行排序,用排序后的中值取代要处理的数据即可。
下图为中值滤波示意图:
四邻域八邻域
均值的原理是,一个规定的邻域内,所有像素的平局值作为最终计算的结果,每个像素的权值相同,为总像素的倒数。均值平滑都是线性的,一旦参数给定,模板就确定下来,不会因为位置和像素分布不同而改变,而线性模板的基本运算是卷积。
边缘检测是图像处理和计算机视觉中的基本问题,边缘检测的目的是标识数字图像中亮度变化明显的点。图像属性中的显著变化通常反映了属性的重要事件和变化。这些包括:深度上的不连续、表面方向不连续、物质属性变化和场景照明变化。 边缘检测是图像处理和计算机视觉中,尤其是特征提取中的一个研究领域。图像边缘检测大幅度地减少了数据量,并且剔除了可以认为不相关的信息,保留了图像重要的结构属性。有许多方法用于边缘检测,它们的绝大部分可以划分为两类:基于查找一类和基于零穿越的一类。基于查找的方法通过寻找图像一阶导数中的最大和最小值来检测边界,通常是将边界定位在梯度最大的方向。基于零穿越的方法通过寻找图像二阶导数零穿越来寻找边界,通常是Laplacian过零点或者非线性差分表示的过零点。
人类视觉系统认识目标的过程分为两步:首先,把图像边缘与背景分离出来;然后,才能知觉到图像的细节,辨认出图像的轮廓。计算机视觉正是模仿人类视觉的这个过程。因此在检测物体边缘时,先对其轮廓点进行粗略检测,然后通过链接规则把原来检测到的轮廓点连接起来,同时也检测和连接遗漏的边界点及去除虚假的边界点。图像的边缘是图像的重要特征,是计算机视觉、模式识别等的基础,因此边缘检测是图象处理中一个重要的环节。然而,边缘检测又是图象处理中的一个难题,由于实际景物图像的边缘往往是各种类型的边缘及它们模糊化后结果的组合,且实际图像信号存在着噪声。噪声和边缘都属于高频信号,很难用频带做取舍。这就需要边缘检测来进行解决的问题了。边缘检测的基本方法有很多:一阶的有Laplace算子,Roberts算子,Prewitt算子,Sobel算子,Canny算子等。
Laplace算子是最简单的各向同性微分算子。一个二维图像函数f(x,y) f(x, y)f(x,y) 定义为:
Roberts算子是一种利用局部差分算子寻找边缘的算子,它有下式给出:
其中f(x,y)、f(x+1,y+1)、f(x,y+1)、f(x+1,y) 分别为4领域的坐标,且是具有整数像素坐标的输人图像;其中的平方根运算使得该处理类似于人类视觉系统中发生的过程。Roberts算子是2X2算子模板。图1所示的2个卷积核形成了Roberts算子。图象中的每一个点都用这2个核做卷积。
Sobel算子是一种一阶微分算子,它利用像素邻近区域的梯度值来计算1个像素的梯度,然后根据一定的绝对值来取舍。它由下式给出:
Sobel算子是33算子模板。图2所示的2个卷积核dx 、 dy形成Sobel算子。一个核对通常的垂直边缘响应最大,而另一个核对水平边缘响应最大。2个卷积的最大值作为该点的输出值。运算结果是一幅边缘幅度图像。
Prewitt算子由下式给出:
Prewitt算子是33算子模板。图3所示的2个卷积核dx ,不要形成了Prewitt算子。与Sobel算子的方法一样,图像中的每个点都用这2个核进行卷积,取最大值作为输出值。Prewitt算子也产生一幅边缘幅度图像。
Canny算子是是一阶算子。其方法的实质是用1个准高斯函数作平滑运算fs=f(x,y)G(x,y),然后以带方向的一阶微分算子定位导数最大值。
平滑后fs(x,y)的梯度可以使用22的一阶有限差分近似式:
P[i,j]≈(fs[i,j+1]-fs[i,j]+fs[i+1,j+1]-fs[i+1,j])/2
Q[i,j]≈(fs[i,j]-fs[i+1,j]+fs[i,j+1]-fs[i+1,j+1])/2
在这个2x2正方形内求有限差分的均值,便于在图像中的同一点计算二和y的偏导数梯度。幅值和方向角可用直角坐标到极坐标的坐标转化来计算:
M[i,j]反映了图象的边缘强度;反映了边缘的方向。使得M}i,j}取得局部最大值的方向角,就反映了边缘的方向。
Canny算子也可用高斯函数的梯度来近似,在理论上很接近4个指数函数的线性组合形成的最佳边缘算子。在实际工作应用中编程较为复杂且运算较慢。
% 灰度图像中值滤波平滑处理
function result = median_filtering(image, width, leng)
result = im2uint8(zeros(size(image)));
[rows,cols] = size(image); % 图像行列数
temp = im2uint8(zeros([rows+2,cols+2]));
temp(2:rows+1,2:cols+1) = image;
for i = 1:(rows + 2 - leng + 1)
for j = 1:(cols + 2 - width + 1)
data = temp(i:i + leng - 1, j:j + width - 1); % 取3*3矩阵
data = sort(data(:)); % 返回排序结果
result(i, j) = data((length(data)+1)/2);
end % 赋值
end
% image = imread('noise.jpg');
% width=3;leng=3;
% result = median_filtering(image, width, leng);
% imshow(result)
% 灰度图像均值滤波平滑处理
function result = average_filtering(image, width, leng)
result = im2uint8(zeros(size(image)));
[rows,cols] = size(image); % 图像行列数
temp = im2uint8(zeros([rows+2,cols+2]));
temp(2:rows+1,2:cols+1) = image;
for i = 1:(rows + 2 - leng + 1)
for j = 1:(cols + 2 - width + 1)
data = temp(i:i + leng - 1, j:j + width - 1); % 取3*3矩阵
average = mean(data(:)); % 返回排序结果
result(i, j) = average; % 赋值
end
end
% image = imread('noise.jpg');
% width=3;leng=3;
% result = average_filtering(image, width, leng);
% imshow(result)
% 灰度图像Laplace锐化处理
function laplaceion = laplace(image,threshold)
image = double(image);
[rows,cols,n] = size(image); % 图像行列数
temp1 = int16(zeros([rows+2,cols+2]));
temp2 = int16(zeros([rows+2,cols+2]));
temp3 = int16(zeros([rows+2,cols+2]));
temp1(2:rows+1,2:cols+1) = image(:, :, 1);
temp2(2:rows+1,2:cols+1) = image(:, :, 2);
temp3(2:rows+1,2:cols+1) = image(:, :, 3);
laplaceion = uint8(zeros(size(image)));
for i = 2:(rows + 1)
for j = 2:(cols + 1)
laplaceion(i-1,j-1,1) = temp1(i-1,j+1) + temp1(i+1,j+1) + temp1(i-1,j-1) + temp1(i+1,j-1) + temp1(i+1,j) + temp1(i-1,j) + temp1(i,j+1) + temp1(i,j-1) - 8 * temp1(i,j);
if laplaceion(i-1,j-1,1) <= threshold
laplaceion(i-1,j-1,1) = 0;
else
laplaceion(i-1,j-1,1) = 255;
end
end
end
for i = 2:(rows + 1)
for j = 2:(cols + 1)
laplaceion(i-1,j-1,2) = temp2(i-1,j+1) + temp2(i+1,j+1) + temp2(i-1,j-1) + temp2(i+1,j-1) + temp2(i+1,j) + temp2(i-1,j) + temp2(i,j+1) + temp2(i,j-1) - 8 * temp2(i,j);
if laplaceion(i-1,j-1,2) <= threshold
laplaceion(i-1,j-1,2) = 0;
else
laplaceion(i-1,j-1,2) = 255;
end
end
end
for i = 2:(rows + 1)
for j = 2:(cols + 1)
laplaceion(i-1,j-1,3) = temp3(i-1,j+1) + temp3(i+1,j+1) + temp3(i-1,j-1) + temp3(i+1,j-1) + temp3(i+1,j) + temp3(i-1,j) + temp3(i,j+1) + temp3(i,j-1) - 8 * temp3 (i,j);
if laplaceion(i-1,j-1,3) <= threshold
laplaceion(i-1,j-1,3) = 0;
else
laplaceion(i-1,j-1,3) = 255;
end
end
end
imwrite(laplaceion,'laplace.jpg');
% 与库函数的laplace算子处理效果进行比较
% H = [1 1 1; 1 -8 1; 1 1 1];
% image = uint8(image);
% res = imfilter(image,H);
% cmp=(res==laplaceion);
% length(cmp(cmp==0))
% 测试代码
% image = imread('test.jpg');
% laplaceion = laplace(image);
% result = image - laplaceion;
% imshow(result);
% imwrite(result,'laplace_result.jpg');
% 灰度图像prewitt锐化处理
function result = prewitt(image,threshold)
image = double(image);
[rows,cols,n] = size(image); % 图像行列数
temp1 = int16(zeros([rows+2,cols+2]));
temp2 = int16(zeros([rows+2,cols+2]));
temp3 = int16(zeros([rows+2,cols+2]));
temp1(2:rows+1,2:cols+1) = image(:, :, 1);
temp2(2:rows+1,2:cols+1) = image(:, :, 2);
temp3(2:rows+1,2:cols+1) = image(:, :, 3);
result = uint8(zeros(size(image)));
for i = 2:(rows + 1)
for j = 2:(cols + 1)
result(i-1,j-1,1) = abs(temp1(i-1,j-1)+temp1(i,j-1)+temp1(i+1,j-1)-temp1(i-1,j+1)-temp1(i,j+1)-temp1(i+1,j+1))+abs(temp1(i+1,j-1)+temp1(i+1,j)+temp1(i+1,j+1)-temp1(i-1,j-1)-temp1(i-1,j)-temp1(i-1,j+1));
if result(i-1,j-1,1) <= threshold
result(i-1,j-1,1) = 0;
else
result(i-1,j-1,1) = 255;
end
end
end
for i = 2:(rows + 1)
for j = 2:(cols + 1)
result(i-1,j-1,2) = abs(temp2(i-1,j-1)+temp2(i,j-1)+temp2(i+1,j-1)-temp2(i-1,j+1)-temp2(i,j+1)-temp2(i+1,j+1))+abs(temp2(i+1,j-1)+temp2(i+1,j)+temp2(i+1,j+1)-temp2(i-1,j-1)-temp2(i-1,j)-temp2(i-1,j+1));
if result(i-1,j-1,2) <= threshold
result(i-1,j-1,2) = 0;
else
result(i-1,j-1,2) = 255;
end
end
end
for i = 2:(rows + 1)
for j = 2:(cols + 1)
result(i-1,j-1,3) = abs(temp3(i-1,j-1)+temp3(i,j-1)+temp3(i+1,j-1)-temp3(i-1,j+1)-temp3(i,j+1)-temp3(i+1,j+1))+abs(temp3(i+1,j-1)+temp3(i+1,j)+temp3(i+1,j+1)-temp3(i-1,j-1)-temp3(i-1,j)-temp3(i-1,j+1));
if result(i-1,j-1,3) <= threshold
result(i-1,j-1,3) = 0;
else
result(i-1,j-1,3) = 255;
end
end
end
imwrite(result,'prewitt_result.jpg');
% 测试代码
% image = imread('test.jpg');
% result = prewitt(image,240);
% imshow(result)
% 灰度图像Laplace锐化处理
function result = roberts(image,threshold)
image = double(image);
[rows,cols,n] = size(image); % 图像行列数
temp1 = int16(zeros([rows+2,cols+2]));
temp2 = int16(zeros([rows+2,cols+2]));
temp3 = int16(zeros([rows+2,cols+2]));
temp1(2:rows+1,2:cols+1) = image(:, :, 1);
temp2(2:rows+1,2:cols+1) = image(:, :, 2);
temp3(2:rows+1,2:cols+1) = image(:, :, 3);
result = uint8(zeros(size(image)));
for i = 2:(rows + 1)
for j = 2:(cols + 1)
result(i-1,j-1,1) = abs(temp1(i+1,j+1)-temp1(i,j))+abs(temp1(i,j+1)-temp1(i+1,j));
if result(i-1,j-1,1) <= threshold
result(i-1,j-1,1) = 0;
else
result(i-1,j-1,1) = 255;
end
end
end
for i = 2:(rows + 1)
for j = 2:(cols + 1)
result(i-1,j-1,2) = abs(temp2(i+1,j+1)-temp2(i,j))+abs(temp2(i,j+1)-temp2(i+1,j));
if result(i-1,j-1,2) <= threshold
result(i-1,j-1,2) = 0;
else
result(i-1,j-1,2) = 255;
end
end
end
for i = 2:(rows + 1)
for j = 2:(cols + 1)
result(i-1,j-1,3) = abs(temp3(i+1,j+1)-temp3(i,j))+abs(temp3(i,j+1)-temp3(i+1,j));
if result(i-1,j-1,3) <= threshold
result(i-1,j-1,3) = 0;
else
result(i-1,j-1,3) = 255;
end
end
end
imwrite(result,'roberts_result.jpg');
% 测试代码
% image = imread('test.jpg');
% result = roberts(image,240);
% imshow(result);
% 灰度图像sobel锐化处理
function result = sobel(image,threshold)
image = double(image);
[rows,cols,n] = size(image); % 图像行列数
temp1 = int16(zeros([rows+2,cols+2]));
temp2 = int16(zeros([rows+2,cols+2]));
temp3 = int16(zeros([rows+2,cols+2]));
temp1(2:rows+1,2:cols+1) = image(:, :, 1);
temp2(2:rows+1,2:cols+1) = image(:, :, 2);
temp3(2:rows+1,2:cols+1) = image(:, :, 3);
result = uint8(zeros(size(image)));
for i = 2:(rows + 1)
for j = 2:(cols + 1)
result(i-1,j-1,1) = abs(temp1(i-1,j-1)+2*temp1(i,j-1)+temp1(i+1,j-1)-temp1(i-1,j+1)-2*temp1(i,j+1)-temp1(i+1,j+1))+abs(temp1(i+1,j-1)+2*temp1(i+1,j)+temp1(i+1,j+1)-temp1(i-1,j-1)-2*temp1(i-1,j)-temp1(i-1,j+1));
if result(i-1,j-1,1) <= threshold
result(i-1,j-1,1) = 0;
else
result(i-1,j-1,1) = 255;
end
end
end
for i = 2:(rows + 1)
for j = 2:(cols + 1)
result(i-1,j-1,2) = abs(temp2(i-1,j-1)+2*temp2(i,j-1)+temp2(i+1,j-1)-temp2(i-1,j+1)-2*temp2(i,j+1)-temp2(i+1,j+1))+abs(temp2(i+1,j-1)+2*temp2(i+1,j)+temp2(i+1,j+1)-temp2(i-1,j-1)-2*temp2(i-1,j)-temp2(i-1,j+1));
if result(i-1,j-1,2) <= threshold
result(i-1,j-1,2) = 0;
else
result(i-1,j-1,2) = 255;
end
end
end
for i = 2:(rows + 1)
for j = 2:(cols + 1)
result(i-1,j-1,3) = abs(temp3(i-1,j-1)+2*temp3(i,j-1)+temp3(i+1,j-1)-temp3(i-1,j+1)-2*temp3(i,j+1)-temp3(i+1,j+1))+abs(temp3(i+1,j-1)+2*temp3(i+1,j)+temp3(i+1,j+1)-temp3(i-1,j-1)-2*temp3(i-1,j)-temp3(i-1,j+1));
if result(i-1,j-1,3) <= threshold
result(i-1,j-1,3) = 0;
else
result(i-1,j-1,3) = 255;
end
end
end
imwrite(result,'sobel_result.jpg');
% 测试代码
% image = imread('test.jpg');
% result = sobel(image,240);
% imshow(result)
原图(含椒盐噪声)
中值滤波结果、均值滤波结果
laplace算子边缘检测结果
prewitt算子边缘检测结果
roberts算子边缘检测结果
sobel算子边缘检测结果
均值滤波和和中值滤波都可以起到平滑图像,虑去噪声的功能。均值滤波采用线性的方法,平均整个窗口范围内的像素值,均值滤波本身存在着固有的缺陷,即它不能很好地保护图像细节,在图像去噪的同时也破坏了图像的细节部分,从而使图像变得模糊,不能很好地去除噪声点。均值滤波对高斯噪声表现较好,对椒盐噪声表现较差。中值滤波采用非线性的方法,它在平滑脉冲噪声方面非常有效,同时它可以保护图像尖锐的边缘,选择适当的点来替代污染点的值,所以处理效果好,对椒盐噪声表现较好,对高斯噪声表现较差。
laplace算子是与方向无光的各向同性边缘检测算子,若只关心边缘点的位置而不顾其周围的实际灰度差时,一般选择该算子进行检测.特点:各向同性,线性和位移是不变的,对线性和孤立点检测效果好, 但边缘方向信息丢失,常产生双像素的边缘,对噪声有双倍的加强作用。Roberts算子边缘定位准,但是对噪声敏感。适用于边缘明显且噪声较少的图像分割。Roberts边缘检测算子是一种利用局部差分算子寻找边缘的算子,Robert算子图像处理后结果边缘不是很平滑。经分析,由于Robert算子通常会在图像边缘附近的区域内产生较宽的响应,故采用上述算子检测的边缘图像常需做细化处理,边缘定位的精度不是很高。Prewitt算子对噪声有抑制作用,抑制噪声的原理是通过像素平均,但是像素平均相当于对图像的低通滤波,所以Prewitt算子对边缘的定位不如Roberts算子。Sobel算子和Prewitt算子都是加权平均,但是Sobel算子认为,邻域的像素对当前像素产生的影响不是等价的,所以距离不同的像素具有不同的权值,对算子结果产生的影响也不同。一般来说,距离越远,产生的影响越小。