Tutorial i exercisis
En aquesta pràctica es parteix d’una idea fonamental: una imatge digital es pot entendre com una matriu de píxels. Cada píxel té una posició dins de la imatge i conté informació visual, ja sigui un nivell de gris o diversos valors associats al color. Per aquest motiu, conceptes com la resolució espacial, la quantificació i el model de color són importants abans d’aplicar qualsevol tècnica de processament.
Al llarg del tutorial es veuran operacions molt bàsiques, però totes tenen una interpretació conceptual clara. Algunes modifiquen només el valor dels píxels, mentre que altres canvien la mida, la posició o la forma aparent de la imatge. Entendre aquesta diferència ajuda a connectar aquesta primera pràctica amb temes posteriors com el filtratge, la segmentació i la descripció d’objectes.
Manipulació bàsica d’imatges
Carreguem les imatges
I = imread("Imagenes\lena_gray_512.tif");
F = imread("Imagenes\lena_color_512.tif");
Mostrem les imatges
imshow(I)

imshow(F)

Calculem la resolució espacial de cada imatge
La resolució espacial indica el nombre de píxels que formen la imatge en amplada i alçada. Una resolució més gran pot representar més detall si la captura original també el conté, però canviar la mida d’una imatge ja digitalitzada no afegeix informació real. Quan ampliem o reduïm, el sistema ha d’estimar valors nous a partir dels píxels existents, i això pot suavitzar detalls o generar artefactes.
size(I)
ans = 1x2
512 512
size(F)
ans = 1x3
512 512 3
Calculem la resolució d’intensitat, o quantificació, de cada imatge
La resolució d’intensitat, també anomenada quantificació, indica quants nivells diferents pot representar cada píxel. En una imatge de 8 bits hi ha 256 valors possibles, de 0 a 255. Si es redueix aquest nombre de nivells, diferents intensitats de l’escena es representen amb el mateix valor, i això pot provocar pèrdua de contrast fi o bandes visibles en zones suaus.
max(max(I))
ans = uint8245
max(max(F))
ans = 1x1x3 uint8 array
ans(:,:,1) =
255
ans(:,:,2) =
248
ans(:,:,3) =
225
Reescalem espacialment la imatge
Reescalar espacialment vol dir canviar el nombre de píxels de la imatge. Si reduïm la imatge, es perden mostres i per tant es pot perdre detall. Si l’ampliem, cal inventar valors intermedis mitjançant interpolació; per això una ampliació no recupera detall real que no fos a la imatge original.
I = imresize(I,[128,128]);
imshow(I)

I = imresize(I,[64,64]);
imshow(I)

I = imresize(I,[16,16]);
imshow(I)

I = imread("Imagenes\lena_gray_512.tif");
I = imresize(I,[1028,1028]);
imshow(I)

Reescalem els nivells d’intensitat de la imatge
Reescalar els nivells d’intensitat vol dir canviar el rang de valors dels píxels. Aquesta operació pot fer que una imatge es vegi més clara, més fosca o amb més contrast, però no canvia la posició dels objectes. És una transformació útil per preparar imatges abans d’aplicar llindars o filtres.
nivells_gris = [128,32,4];
I_128 = imquantize(I, linspace(0, 255, nivells_gris(1)));
I_32 = imquantize(I, linspace(0, 255, nivells_gris(2)));
I_4 = imquantize(I, linspace(0, 255, nivells_gris(3)));
imshow(I_128,[])

imshow(I_32,[])

imshow(I_4,[])

Calculem l’histograma
L’histograma és una eina senzilla per estudiar la distribució dels nivells d’intensitat d’una imatge. Mostra quants píxels hi ha a cada valor, però no conserva informació sobre la seva posició. Tot i aquesta limitació, és molt útil per detectar si una imatge és fosca, clara, té poc contrast o presenta grups d’intensitats que podrien separar-se mitjançant un llindar.
histograma = imhist(I);
Visualitzem l’histograma
bar(histograma)

