Matlab实现图像滤波(叁):高效的中值滤波

图像处理 同时被 2 个专栏收录
20 篇文章 0 订阅
17 篇文章 0 订阅

Matlab实现图像滤波(叁):高效的中值滤波

0 背景介绍

Matlab实现图像滤波(贰)中介绍到了有关中值滤波的相关知识。

在这里插入图片描述

基本思想是:用一个中值滤波器窗口依次遍历整个图像,在每个位置都计算得到一个中值,然后将这些值拼在一起就得到了中值滤波后的图像。中值滤波可以很好地去除椒盐噪声,如:

在这里插入图片描述

参考代码:

% imgOrg = rgb2gray(imread("peppers.png"));
imgOrg = imread("peppers.png");
imgOrg = imnoise(imgOrg, 'salt & pepper'); % Adding salt-pepper noise
subplot(1,3,1);
imshow(imgOrg);
title("Originall img");

% median filter
imgMedian = medianfilter(imgOrg, 3); % Generally, the size of a filter is an odd num
subplot(1,3,2);
imshow(imgMedian);
title("Median filter img");

% Using Matlab API
subplot(1,3,3);
[~, ~, c] = size(imgOrg);
newImg = zeros(size(imgOrg));
for i = 1:c
    newImg(:,:,i) = medfilt2(imgOrg(:,:,i));
end
newImg = uint8(newImg);
imshow(newImg);
title("Medfilt img by API");

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function imgMedian = medianfilter(img,filterSize)
% img: image
% filterSize: if=5, it means 5*5

% Generate new blank image
[h, w, c] = size(img);
padSize = (filterSize-1)/2;
imgMedianT = zeros([h+2*padSize, w+2*padSize, c]);
imgMedianT(1+padSize:padSize+h, 1+padSize:padSize+w, :) = img;
imgMedian = zeros([h, w, c]);

for k = 1:c
    for i = 1:h
        for j = 1:w
            block = imgMedianT(i:i-1+filterSize, j:j-1+filterSize, k);
            imgMedian(i, j, k) = median(block, 'all');
        end
    end
end

imgMedian = uint8(imgMedian);

end

Elapsed time is 0.895780 seconds.

从上面可知,每次移动滤波器窗口就要重新求一次中值,而要求中值需要进行排序,所以开销很大,那么有没有更快地方法呢?请看下文。

1 高效的中值滤波算法

不难发现,每一移动滤波器窗口时,该窗口的变化为:丢掉最左边的一列而新增最右边的一列,对于m*n的中值滤波窗口,有mn-2m个像素没有发生变化,因此不需要重新排序。

在这里插入图片描述

由此我们得到新的算法:


设滤波器窗口大小为 x ∗ y = 3 ∗ 3 x*y = 3*3 xy=33,一个图像的像素分布为

在这里插入图片描述

则:

Step 1

令 t = c e i l ( x y 2 ) \textcolor{FF8F80}{令t = ceil(\dfrac{xy}{2})} t=ceil(2xy)

解释: t = c e i l ( 3 ∗ 3 2 ) = 5 t=ceil(\dfrac{3*3}{2})=5 t=ceil(233)=5为排序后中位数所处的位置。取整可以避免不必要的浮点数运算。

Step 2

将 窗 口 移 至 一 个 新 行 的 开 始 , 对 其 内 容 排 序 。 建 立 窗 口 像 素 的 直 方 图 H , 确 定 其 中 值 m , 记 下 亮 度 ≤ m 的 像 素 数 目 n m \textcolor{FF8F80}{将窗口移至一个新行的开始,对其内容排序。建立窗口像素的直方图H,确定其中值m,记下亮度\leq m的像素数目n_m} Hmmnm

解释:当滤波器移至如图示黄色区域窗口时:

在这里插入图片描述

n m n_m nm相当于当前中值的位置,例如下图 3 ∗ 3 3*3 33滤波器窗口排序好后, 105 105 105为中值,此时 n m = 5 n_m=5 nm=5,即此时中值的位置为 5 5 5号位置。

