Tutorial i exercisis
En aquesta pràctica es treballen característiques que permeten descriure i comparar imatges. Algunes són globals, com els histogrames, perquè resumeixen informació de tota la imatge o d’una regió gran. Altres són més locals, com els vèrtexs o les rectes detectades, perquè indiquen punts o estructures concretes. Totes elles ajuden a convertir informació visual en dades més fàcils d’analitzar.
Carreguem les imatges que utilitzarem en la pràctica.
lena = imread("Imagenes\lena_color_512.tif");
mandril = imread("Imagenes\mandril_color.tif");
malla = imread("Imagenes\patron_malla.jpg");
textura = imread("Imagenes\astablet.tif");
chessboard = imread("Imagenes\chessboardpattern.jpg");
chessboard_inclinado = imread("Imagenes\esquinas_perspectiva.jpg");
malla = rgb2gray(malla);
chessboard_inclinado = rgb2gray(chessboard_inclinado);
montage({lena,mandril,malla,textura,chessboard,chessboard_inclinado})

Característiques basades en l’histograma
Un histograma de color indica com es distribueixen els valors dels canals de color. És útil per descriure l’aparença general d’una imatge, per exemple si predominen tons foscos, clars o determinats colors. Tot i això, l’histograma no conserva informació espacial: dues imatges poden tenir el mateix histograma i, alhora, mostrar objectes disposats de manera completament diferent.
Histograma del color
Primer exemple: imatge Lena
Separem la imatge en els tres canals de color
vermell = lena(:,:,1);
verd = lena(:,:,2);
blau = lena(:,:,3);
I obtenim els histogrames de cada canal
h_vermell = imhist(vermell);
h_verd = imhist(verd);
h_blau = imhist(blau);
bar(h_vermell)

bar(h_verd)

bar(h_blau)

Un altre exemple: imatge mandril
vermell = mandril(:,:,1);
verd = mandril(:,:,2);
blau = mandril(:,:,3);
h_vermell = imhist(vermell);
h_verd = imhist(verd);
h_blau = imhist(blau);
bar(h_vermell)

bar(h_verd)

bar(h_blau)

Calculem les mesures de similitud per comparar histogrames. Per simplificar, compararem només un histograma per imatge.
Comparar histogrames vol dir mesurar fins a quin punt dues distribucions d’intensitat o color s’assemblen. La distància euclidiana tracta les diferències de manera directa, la khi quadrat dona més importància a diferències relatives i la divergència de Jeffrey compara distribucions de forma més simètrica. Cap mètrica és universalment millor; depèn de què es vulgui considerar semblant.
lena_gris = rgb2gray(lena);
mandril_gris = rgb2gray(mandril);
h_lena = imhist(lena_gris);
h_mandril = imhist(mandril_gris);
Normalitzem l’histograma
La normalització dels histogrames és necessària quan es volen comparar imatges de mida diferent o amb diferent nombre de píxels. Sense normalitzar, una imatge més gran podria donar valors més alts simplement perquè conté més píxels. En normalitzar, la comparació se centra millor en la forma de la distribució i no tant en la quantitat absoluta de mostres.
h_lena_n = h_lena/numel(lena_gris);
h_mandril_n = h_mandril/numel(mandril_gris);
bar(h_lena_n)

bar(h_mandril_n)

Distància euclidiana
dist_euclidiana = sqrt(sum((h_lena_n - h_mandril_n).^2))
dist_euclidiana = 0.0533
Distància khi quadrat
dist_khi_quadrat = sum(((h_lena_n - h_mandril_n).^2) ./ (h_lena_n + h_mandril_n + eps))
dist_khi_quadrat = 0.2997
Distància de la divergència de Jeffrey
divergencia_jeffrey = sum(h_lena_n.*log((h_lena_n./(h_mandril_n + eps))+eps))
divergencia_jeffrey = 2.1436
Histograma dels gradients orientats
L’histograma de gradients orientats, o HOG, descriu la distribució de les direccions del gradient en petites zones de la imatge. Com que el gradient és fort a les vores, aquest descriptor resumeix informació sobre contorns i formes locals. Durant molts anys va ser un descriptor molt utilitzat en detecció d’objectes, especialment abans que les xarxes convolucionals fossin tan habituals.
Primer exemple: imatge Lena
Comanda: extractHOGFeatures
[vector_caracteristiques,hog] = extractHOGFeatures(lena);
imshow(lena);
hold on;
plot(hog);
hold off