Calculem cadascun dels canals de color de la imatge mitjançant “eliminar” els altres dos
Separar els canals de color ajuda a entendre que el color d’un píxel és una combinació de diverses components. En el model RGB, cada canal representa la contribució de vermell, verd o blau. En canvi, en el model HSV es descriu el color mitjançant el to, la saturació i la intensitat percebuda, fet que pot ser més adequat en algunes tasques d’anàlisi visual.
F_vermell = F;
F_vermell(:,:,2)=0;
F_vermell(:,:,3)=0;
F_verd = F;
F_verd(:,:,1)=0;
F_verd(:,:,3)=0;
F_blau = F;
F_blau(:,:,1)=0;
F_blau(:,:,2)=0;
imshow(F_vermell)

imshow(F_verd)

imshow(F_blau)

Convertim la imatge de RGB a escala de grisos
La conversió a escala de grisos redueix una imatge de tres canals a una sola imatge d’intensitat. Normalment no es fa una mitjana simple dels canals, sinó una combinació ponderada que té en compte la sensibilitat visual al vermell, verd i blau. Es perd informació cromàtica, però es simplifica l’anàlisi quan el color no és essencial.
F_gris = rgb2gray(F);
imshow(F_gris)

Convertim la imatge de RGB a HSV
El model HSV separa la informació de color en tres components més interpretables: el to indica el tipus de color, la saturació indica la puresa del color i el valor indica la brillantor. Aquesta separació pot facilitar tasques en què interessa analitzar el color independentment de la il·luminació.
F_hsi = rgb2hsv(F);
imshow(F_hsi)

Calculem els canals H, S i V
imshow(F_hsi(:,:,1))

imshow(F_hsi(:,:,2))

imshow(F_hsi(:,:,3))

Soroll gaussià
El soroll representa alteracions no desitjades dels valors dels píxels. Pot aparèixer per limitacions del sensor, de la il·luminació, de la transmissió o del procés de digitalització. En el cas del soroll gaussià, molts píxels pateixen canvis petits al voltant d’un valor mitjà, de manera que la imatge conserva l’estructura general però adquireix un aspecte més granulat.
Definim els paràmetres del soroll gaussià, és a dir, la mitjana i la variància
mitjana = 0;
variancia = 0.01;
La funció imnoise afegeix soroll gaussià multiplicatiu, cosa que es pot detectar fàcilment pel seu aspecte granulat
En el soroll multiplicatiu, la pertorbació depèn del valor del píxel. Això vol dir que les zones més intenses poden veure’s afectades de manera diferent que les zones fosques. Aquest model és útil per entendre sorolls que no s’afegeixen igual a tota la imatge.
I_gaussian_mult = imnoise(I,"gaussian",mitjana,variancia);
imshow(I_gaussian_mult)

Mentre que el soroll gaussià additiu, que s’afegeix tal qual a la imatge, només difumina lleugerament els detalls
En el soroll additiu, a cada píxel se li suma una variació aleatòria independent del seu valor original. La imatge conserva l’estructura general, però les petites diferències locals poden quedar contaminades. Per això molts filtres de suavitzat intenten reduir aquest tipus de variació local.
soroll_gaussia = uint8(randn(size(I)) * sqrt(variancia) + mitjana);
I_gaussian_add = I + soroll_gaussia;
imshow(I_gaussian_add)

Soroll sal i pebre
El soroll de sal i pebre és un exemple de soroll impulsional. A diferència del soroll gaussià, no afecta tots els píxels de manera suau, sinó que substitueix alguns valors per intensitats extremes, normalment negre o blanc. Aquest comportament explica per què, en pràctiques posteriors, els filtres no lineals com la mediana poden ser més adequats que un simple promig.
Definim els paràmetres del soroll sal i pebre, és a dir, la probabilitat que un cert píxel passi a ser un gra de sal o de pebre
probabilitat = 0.05;
Generem una imatge aleatòria que fem servir per canviar els píxels de la imatge original per punts de sal o pebre. Si un píxel aleatori està per sobre o per sota de la probabilitat definida, el píxel corresponent de la imatge original es canvia.
soroll_sal_pebre = rand(size(I));
I_soroll = I;
I_soroll(soroll_sal_pebre < probabilitat/2) = 0; % Soroll "sal"
I_soroll(soroll_sal_pebre > 1 - probabilitat/2) = 255; % Soroll "pebre"
imshow(I_soroll)

