% Function to compute a spectral density matrix estimate of a three-component % color image using the Welch method of averaging modified periodograms % adapted to vector data following Brillinger. % Follow description in section 9.6 of MDSP book. % Eric Dubois 2018-04-23 function WelchSDM = WelchSDM_est(A,N) % A(:,:,3) is a three-component color image in double format. % The three components are set in the calling program. % N x N is the block size. N should be a power of 2. Usually N=64 % WelchSDM(N,N,3,3) is the N x N spectral density estimate on a linear scale for % each of the nine spectral densities in the spectral density matrix. % Since the spectral density matrix at each frequency is Hermitian, only % six spectral densities need to be computed but for simplicity and since % the computational complexity is low, all nine are computed. % The spectral densities are computed at normalized frequencies % ux=-1/2:1/N:1/2-(1/N); vx=ux; % % Remove the mean from each component of the image. A non-zero mean implies % a Dirac delta at zero frequency. Az is the new image with zero mean. I = size(A,1); J = size(A,2); prodsize=I*J; for C=1:3 mean(C)=sum(sum(A(:,:,C)))/prodsize; Az(:,:,C)=A(:,:,C)-mean(C); end % Compute the 2D separable window (we use a 4-term Blackman-Harris % (or Harris-Nutall) Window) n=0:1:N-1; wd=zeros(N,1); a0=0.40217; a1=0.49703; a2=0.09892; a3=0.00183; wd(n+1)=a0-a1*cos(2*pi*n/N)+a2*cos(2*pi*2*n/N)-a3*cos(2*pi*3*n/N); W=wd*wd'; V = sum(sum(W.*W)); % total power of the window % normalize the window so that the total power is K = N^2. W = N*W/sqrt(V); % % Compute the spectral estimate using an x and y overlap of N/4 % Note that this overlap could be set as a parameter of the algorithm PDS=zeros(N,N,3,3); shx=N/4; % x overlap shy=N/4; % y overlap % Number of blocks in x and y direction Mx=floor((I-N)/(N-shx)); My=floor((J-N)/(N-shy)); for i=0:1:Mx for j=0:1:My %Compute the three windowed components and their DFT for C=1:3 BLK(:,:,C) = W.*Az(i*(N-shx)+1:i*(N-shx)+N,j*(N-shy)+1:j*(N-shy)+N,C); BLK_DFT(:,:,C) = fft2(BLK(:,:,C)); end %Compute the nine spectral estimates for block i,j (ignoring %Hermitian symmetry) for C1=1:3 for C2=1:3 PDS(:,:,C1,C2) = PDS(:,:,C1,C2) + BLK_DFT(:,:,C1).*conj(BLK_DFT(:,:,C2))/(N^2); end end end end %Compute the average. The number of blocks is L = (Mx+1)*(My+1) PDS=PDS/((Mx+1)*(My+1)); %Shuffle the FFT blocks to put the origin at the center for C1=1:3 for C2=1:3 WelchSDM(:,:,C1,C2) = [PDS(N/2+1:N,N/2+1:N,C1,C2) PDS(N/2+1:N,1:N/2,C1,C2);... PDS(1:N/2,N/2+1:N,C1,C2) PDS(1:N/2,1:N/2,C1,C2)]; end end