在这里插入图片描述

Step 3

向 右 移 动 滤 波 器 , 对 于 移 出 的 左 列 的 每 个 亮 度 为 p g 的 像 素 p , 做 如 下 操 作 : H [ p g ] = H [ p g ] − 1 , 若 p g ≤ m , 则 n m = n m − 1 \textcolor{FF8F80}{向右移动滤波器,对于移出的左列的每个亮度为p_g的像素p,做如下操作:\\H[p_g] = H[p_g]-1,若p_g\leq m,则n_m=n_m-1} pgp,H[pg]=H[pg]1pgmnm=nm1

解释:当滤波器移至如图示黄色区域窗口时:

在这里插入图片描述

最左侧(如红色部分)一列被移除,最右侧一列被移入。所以执行 H [ 0 ] = H [ 0 ] − 1 , H [ 84 ] = H [ 84 ] − 1 , H [ 105 ] = H [ 105 ] − 1 H[0]=H[0]-1,H[84]=H[84]-1,H[105]=H[105]-1 H[0]=H[0]1,H[84]=H[84]1,H[105]=H[105]1,即:

在这里插入图片描述

由于 0 ≤ m , 84 ≤ m , 105 ≤ m ,   w h e r e   m = 105 0\leq m, 84 \leq m, 105 \leq m, \space where\space m=105 0m,84m,105m, where m=105,所以现在的 n m = 5 − 1 − 1 − 1 = 2 n_m=5-1-1-1=2 nm=5111=2

Step 4

对 于 移 入 的 右 列 的 每 个 亮 度 为 p g 的 像 素 p , 做 如 下 操 作 : H [ p g ] = H [ p g ] + 1 , 若 p g ≤ m , 则 n m = n m + 1 \textcolor{FF8F80}{对于移入的右列的每个亮度为p_g的像素p,做如下操作:\\H[p_g] = H[p_g]+1,若p_g\leq m,则n_m=n_m+1} pgp,H[pg]=H[pg]+1pgmnm=nm+1

解释:紧接着 S t e p 3 Step3 Step3,执行 H [ 55 ] = H [ 55 ] + 1 , H [ 120 ] = H [ 120 ] + 1 , H [ 255 ] = H [ 255 ] + 1 H[55]=H[55]+1,H[120]=H[120]+1,H[255]=H[255]+1 H[55]=H[55]+1,H[120]=H[120]+1,H[255]=H[255]+1,即:

在这里插入图片描述

由于 55 ≤ m   w h e r e   m = 105 55 \leq m\space where\space m=105 55m where m=105,所以现在的 n m = 2 + 1 = 3 n_m=2+1=3 nm=2+1=3

Step 5

若 n m = t , 则 跳 至 S t e p 8 若 n m < t , 则 跳 至 S t e p 6 若 n m > t , 则 跳 至 S t e p 7 \textcolor{FF8F80}{若n_m=t,则跳至Step8 \\ 若n_m < t,则跳至Step6 \\ 若n_m > t,则跳至Step7} nm=tStep8nm<tStep6nm>tStep7

解释: n m = t n_m=t nm=t,意味着,移动滤波器后,没有改变中值,所以无需进行额外操作。 n m ≠ t n_m\neq t nm=t,意味着,移动滤波器后,改变了中值的位置,所以需要进行额外修正操作。这里, n m = 3 , t = 5 , n m < t n_m=3,t=5,n_m<t nm=3,t=5,nm<t,故跳至 S t e p 6 Step6 Step6。其他情况类似,此处不再举例赘述。

Step 6

重 复 执 行 以 下 操 作 : m = m + 1 n m = n m + H [ m ] 直 到 n m ≥ t , 然 后 跳 至 S t e p 8 \textcolor{FF8F80}{重复执行以下操作:\\m=m+1 \\ n_m=n_m+H[m]\\直到n_m\geq t,然后跳至Step8} m=m+1nm=nm+H[m]nmtStep8

