This commit is contained in:
2026-01-15 10:45:54 +01:00
parent 9452e42623
commit 80b38f0592
3 changed files with 215 additions and 1 deletions

View File

@@ -22,7 +22,7 @@ head(img_matrix)
# 2. Application de l'algorithme K-means
# Choix du nombre de couleurs (k)
k <- 12
k <- 8
# Application de K-means
# On augmente iter.max car la convergence sur des milliers de pixels peut être lente
@@ -55,12 +55,121 @@ title(paste("Compressée (k =", k, ")"))
# l'image compressée :
# Plus $k$ est petit, plus le résumé est ..., plus le MSE .....
library(imager)
mse_imager <- function(img1, img2) {
# Harmoniser dimensions (recadrage ou redimensionnement si besoin)
if (!all(dim(img1) == dim(img2))) {
# Ici, on redimensionne img2 sur la taille d'img1
img2 <- imresize(img2, size_x = width(img1), size_y = height(img1))
if (spectrum(img2) != spectrum(img1)) {
img2 <- grayscale(img2) # fallback simple si nb de canaux diffère
img1 <- grayscale(img1)
}
}
# Convertir en vecteurs numériques [0,1]
x <- as.numeric(img1)
y <- as.numeric(img2)
mean((x - y)^2)
}
mse_val <- mse_imager(img, img_compressed)
cat("MSE =", mse_val, "\n")
mse_matrix <- mean((img_matrix - img_compressed_matrix)^2)
cat("MSE =", mse_matrix, "\n")
########################################################################
# Règle du coude (Elbow Method)
# tracez l'évolution de la Within-Cluster Sum of Squares (WCSS) en fonction de $k$
# Prnde k = 2 à 32
# A partir de quel $k$ le gain visuel devient-il négligeable pour l'œil humain ?
# X : matrice/df n x d
# ks : valeurs de k à tester (par défaut 1:10)
elbow_wss <- function(X, ks = 2:32, nstart = 10, scale_data = FALSE) {
X <- as.matrix(X)
if (scale_data) {
X <- scale(X)
}
wss <- numeric(length(ks))
# Cas k = 1 : WSS = TSS (variance totale)
total_ss <- sum(scale(X, scale = FALSE)^2) # TSS
for (i in seq_along(ks)) {
k <- ks[i]
cat(" k =", k, "\n")
if (k == 1) {
wss[i] <- total_ss
} else {
set.seed(123) # reproductible
km <- kmeans(X, centers = k, nstart = nstart, iter.max = 100)
wss[i] <- km$tot.withinss
}
}
plot(ks, wss, type = "b", pch = 19, xlab = "Nombre de clusters (k)",
ylab = "Inertie intra-classe (WSS)",
main = "Méthode du coude (k-means)")
grid()
# invisible(data.frame(k = ks, WSS = wss))
}
# Exemple d'utilisation :
res <- elbow_wss(img_compressed, ks = 2:32, nstart = 20, scale_data = FALSE)
###############################################################################
elbow_wss_safe <- function(X, ks = 2:32, nstart = 20, scale_data = FALSE, seed = 123) {
X <- as.matrix(X)
if (scale_data) X <- scale(X)
set.seed(seed)
# Nombre de lignes distinctes
n_unique <- nrow(unique(X))
if (n_unique < 2) stop("Moins de 2 points distincts : k-means n'a pas de sens.")
# Tronquer ks si nécessaire
ks <- ks[ks <= n_unique]
if (length(ks) == 0) stop("Tous les k demandés dépassent le nombre de points distincts.")
wss <- numeric(length(ks))
# TSS (k = 1)
total_ss <- sum(scale(X, scale = FALSE)^2)
for (i in seq_along(ks)) {
k <- ks[i]
cat(" k =", k, "\n")
if (k == 1) {
wss[i] <- total_ss
} else {
km <- kmeans(X, centers = k, nstart = nstart, iter.max = 100)
wss[i] <- km$tot.withinss
}
}
plot(ks, wss, type = "b", pch = 19, xlab = "Nombre de clusters (k)",
ylab = "Inertie intra-classe (WSS)", main = "Méthode du coude (k-means)")
axis(1, at = ks)
grid()
# invisible(data.frame(k = ks, WSS = wss))
}
# Exemple :
res <- elbow_wss_safe(img_compressed, ks = 2:32, nstart = 20)
# Taille de stockage
# Ouvrir un fichier JPG
jpeg("./data/image_compressed.jpg")