前言
不论是野外数据采集,还是图像处理,实际二维数据都会存在噪声!用卷积对二维数据降噪是十分常用的一种方法!其原理还是利用卷积可以改变原始数据矩阵中的数值大小。本文主要介绍两种最为常见的二维卷积滤波方法:"均值滤波"与"中值滤波"。
均值滤波与中值滤波原理
原理一句话:原来卷积是两个小矩阵的"点乘再相加(卷积神经网络里的操作)",现在是"点乘相加后求平均(均值滤波)"和"点乘后取中值(中值滤波)"。图1非常明显易懂:
图1:均值滤波与中值滤波原理图
了解了原理,可以很简单的用matlab实现二维卷积滤波的程序。
噪声例子
本文主要使用两种常见的、matlab自带的:"高斯随机噪声"和"椒盐黑白噪声"。直接使用一条语句就可以为原始图像加噪声:
data = imread('zxc.jpg'); % 数据——最好比卷积核的尺寸大
data = im2double(data); % 原图像进来是uint8,矩阵运算时double 故要转一下
data = rgb2grey(data); % 转为灰度图像方便
noise_data1 = imnoise(data, 'gaussian', 0.2); % 加入高斯噪声的命令
noise_data2 = imnoise(data, 'salt & pepper', 0.3); % 加入椒盐噪声的命令
对应的噪声所带来的影响如下:图2是原始灰度图像,图3是分别加了两种噪声后的效果:
图2:原始灰度图像
图3:左图是加了高斯噪声效果图,右图是加了椒盐噪声效果图
均值滤波与中值滤波效果
分别用这两种滤波方法对这两种噪声进行滤波,看看效果怎么样:图4是均值滤波对两种噪声的处理效果,图5是中值滤波对两种噪声的处理效果。
图4:均值滤波分别对高斯、椒盐噪声处理效果
图5:中值滤波分别对高斯、椒盐噪声处理效果
效果对比:
对高斯噪声,两种滤波方法都还不错,但很明显均值滤波自身的缺点把图像模糊了;
对椒盐噪声,很明显中值滤波要比均值滤波很的多!虽然中值滤波结果中还是一些"盐噪声(白点)"去不掉!但其图像恢复效果已经很不错了。(注:对椒盐噪声的去噪,只有!只有!中值滤波效果不错)。
Matlab实现
均值滤波实现如下:
clc; clear;
data = imread('zxc.jpg'); % 数据——最好比卷积核的尺寸大
data = im2double(data); % 原图像进来是uint8,矩阵运算时double 故要转一下
% rgb转为灰度图像
data = rgb2gray(data);
figure(1);
imshow(data);
title('原始灰度值图像');
% 高斯噪声: 均值为m,方差为var的高斯噪声加到图像中 var越大越模糊
% noise_data = imnoise(data, 'gaussian', 0.2);
% 椒盐噪声: 0.1是全图10%的程度受污染
noise_data = imnoise(data, 'salt & pepper', 0.3);
% noise_data = im2double(noise_data); % 这里记得要先转为double类型
figure(2);
imshow(noise_data);
title('加入"高斯噪声"后图像')
% 开始卷积均值滤波:
% x = zeros(3,3)+1; % 卷积核——必须是方阵且为奇数行/列
x = zeros(5,5)+1;
x = x/length(x(:)); % 均值专用
x = rot90(rot90(x)); % 新的卷积核
% 核的尺寸
size_x = size(x);
row_x = size_x(1); % 核的行数
col_x = size_x(2); % 核的列数
% 数据的尺寸
size_data = size(data);
row_data = size_data(1); % 数据的行数
col_data = size_data(2); % 数据的列数
% 核的中心元素:
centerx_row = round(row_x/2);
centerx_col = round(col_x/2);
centerx = x(centerx_row,centerx_col);
% 对原始数据扩边:
data_tmp = zeros(row_data+row_x-1,col_data+row_x-1);
data_tmp(centerx_row:centerx_row+row_data-1,centerx_row:centerx_row+col_data-1) = noise_data;
data_k = data_tmp;
% 扩边后新数据矩阵尺寸:
size_data_k = size(data_k);
row_data_k = size_data_k(1);
col_data_k = size_data_k(2);
% m = centerx_row:row_data+row_x-2
% 开始卷积计算: m n 是新数据矩阵的正常索引
result = zeros(row_data_k,col_data_k);
% m n一般卷积步长都是1
for m = centerx_row:centerx_row+row_data-1
for n = centerx_row:centerx_row+col_data-1
% tt是临时与卷积核大小相同的数据中的部分矩阵:
tt = data_k(m-(centerx_row-1):m+(centerx_row-1),n-(centerx_row-1):n+(centerx_row-1));
% juan是中间每一次卷积计算求和的中间量:
juan = sum(x.*tt);
result(m,n) = sum(juan(:));
end
end
% 求掉之前扩边的0:
result = result(centerx_row:centerx_row+row_data-1,centerx_row:centerx_row+col_data-1);
% 做图:
figure(3);
imshow(result)
title('二维卷积均值滤波后图像');
中值滤波实现如下:只需修改两个for循环那部分
% m n一般卷积步长都是1
for m = centerx_row:centerx_row+row_data-1
for n = centerx_row:centerx_row+col_data-1
% tt是临时与卷积核大小相同的数据中的部分矩阵:
tt = data_k(m-(centerx_row-1):m+(centerx_row-1),n-(centerx_row-1):n+(centerx_row-1));
% juan是中间每一次卷积计算求和的中间量:
juan = median(x.*tt);
result(m,n) = median(juan(:));
end
end
结尾附上自行车的原始图片,方便大家直接测试:
文中用到的图片 提取码:i20n