空間周波数の操作2のプログラムを元に、横軸を周波数(cycle per image)、縦軸をフーリエスペクトルとしてプロットしたグラフ(散布図)を描画します。以下の例では、円形のハニング窓をかけてフーリエ変換した値(Fim4)を分析対象としています。
グラフの縦軸(スペクトル)の値は、仮想的な円を想定して、その円周上のスペクトルを合算してデータの個数で割ることにより求めています。データの個数で割る理由は、仮想円の半径が大きくなるほど合算されるデータの数が大きくなるためです。仮想円の半径を1ずつ増加させながら、それぞれの半径におけるスペクトルの値を算出します。
グラフの軸はX軸Y軸ともに対数軸であることに注意してください。(loglog関数を使用しています)
スペクトルの値は、プログラムと同じフォルダ内にCSVファイルとして出力されます。
function spectrum3close all;clear all;global MYFILENAME; % 別ファイルでも使うのでグローバル変数imgFileName = 'grayRabbit.jpg'; % 画像のファイル名im1 = imread(imgFileName); % 画像のデータを読み込む。% 画像のファイル名を分解[pathstr, MYFILENAME, ext] = fileparts(imgFileName); %% 必要に応じて正規化im2 = double(im1);imMean=mean(im2(:)); % 平均輝度imSD=std(im2(:)); % 輝度の標準偏差im2=(im2-imMean)./imSD; % 平均を0、標準偏差を1に。im2 = im2.*25; % 標準偏差の変更(25は適当)im2 = im2+128; % 平均値の変更(128は256階調の半分)% 正規化しないときは次の行をコメントアウト%im2 = im1;% 正規化した画像をjpgファイルとして出力。imwrite(uint8(im2), [MYFILENAME '-norm.jpg'], 'jpeg');%% 座標の設定imSize = size(im1);halfImgSize = imSize(2)/2; % 画像が正方形、つまり、imSize(1) = imSize(2)を前提としている。[X, Y] = meshgrid(-halfImgSize:(halfImgSize-1), halfImgSize:-1:-(halfImgSize-1)); % 行がY方向、列がX方向であることに注意。Y軸は上が正であることに注意。[TH, R] = cart2pol(X,Y); % X,Yを極座標へ変換%% 出力結果を表示するfigureの設定ScreenSize = get(0, 'ScreenSize');figure('Position', [ScreenSize(3)./4, ScreenSize(4)./4, 1000, 800]); % 画像の位置%% 正規化した画像を表示subplot(2,3,1);ShowGrayScale(im2);%% 画像データにハニング窓(四角形)をかける absXY = max(abs(X), abs(Y)); % absXYは0からhalfImgSizeを取り得る。% 画像の中心部では、absXYは0で、hanningの値は1となる。% absXYが最大(halfImgSize)のとき、hanningの値は0となる。hanning1 = 0.5 - 0.5 * cos(2*pi*(halfImgSize/2+absXY./2)/halfImgSize);im3 = double(im2) .* hanning1;subplot(2,3,2);ShowGrayScale(im3);%% 画像データにハニング窓(円形)をかけるR2 = min(R, halfImgSize); % halfImgSizeを超えない半径のデータを作る。% R2は0からhalfImgSizeを取り得る。% 画像の中心部では、R2は0で、hanningの値は1となる。% R2が最大(halfImgSize)のとき、hanningの値は0となる。hanning2 = 0.5 - 0.5 * cos(2*pi*(halfImgSize/2+R2./2)/halfImgSize);im4 = double(im2) .* hanning2;subplot(2,3,3);ShowGrayScale(im4);%% im2のFFTFim2 = fftshift(fft2(im2)); % スペクトル画像subplot(2,3,4);ShowGrayScale(log(abs(Fim2)));%ShowGrayScale(log(Fim2.*conj(Fim2))); % こういう方法もある。%% im3のFFTFim3 = fftshift(fft2(im3));% スペクトル画像subplot(2,3,5);ShowGrayScale(log(abs(Fim3)));%% im4のFFTFim4 = fftshift(fft2(im4));% スペクトル画像subplot(2,3,6);ShowGrayScale(log(abs(Fim4)));% 周波数解析ShowSpectrum(R, Fim4);function ShowGrayScale(imageData)% 画像をグレースケールで表示する。imagesc(imageData);axis('image');axis('off');colormap(gray);function ShowSpectrum(Rdata, Fdata)% スペクトル解析のグラフ(横軸は周波数(半径)cycle/image)を描く% Rdataは、画像中心からの半径のデータ% Fdataは、画像データをフーリエ変換した結果(RdataとFdataのサイズは同じ。ただしFdataは複素数)global MYFILENAME;% 中心からの半径の最大値Rmax = floor(size(Rdata, 1)/2);Intensity = zeros(1,Rmax); % 半径ごとのスペクトルの合計値を保管outputData = zeros(Rmax, 2); % CSVファイルに出力するデータfor n = 1:Rmax; mask = (Rdata > n-1 & Rdata <= n); % ある半径の1ピクセル以内のデータだけを取り出す。 % (パワー)スペクトルの計算 spect = mask.*abs(Fdata); %spect = mask.*(abs(Fdata).^2); % パワースペクトル %spect = mask.*(Fdata.*conj(Fdata)); % パワースペクトル(上の式と結果は同じ) ind = find(mask); % indはmask=1の場所を表す列ベクトル Intensity(n) = sum(sum(spect)) / size(ind, 1); % 正規化(spectの数は半径ごとに異なるため) outputData(n, :) = [n Intensity(n)]; endfigure;loglog(1:Rmax,Intensity,'o'); % 対数軸でのグラフxlabel('Spatial Frequency (cycle per image)'), ylabel('Fourier Power');title(MYFILENAME);% すべてのパワースペクトルのデータを出力dlmwrite([MYFILENAME '-ps1.csv'], outputData, 'precision', 20); % 有効桁数に注意