Wavelets
Ttrasformata di Fourier e trasformata coseno hanno dimostrato efficacia per l'analisi in frequenza dei segnali, sfortunatamente però osservando il segnale nel dominio spaziale non si hanno informazioni relative alla frequenza, mentre nel dominio della frequenza non si hanno informazioni spaziali, per mantenere entrambe le informazioni dobbiamo tassellare il piano della spazio-frequenza, le Wavelet rappresentano proprio tassellazioni ammissibili del piano di spazio-frequenza che permettano la ricostruzione esatta del segnale di partenza.
PS: usare http://www.codecogs.com/latex/eqneditor.php per vedere le eq.
Contents
Primi esempi intuitivi
Intuitivamente, un filtro passa-basso applicato a un segnale genera un segnale contenente le sole basse frequenze spazialmente localizzate, il residuo contiene le altre frequenze... che a loro volta possono essere separate nello stesso modo:
% Genero un segnale: X = 0:0.01:10; sig = sin(((X/5).^2).*X) + sin((X.^2).*X); % Preparo un filtro passa-basso: H1 = gauss(-5:0.1:5,0.15,0,false); % Separo le basse frequenze da quelle più alte: ans1 = filter(H1,1,sig); sig1 = sig - ans1; % Separo Ancora: H2 = H1(1:2:end); ans2 = filter(H2,1,sig1); sig2 = sig1 - ans2; % Separo Ancora: H3 = H2(1:2:end); ans3 = filter(H3,1,sig2); sig3 = sig2 - ans3; figure; subplot(511); plot(X,sig); title('Segnale originale'); subplot(512); plot(X,ans1); title('Prima risposta'); subplot(513); plot(X,ans2); title('Seconda risposta'); subplot(514); plot(X,ans3); title('Terza risposta'); subplot(515); plot(X,sig3); title('Residuo');
Sempre intuitivamente, per ottenere un filtro con risposta localizzata sia spazialmente che nel dominio della frequenza è necessario identificare una trasformata che si avvalga di atomi (componenti) a loro volta localizzate sia spazialmente che nelle frequenze. La trasformata di Fourier utilizza come atomi le armoniche e^{iwt} di pulsazione w, infinitamente localizzate nella frequenza ma non localizzate nel tempo.
Sempre intuitivamente, la localizzazione nel tempo la si può ottenere "pesando localmente" il segnale:
f_u(t) = \int_{-\infty}^{+\infty} \hat{f}(w)g(t-u)e^{iwt}dw
In generale, si consideri una trasformata come la proiezione di una funzione f(t) su una base dello spazio di Hilbert in cui la funzione stessa vive (vedremo quale di preciso, in particolare le funzioni appartenenti allo spazio considerato sono continue e derivabili a tratti), ovvero:
f(t) = \int_{-\infty}^{+\infty} \left< f,\Psi_w \right> \Psi_w dw
dove la singola componente \Psi(w) è "pesata" dal prodotto interno:
\left< f,\Psi_w \right> = \int_{-\infty}^{+\infty} f(t)\overline{\Psi_w(t)} dt
Se quindi si intendono evidenziare caratteristiche localizzate simultaneamente nel tempo e nella frequenza bisognerà scegliere \Psi opportunamente.
Nota: una gaussiana è localizzata sia nel dominio del tempo che della frequenza (la trasformata di una gaussiana è una gaussiana). Un approccio consiste nel traslare una gaussiana (o alra funzione) sia nel dominio del tempo che della frequenza, considerato che una traslazione di \xi in frequenza si ottiene moltiplicando per e^{i\xi t}, otteniamo:
\Psi_{u,\xi} = g(t-u)e^{i\xi t}
con g() gaussiana non normalizzata.
% Creo una gaussiana: sigma = 0.5; g = @(t)(gauss(t,sigma,0,false)); % La traslo in spazio e frequenza: u = 4; xi = 10; g2 = @(t)(g(t-u).*exp(1i.*xi.*t)); % Vediamo cosa salta fuori: X = -2:0.05:8; figure; subplot(211); hold on; title('Traslazione vista nel tempo'); plot(X,g(X),'b',X,real(g2(X)),'r'); subplot(212); hold on; title('Traslazione vista nella frequenza'); plot(abs(fftshift(fft(g(X)))),'b'); plot(abs(fftshift(fft(g2(X)))),'r');
Gli atomi ottenuti prendono il nome di filtri di Gabor, in 2 dimensioni i filtri di Gabor hanno più gradi di libertà, in particolare 2DoF per la traslazione in spazio, 2DoF per la traslazione in frequenza, 1DoF per la rotazione e 1DoF per la fase (presente anche in 1d). Date (x,y), le coordinate di un punto del piano, per la rotazione si ha:
(x',y') = \left(x cos(\theta) + y sin(\theta), y cos(\theta) - x sin(\theta) \right)
da cui il filtro di Gabor 2d con orientazione theta:
\Psi_{\theta,\vec{u},\xi}(x,y) = g(\|(x',y')-\vec{u}\|) e^{i\xi x'}
% Init: sigma = 5; xi = 1; theta = -30*pi/180; [X,Y] = meshgrid(-3*sigma:3*sigma); % Ruotiamo il sistema di riferimento: xp = X.*cos(theta) + Y.*sin(theta); yp = Y.*cos(theta) - X.*sin(theta); % Calcoliamo separatamente gaussiana e traslazione in frequenza: G = gauss(sqrt(xp.^2 + yp.^2), sigma, 0, false); Gw = exp(1i*(xi*xp + pi/2)); % Notare la fase pi/2 per ottenere un filtro derivativo % Il filtro di Gabor: Psi = Gw.*G; % Vediamolo: figure; subplot(121); title('Filtro di Gabor 2d'); surf(X,Y,real(Psi)); subplot(122); title('Filtro di Gabor 2d'); imshowscale(real(Psi));
Trasformata di Fourier "a finestra"
Unendo i concetti precedenti è possibile ottenere una trasformata di Fourier localizzata in spazio e frequenza come proiezione di una funzione su un atomo:
Sf(u,\xi) = \left< f, \Psi_{u,\xi} \right> = \int_{-\infty}^{+\infty} f(t)g(t-u)e^{-i\xi t} dt
Grazie a questa trasformata è possibile osservare la variazione delle componenti in frequenza al variare dell'istante di osservazione.
% Init: X = 1:1000; sigma = 3; % Una funzione: f_t = sin(X.*((1+50*X/numel(X)).^2*2*pi/20000)); % Per ogni u: Sf = zeros(numel(X)); for u=1:numel(X) % La peso con una gaussiana: f_t_g = f_t.*gauss(X,sigma,u,false); % Trasformata di fourier: Sf(:,u) = fftshift(fft(f_t_g)); end % Vediamola: figure; imshowscale(abs(Sf));
Heisenberg boxes
Si osservi che ogni filtro locale in tempo e frequenza occupa un rettangolo nel piano tempo-frequenza che viene così tassellato, si può dimostrare che ogni rettangollo non può avere area minore di 1/2, ovvero non esistono atomi il cui supporto in tempo-frequenza ha area minore di questo valore. Da ciò se ne deduce che l'aumento in risoluzione in un dominio (ad esempio nel tempo) ne riduca la risoluzione nell'altro (ad esempio in frequenza).
% Un banco completo di filtri di Gabor: bank = gaborBank((0:360/8:359)*pi/180,2.^(-5:-1),true); contr = zeros(size(bank{1})); for i=1:numel(bank) contr = contr + fftshift(fft2(bank{i})); end figure; imshowscale(abs(contr)); % for i=1:numel(bank); figure; imshowscale(bank{i}); end
Dai filtri a finestra alle wavelet
La tassellazione del piano tempo-frequenza della trasformata di Fourier a finestra è uniforme, per poter operare in modalità multiscala è invece utile tassellare tale piano in maniera non uniforme, ovvero aumentando la risoluzione spaziale per le frequenze più alte, questo risultato può essere ottenuto mantenendo fissa una wavlet detta "madre" e scalandola nel dominio del tempo:
Wf(u,s) = \left< f, \Psi_{u,s} \right> = \int_{-\infty}^{+\infty} f(t)\frac{1}{\sqrt{s}}\overline{\Psi\left(\frac{u-t}{s}\right)} dt
% Un banco completo di wavelet di Gabor: bank = gaborBank((0:360/8:359)*pi/180,2.^(-5:-1)); contr = zeros(size(bank{1})); for i=1:numel(bank) contr = contr + fftshift(fft2(bank{i})); end figure; imshowscale(abs(contr)); % for i=1:numel(bank); figure; imshowscale(bank{i}); end
Applicazione di esempio
In questo esempio proviamo ad utilizzare i pochi strumenti a disposizione per affrontare un problema reale (ottenendo un risultato non eccezionale e sicuramente migliorabile con un po' di strumenti in più).
Scopo del gioco è ritrovare un punto di interesse segnato su una immagine, allinterno di una seconda immagine differente dalla prima, in particolare un punto dell'occhio dove sia presente una struttura di bordi identificabile tramite filtri orientabili come quelli di Gabor.
% % Caricamento delle immagini: % img = imread('http://farm4.static.flickr.com/3024/3070506253_842da24afe.jpg'); % img2 = imread('http://media-2.web.britannica.com/eb-media/21/79821-004-507765DA.jpg'); % img = imtype(img,'gF'); % img2 = imtype(img2,'gF'); % % % Selezione del punto di interesse: % figure; imshow(img); % p = getpoints(1); % Carico localmente i dati: img = imtype(imread('training.jpg'),'gF'); img2 = imtype(imread('testing.jpg'),'gF'); p = [120;284]; % Preparazione dei filtri: bank = gaborBank; bank = bank(1:end-1); % Caratterizzazione del punto di interesse: v = real(bankApply(img,bank,p)); v = reshape(v,[1,1,numel(bank)]); % Applicazione dei filtri all'intera immagine: C = bankApply(img2,bank); V1 = real(cat(3,C{:})); % % Calcolo della distanza coseno: % v = v/norm(v(:)); % normV1 = sqrt(sum(V1.^2,3)); % V1normalized = V1 ./ repmat(normV1,[1,1,numel(bank)]); % cos_theta = sum(V1normalized.*repmat(v,[size(V1,1),size(V1,2)]),3); % dist = (1-cos_theta)/2; % Distanza euclideea tra features: dist = sqrt(sum((repmat(v,[size(V1,1),size(V1,2)])-V1).^2,3)); % Ottenimento dei punti con minore distanza coseno: % [val,pos] = min(dist_cos(:)); [val,pos] = sort(dist(:)); [y,x] = ind2sub(size(dist),pos); % Vediamo il risultato: figure; subplot(121); imshow(img); hold on; plotpoints(p,'ro'); subplot(122); imshow(img2); hold on; plotpointsLabels([x(1:10),y(1:10)]','ro');