Operacions aritmètiques
Les operacions aritmètiques actuen directament sobre els valors numèrics dels píxels. Sumar o restar pot modificar la brillantor, mentre que multiplicar o dividir pot canviar el contrast de manera global. Cal tenir present que les imatges digitals tenen un rang de valors limitat; si una operació produeix valors fora d’aquest rang, es pot perdre informació per saturació.
I = imread("Imagenes\lena_gray_512.tif");
F = imread("Imagenes\Contornos.tif");
G = imread("Imagenes\Office1.png");
H = imread("Imagenes\Office2.png");
G = rgb2gray(G);
H = rgb2gray(H);
montage({I,F,G,H})

Suma aritmètica per una constant
I_50 = I + 50;
Reescalem per poder operar amb les imatges i fem servir la funció add per sumar-les
s = size(G);
H = imresize(H,[s(1),s(2)]);
GH_add = imadd(G,H);
montage({I_50,GH_add})

Resta per una constant
I_75 = I - 75;
Reescalem per poder operar amb les imatges i fem servir la funció substract per restar-les
F = rgb2gray(imresize(F,[512,512]));
IF_resta = imsubtract(I,F);
montage({I_75,IF_resta})

Producte per una constant
I_2 = I.*2;
Reescalem per poder operar amb les imatges i fem servir la funció immultiply per multiplicar-les
IG_prod = immultiply(I,imresize(G,[512,512]));
montage({I_2,IG_prod})

Divisió per una constant
I__2 = I./2;
Reescalem per poder operar amb les imatges i fem servir la funció imdivide per dividir-les
I_div = imdivide(I,imresize(G,[512,512]));
montage({I__2,I_div})

