局部標準差在圖像處理鄰域具有廣泛的應用,但是直接計算非常耗時,本文利用積分圖像對局部標準差的計算進行加速。
局部標準差:
標準差定義如下(採用統計學中的定義,分母爲):
其中。
爲了計算圖像的局部標準差,首先設定局部區域的大小爲 ,則局部區域的像素點個數 。
對標準差的公式進行化簡:
因,故:
可以看出,局部標準差計算中需要對圖像與進行局部求和操作,即和。
我們可以先分別計算出圖像和的積分圖像、,這樣就能在常量時間計算出上述的局部和。
時間複雜度:
圖像中共個像素點,每個局部區域共有個像素點,直接計算局部標準差的時間複雜度 ,利用積分圖像計算局部標準差的時間複雜度爲。(計算積分圖像的時間爲 、計算一個像素點的局部標準差需要常量時間,共個像素點,故最後的計算複雜度仍爲 )
Matlab程序:
Localstd.m:直接計算圖像的局部標準差
function Std=Localstd(Img,d)
[m,n]=size(Img);
Var=zeros(m,n);
Img = padarray(Img,[d d],'symmetric');%邊界填充
N=(2*d+1)^2;
for i=1:m
for j=1:n
i1=i+d;
j1=j+d;
B=Img(i1-d:i1+d,j1-d:j1+d);%取局部區域
Var(i,j)=sum(sum((B-mean(B(:))).^2))/(N-1);%標準差公式
end
end
Std=sqrt(Var);
fastLocalstd.m:利用積分圖像進行快速計算
function Std=fastLocalstd(Img,d)
[m,n]=size(Img);
Img = padarray(Img,[d+1 d+1],'symmetric');%邊界填充
Img2=Img.^2;
Int=integral(Img);%計算Img的積分圖像
Int2=integral(Img2);%計算Img^2的積分圖像
Var=zeros(m,n);
N=(2*d+1)^2;%局部像素點個數
for i=1:m
for j=1:n
i1=i+d+1;
j1=j+d+1;
%利用積分圖像求局部和
sumi2=Int2(i1+d,j1+d)+Int2(i1-d-1,j1-d-1)-Int2(i1+d,j1-d-1)-Int2(i1-d-1,j1+d);
sumi=Int(i1+d,j1+d)+Int(i1-d-1,j1-d-1)-Int(i1+d,j1-d-1)-Int(i1-d-1,j1+d);
Var(i,j)=(sumi2-sumi^2/N)/(N-1);
end
end
Std=sqrt(Var);
function I=Integral(Img)
Img=double(Img);
[m,n]=size(Img);
I=zeros(m,n);
for i=1:m
for j=1:n
if i==1 && j==1 %積分圖像左上角
I(i,j)=Img(i,j);
elseif i==1 && j~=1 %積分圖像第一行
I(i,j)=I(i,j-1)+Img(i,j);
elseif i~=1 && j==1 %積分圖像第一列
I(i,j)=I(i-1,j)+Img(i,j);
else %積分圖像其它像素
I(i,j)=Img(i,j)+I(i-1,j)+I(i,j-1)-I(i-1,j-1);
end
end
end
main.m:
clear all;
close all;
clc;
Img=double(imread('lena.tif'));
d=1;
tic
J1=Localstd(Img,d);
toc
tic
J2=fastLocalstd(Img,d);
toc
figure;
imshow([Img/max(Img(:)),J1/max(J1(:)),J2/max(J2(:))]);
lena.tif大小爲256*256,Localstd運行時間爲 0.984451s,而fastLocalstd運行時爲0.025528s。
當然,對於局部標準差,Matlab本身提供了函數stdfilt,下面是它的核心代碼:
function Std=Stdfilt(I,d)
I=double(I);
h=ones(2*d+1);
n=(2*d+1)^2;
conv1 = imfilter(I.^2,h,'symmetric') / (n-1);
conv2 = imfilter(I,h,'symmetric').^2 / (n*(n-1));
Std = sqrt(conv1-conv2);
可以看出,它按照化簡後的公式直接對圖像和進行卷積操作,因爲imfilter函數是使用c實現的,且內部應該進行了優化,故速度較快。對上面的lena.tif運行時間爲:0.064522s。