La notion des valeurs singulières rappelle quelques souvenirs des cours d’algèbre linéaire de prépa. Le prof avait sûrement mentionné le fait que la compression d’image pouvait utiliser cette notion. Mais j’avais trop la tête dans les calculs. C’est seulement maintenant que je découvre toute la beauté de la Décomposition en Valeurs Singulières.
Une image digitale de 10 x 10 pixels est une matrix de 10 x 10 avec les valeurs numériques qui indiquent les paramètres de couleurs. Une couleur peut être codée avec trois paramètres rgb. Pour une image en gris, une seule valeur suffit pour indiquer le niveau de gris.
Les biologistes ont beaucoup contribué à l’analyse des images. Le package EBImage est disponible sur bioconductor.
Pour avoir un peu plus d’informations sur la manipulation d’images, il y a un très bon article sur EBImage
img <- readImage("images/IRIS.jpg")
dim(img)
## [1] 300 295 3
attributes(img)
## $dim
## [1] 300 295 3
##
## $colormode
## [1] 2
##
## $class
## [1] "Image"
## attr(,"package")
## [1] "EBImage"
str(img)
## Formal class 'Image' [package "EBImage"] with 2 slots
## ..@ .Data : num [1:300, 1:295, 1:3] 1 1 1 1 1 1 1 1 1 1 ...
## ..@ colormode: int 2
display(img, method = "raster")
gris <- imagematrix(img, type = "grey")
dim(gris)
## [1] 300 295
attributes(gris)
## $dim
## [1] 300 295
##
## $type
## [1] "grey"
##
## $class
## [1] "imagematrix" "matrix"
str(gris)
## imagematrix [1:300, 1:295] 1 1 1 1 1 1 1 1 1 1 ...
## - attr(*, "type")= chr "grey"
## - attr(*, "class")= chr [1:2] "imagematrix" "matrix"
display(gris, method = "raster")
Voir l’article de wikipédia.
gris.svd <- svd(gris)
u <- gris.svd$u
v <- gris.svd$v
d <- diag(gris.svd$d)
dim(d)
## [1] 295 295
Analyse des valeurs singulières, qui sont les valeurs de de la diagonale de la matrice D. Ainsi, on voit que le rang de la matrice est de nrow(d)
. On peut afficher l’ensemble des valeurs singulières :
sigmas = gris.svd$d
plot(1:length(gris.svd$d), gris.svd$d,
xlab="Enumération", ylab="Valeur singulière", main="Valeurs singulières")
Pour voir la contribution cumulée des valeurs singulières, on peut tracer la courbe suivante :
plot(1:length(gris.svd$d), cumsum(gris.svd$d) / sum(gris.svd$d),
xlab="i plus grand",ylab="Pourcentage",
main="Contribution cumulative des valeurs singulières")
Comme l’image est globalement blanche, on peut penser que le premier couple de vecteurs singulers permet de traduire l’abondance de blanc autour.
u1 <- as.matrix(u[, 1])
v1 <- as.matrix(v[, 1])
d1 <- as.matrix(d[1, 1])
l1 <- u1 %*% d1 %*% t(v1)
l1g <- imagematrix(l1, type = "grey")
display(l1g, method = "raster", all=TRUE)
Selon la courbe cumulative, on peut voir que les 10 plus grandes valeurs représentent 62% de l’image.
debut=1
fin=10
us <- as.matrix(u[, debut:fin])
vs <- as.matrix(v[, debut:fin])
ds <- as.matrix(d[debut:fin, debut:fin])
ls <- us %*% ds %*% t(vs)
lsg <- imagematrix(ls, type = "grey")
display(lsg, method = "raster")
On peut maintenant regarder les plus petites valeurs. Avec les 28 dernières, on a uniquement 11%. Si on ne savait que c’était un iris, on ne saurait pas trop deviner sur l’image suivante. Alors que sur l’image précédente. On voir clairement le contour d’un iris.
debut=30
fin=57
us <- as.matrix(u[, debut:fin])
vs <- as.matrix(v[, debut:fin])
ds <- as.matrix(d[debut:fin, debut:fin])
ls <- us %*% ds %*% t(vs)
lsg <- imagematrix(ls, type = "grey")
display(lsg, method = "raster")
Comme une couleur peut être exprimée avec trois paramètres rgb, il suffit de faire les mêmes calculs sur chacun des trois paramètres, comme pour le niveau de gris.
Une image est vue comme une matrice d’un certain rang. La compression d’image qui consiste à réduire le rang de la matrice image illustre le fait que les valeurs singulières représentent la contribution des vecteurs singuliers correspondants qui permettent de reconstituer l’image originale.
Copyright © 2016 Kezhan SHI All rights reserved.