Un altre exemple: imatge mandril
[vector_caracteristiques_mandril,hog_mandril] = extractHOGFeatures(mandril);
imshow(mandril);
hold on
plot(hog_mandril);
hold off

Característiques basades en la transformada de Hough
La transformada de Hough és una tècnica per detectar formes geomètriques simples, com rectes o cercles. La idea és que cada punt de vora vota per les formes que podrien passar per ell. Quan molts punts voten pel mateix conjunt de paràmetres, és probable que hi hagi una forma real a la imatge. Això permet detectar estructures encara que les vores no siguin perfectes o estiguin parcialment interrompudes.
Obtenció de rectes mitjançant la transformada de Hough
Primer obtenim les vores de la imatge
La transformada de Hough no s’aplica normalment sobre tota la imatge, sinó sobre una imatge de vores. Això redueix el nombre de punts que voten i concentra el procés en els píxels que probablement formen part de rectes o contorns.
malla_edge = edge(malla,"canny");
Comanda: hough. Dona com a input la discretització del pla de Hough H, amb els valors de theta T i rho R
[H,T,R] = hough(malla_edge);
Calculem els pics, punts amb més valor, en aquesta discretització del pla de Hough. En particular, ens quedem amb els 16 pics de més valor que estiguin per sobre del 35% del valor màxim.
Un pic en l’espai de Hough indica que molts punts de vora són compatibles amb la mateixa recta. Seleccionar només els pics més forts evita considerar rectes febles o causades per soroll. El llindar controla quantes estructures es conserven.
P = houghpeaks(H, 16,'threshold',ceil(0.35*max(H(:))));
Calculem les rectes amb aquests pics i els seus valors theta i rho associats, que defineixen les rectes corresponents.
lines = houghlines(malla_edge,T,R,P);
imshow(malla)
hold on
for k = 1:length(lines)
xy = [lines(k).point1; lines(k).point2];
plot(xy(:,1),xy(:,2),'LineWidth',2,'Color','red');
end
hold off

Obtenim els cercles en la imatge mitjançant la transformada de Hough. Per a això, utilitzem la comanda imfindcircles, que busca cercles amb un radi de valor comprès en el rang que es defineix com a segon input.
Per detectar cercles, el mètode busca acumulacions de vots compatibles amb un centre i un radi. El rang de radis és important: si és massa ampli, augmenten els falsos positius; si és massa restrictiu, es poden perdre cercles reals. Per això cal relacionar aquest rang amb la mida esperada dels objectes.
[centers, radii] = imfindcircles(textura,[10 30]);
imshow(textura)
viscircles(centers, radii,'EdgeColor','b');

Vèrtexs
Un vèrtex o cantonada és un punt on la imatge canvia de manera significativa en més d’una direcció. Aquest tipus de punt és més fàcil de localitzar de manera precisa que una vora recta, perquè una vora pot desplaçar-se al llarg de la seva direcció sense canviar gaire. Per això les cantonades són útils com a punts d’interès en registre d’imatges, seguiment i comparació entre imatges.
S’utilitza el detector de Harris per identificar cantonades i vèrtexs en les imatges.
El detector de Harris analitza com canvia la intensitat dins d’una petita finestra quan aquesta es desplaça. Si el canvi és gran en totes les direccions, el punt central es considera una bona cantonada. Si el canvi és gran només en una direcció, probablement es tracta d’una vora. Per obtenir resultats més fiables, normalment es conserven només els punts amb una resposta més forta.
corners = detectHarrisFeatures(chessboard);
imshow(chessboard);
hold on
plot(corners.Location(:,1),corners.Location(:,2),'o','Color','r','LineWidth',2);
hold off

Un altre exemple. Noteu que en aquest cas es detecten diversos falsos positius. Una anàlisi més detallada mostra que la mètrica d’aquests és molt baixa, de manera que es poden eliminar fàcilment seleccionant els més forts, és a dir, els que tenen una detecció més robusta.
corners_alt = detectHarrisFeatures(chessboard_inclinado);
imshow(chessboard_inclinado);
hold on
plot(corners_alt.Location(:,1),corners_alt.Location(:,2),'o',"color",'r','LineWidth',2);
hold off

imshow(chessboard_inclinado)
strongest = corners_alt.selectStrongest(20);
hold on
plot(strongest.Location(:,1),strongest.Location(:,2),'o','color','r','LineWidth',2)
hold off