Operacions lògiques
En una imatge binària, cada píxel només pot pertànyer al fons o a l’objecte. Per això, les operacions lògiques es poden interpretar com operacions entre conjunts de píxels: AND correspon a una intersecció, OR a una unió i NOT al complement. Aquesta manera de pensar serà especialment important quan s’introdueixi la morfologia matemàtica.
Binaritzem les imatges per llindarització
G_bin = G>128;
H_bin = H>128;
Calculem l’AND lògic, equivalent a la intersecció si els objectes estan definits per 1
A = and(G_bin,H_bin);
imshow(A

Calculem l’OR lògic, equivalent a la unió si els objectes estan definits per 1
O = or(G_bin,H_bin);
imshow(O)

Calculem l’XOR lògic
X = xor(G_bin,H_bin);
imshow(X)

Calculem el NOT lògic
N = not(G_bin);
imshow(N)

Operacions amb la intensitat dels píxels
Les transformacions d’intensitat són operacions puntuals, perquè cada píxel es modifica segons el seu propi valor i no segons el veïnat. Aquest tipus d’operació no mou els objectes ni canvia la geometria de la imatge, sinó que redistribueix els nivells de gris. Això pot servir per aclarir zones fosques, comprimir zones molt brillants o ajustar el contrast global.
Calculem la imatge negativa
La imatge negativa inverteix els nivells d’intensitat: els valors foscos passen a ser clars i els clars passen a ser foscos. Aquesta transformació és simple, però ajuda a veure que moltes operacions puntuals només redistribueixen valors sense canviar la geometria de l’escena.
I_neg = 255-I;
imshow(I_neg)

Calculem la transf. logarítmica, amb constant c = L-1/log(L) i L nivells de gris de la imatge. La transf. logarítmica aclareix zones fosques respectant les zones que ja eren clares.
imatge = imread("Imagenes\Espalda.jpg");
imatge = rgb2gray(imatge);
imshow(imatge)

imatge_log = (255/(log(256)))*log(double(imatge) + 1);
imshow(uint8(imatge_log))

Calculem la transf. exponencial, amb constant c = L-1/log(L) i L nivells de gris de la imatge. La transf. exponencial enfosqueix zones clares respectant les zones que ja eren fosques. És la inversa de la transf. logarítmica.
imatge_1 = imread("Imagenes\cells_internet.jpg");
imshow(imatge_1)

imatge_exp = exp((log(256)/255)*double(imatge_1))-1;
imshow(uint8(imatge_exp))

Transf. potència-arrel o correcció gamma: aglutina i generalitza les transf. logarítmica i exponencial
La correcció gamma permet controlar de manera flexible la relació entre intensitats d’entrada i sortida. Si gamma és menor que 1, s’aclareixen sobretot les zones fosques; si és major que 1, s’enfosqueixen sobretot les zones clares. És molt utilitzada perquè s’adapta millor a la percepció visual i als dispositius de visualització.
Primer pas: transformo els valors d’intensitat de l’interval \(begin:math:display\)0\,255\(end:math:display\) a \(begin:math:display\)0\,1\(end:math:display\)
imatge_1_gamma = (1./255.)*double(imatge_1);
Segon pas: defineixo el valor de gamma i transformo
Tercer pas: transformo els valors d’intensitat de nou a l’interval \(begin:math:display\)0\,255\(end:math:display\)
gamma = 20;
imatge_1_gamma = uint8(imatge_1_gamma.^gamma * 255);
imshow(imatge_1_gamma)

Expansió i equalització de l’histograma
L’expansió i l’equalització de l’histograma intenten utilitzar millor el rang disponible d’intensitats. L’expansió reparteix els valors entre un mínim i un màxim, mentre que l’equalització busca una distribució més uniforme. Aquestes tècniques poden millorar el contrast, però també poden exagerar soroll o donar resultats poc naturals quan la imatge té il·luminació desigual.
Calculem l’histograma
h = imhist(I);
bar(h)

Calculem els valors d’intensitat màxim i mínim per expandir l’histograma
maxi = double(max(max(I)));
mini = double(min(min(I)));
I_exp = 255.*(double(I)-mini)./(maxi-mini);
imshow(uint8(I_exp))

h_exp = imhist(uint8(I_exp));
bar(h_exp)

Equalitzem l’histograma, cosa que distribueix de manera uniforme els valors d’intensitat en tot l’interval
I_eq = histeq(I,256);
imshow(I_eq)

h_eq = imhist(I_eq);
bar(h_eq)

Operacions geomètriques
Les operacions geomètriques canvien la posició dels píxels o la mida aparent dels objectes. En rotacions, translacions o canvis d’escala, les noves posicions no sempre coincideixen exactament amb la graella discreta de píxels. Per això cal interpolar valors, i el mètode d’interpolació pot influir en la nitidesa, les vores i la qualitat visual del resultat.
Rotació d’angle theta
I_rot = imrotate(I,45);
imshow(I_rot)

Translació en la direcció (x,y)
I_tras = imtranslate(I,[50,150]);
imshow(I_tras)

Translació amb imatge completa
I_tras = imtranslate(I,[50,150],'OutputView','full');
imshow(I_tras)

Simetries vertical i horitzontal
I_simv = flip(I,1);
I_simh = flip(I,2);
montage({I_simv,I_simh})

Dilatació i reducció de factors d i r.
dilatacio_factor = 2;
reduccio_factor = 0.5;
I_dil = imresize(I,dilatacio_factor);
I_red = imresize(I,reduccio_factor);
montage({I_dil,I_red})

Per a algunes de les transformacions geomètriques, cal escollir el mètode d’interpolació, per exemple, rotacions i traslacions
La interpolació defineix com es calcula el valor d’un píxel quan la transformació geomètrica situa una coordenada entre píxels existents. La interpolació nearest és ràpida però pot produir vores dentades; la bilinear dona resultats més suaus; i la bicúbica acostuma a conservar millor la continuïtat, tot i ser més costosa.
I_rot_n = imrotate(I,45,'nearest');
I_rot_b = imrotate(I,45,'bilinear');
I_rot_bb = imrotate(I,45,'bicubic');
imshow(I_rot_n)

imshow(I_rot_b)

imshow(I_rot_bb)