解释: m 从 105 开 始 往 上 增 , 当 m = 116 时 , 由 于 H [ 116 ] = 1 ( 有 一 个 像 素 的 亮 度 为 116 ) , 故 n m 加 1 得 到 n m = 4 。 在 116   120 之 间 , 不 存 在 亮 度 为 117   119 的 像 素 , 故 H [ m ] = 0 , n m 无 变 化 。 同 理 当 m = 120 时 , n m = 5 , 此 时 n m ≥ t = 5 , 故 跳 至 S t e p 8 m从105开始往上增,当m=116时,由于H[116]=1(有一个像素的亮度为116),故n_m加1得到n_m=4。在116\text{~}120之间,不存在亮度为117\text{~}119的像素,故H[m]=0,n_m无变化。同理当m=120时,n_m=5,此时n_m \geq t=5,故跳至Step8 m105m=116H[116]=1116nm1nm=4116 120117 119H[m]=0nmm=120nm=5nmt=5Step8

在这里插入图片描述

注 意 , 若 有 两 个 像 素 的 亮 度 都 是 116 , 则 H [ 116 ] = 2 , n m 应 该 加 2 \textcolor{red}{注意,若有两个像素的亮度都是116,则H[116]=2,n_m应该加2} 116H[116]=2nm2

Step 7

重 复 执 行 以 下 操 作 : n m = n m − H [ m ] m = m − 1 直 到 n m ≤ t , 然 后 跳 至 S t e p 8 \textcolor{FF8F80}{重复执行以下操作:\\ n_m=n_m-H[m] \\m=m-1 \\直到n_m\leq t,然后跳至Step8} nm=nmH[m]m=m1nmtStep8

解释:原理同 S t e p 6 Step6 Step6,这里不多赘述。

Step 8

记 录 m 为 当 前 窗 口 的 中 值 。 然 后 检 查 滤 波 窗 口 的 右 列 是 否 为 图 像 的 右 边 界 : 若 是 , 跳 至 S t e p 9 ; 反 之 , 跳 至 S t e p 3 \textcolor{FF8F80}{记录m为当前窗口的中值。然后检查滤波窗口的右列是否为图像的右边界:\\ 若是,跳至Step9;反之,跳至Step3} mStep9Step3

解释:中值滤波窗口需要遍历图像的一整行。

Step 9

检 查 滤 波 窗 口 的 底 列 是 否 为 图 像 的 下 边 界 : 若 是 , 图 像 遍 历 完 成 , 算 法 结 束 ; 反 之 , 跳 至 S t e p 2 \textcolor{FF8F80}{检查滤波窗口的底列是否为图像的下边界:\\ 若是,图像遍历完成,算法结束;反之,跳至Step2} Step2

解释:中值滤波窗口需要遍历图像的每一行,一行滤波完成后换新行重复操作。


2 算法的Matlab实现

主文件main.m:

img = imnoise(imread("football.jpg"),'salt & pepper',0.1);
filterSize = 5; % odd
tic;
newImg = effMedian(img, filterSize);
toc;
subplot(1,2,1);
imshow(img);
title("Original Image");
subplot(1,2,2);
imshow(newImg);
title("Filtered Image");

函数文件:

function [resultImg] = effMedian(inputImg, fSize)
%EFFMEDIAN Summary of this function goes here
%   Detailed explanation goes here
%   inpuImg: input image
%   fSize: filter size x*x

fSize = [fSize, fSize];
[ih, iw, ic] = size(inputImg);     % height, width and channel of inputImg                    
ch = round((fSize(1)-1)/2);
cw = round((fSize(2)-1)/2);

% padding inputImg
tempImg = zeros([ih+ch*2, iw+cw*2, ic]);
tempImg(1+ch:ih+ch, 1+cw:iw+cw, :) = inputImg;
resultImg = zeros([ih, iw, ic]);

% step1
t = ceil(fSize(1)*fSize(2)/2);

for c = 1:ic
    for h = 1+ch:ih+ch  % Step 9
        w = 1+cw;
        H = zeros([1,256]); % histogram
        filterBlock = tempImg(h-ch:h+ch, w-cw:w+cw, c);
        tempBlock = filterBlock(:);
        for tmpi = 1:fSize(1)*fSize(2)
            H(tempBlock(tmpi)+1) = H(tempBlock(tmpi)+1)+1;% +1:亮度0对应位置1 
        end
        m = median(tempBlock);
        n_m = length(find(tempBlock <= m));
        resultImg(h-ch,w-1,c) = m;
        for w = 2+cw:iw+cw  % Step 8
            moveOut = tempImg(h-ch:h+ch,w-1-cw,c);
            moveIn = tempImg(h-ch:h+ch,w+cw,c);
            tempBlock = moveOut(:);
            for tmpi = 1:fSize(1)  % Step 3
                H(tempBlock(tmpi)+1) = H(tempBlock(tmpi)+1)-1;   
            end
            n_m = n_m - length(find(tempBlock <= m)); % Step 3
            tempBlock = moveIn(:);
            for tmpi = 1:fSize(1)  % Step 4
                H(tempBlock(tmpi)+1) = H(tempBlock(tmpi)+1)+1;   
            end
            n_m = n_m + length(find(tempBlock <= m));  % Step 4
            jmpFlag = n_m - t;                         % Step 5
            if (jmpFlag < 0)                           % Step 6
                while(n_m < t)
                    m = m + 1;
                    n_m = n_m + H(m+1);
                end
            elseif (jmpFlag > 0)                       % Step 7
                while(n_m > t)
                    n_m = n_m - H(m+1);
                    m = m - 1;
                end
            end
            resultImg(h-cw,w-cw,c) = m;
        end
    end
end

resultImg = uint8(resultImg);

end

3 结果验证

在这里插入图片描述

Elapsed time is 0.759880 seconds.

显然,高效的中值滤波效果好的同时,实现了更少的开销。

4 工程下载地址

点击此处下载

  • 3
    点赞
  • 0
    评论
  • 19
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

1. 主要工作: 基于MATLAB图像处理的中值滤波、均值滤波以及高斯滤波的实现与对比: a) 中值滤波法是一种非线性平滑技术,它将每一像素点的灰度值设置为该点某邻域窗口内的所有像素点灰度值的中值. b) 均值滤波是典型的线性滤波算法,它是指在图像上对目标像素给一个模板,该模板包括了其周围的临近像素(以目标像素为中心的周围8个像素,构成一个滤波模板,即去掉目标像素本身),再用模板中的全体像素的平均值来代替原来像素值。 c) 高斯滤波是一种线性平滑滤波,适用于消除高斯噪声,广泛应用于图像处理的减噪过程。通俗的讲,高斯滤波就是对整幅图像进行加权平均的过程,每一个像素点的值,都由其本身和邻域内的其他像素值经过加权平均后得到。高斯滤波的具体操作是:用一个模板(或称卷积、掩模)扫描图像中的每一个像素,用模板确定的邻域内像素的加权平均灰度值去替代模板中心像素点的值。 2. 代码功能: 实现中值滤波、均值滤波以及高斯滤波,并对图像进行输出 3. 结果分析 a) 图像经过中值滤波后,高斯噪声没有被完全去除,椒盐噪声几乎被完全去除效果较好。经过均值滤波后不管是高斯噪声还是椒盐噪声大部分都没有被去除,只是稍微模糊化。经过高斯滤波后,高斯噪声和椒盐噪声几乎被很大程度的模糊化,原图好像被加上了一层蒙版。 【注】若添加图片分辨率过高会发出警报,如果可以正常输出则可以忽视。
©️2020 CSDN 皮肤主题: 博客之星2020 设计师:CY__ 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值