1. Fragestellung

In der Darstellung bestehen Bilder aus Pixel und der Farbe des Pixels. Die JPEG Norm (siehe z. B. (Hudson et al. 2017)) beschreibt z. B. ein Verfahren der Bildkompression.

Die Wahrnehmung von Farben unterscheidet sich aber, siehe z. B. (Paramei and Oakley 2014). In dieser kurzen Fallstudie soll untersucht werden, ob und wie die Anzahl der Farben durch eine einfache Clusteranalyse reduziert werden kann und wie das resultierenden Bild aussieht.

Eine andere Herangehensweise der Komplexitätsreduktion ist die Hauptkomponentenanalyse (siehe z. B. (Mudrova and Procházka 2005)). Auch dies wird vorgestellt.

2. Bilder und Pixel in R

Die Verschiedenfarbige Schwertlilie, lat.: iris versicolor, ist vermutlich eine der drei berühmtesten Blumen in der Statistik und Data-Science. An ihnen wurde im Jahre 1936 von Sir Ronald Aylmer Fisher die Grundlage der Linearen Diskriminanzanalyse als Beispiel eingeführt (Fisher 1936). Hier ein Foto von Armin Hauke:

Vorbereitungen

Pakete laden:

# Ggfs. Paket jpeg installieren
# install.packages("jpeg")
library(jpeg)
# Ggfs. Paket scales installieren
# install.packages("scales")
library(scales)
# Ggfs. Paket mosaic installieren
# install.packages("mosaic")
library(mosaic)

Über den Befehl readJPEG() aus dem Paket jpeg kann das Bild in R eingelesen werden:

img <- readJPEG("irisversi.jpg")

Darstellung des Bildes in R:

dimension <- dim(img)
dimension
## [1]  768 1024    3

Es handelt sich um ein 3-dimensionales array: \(768 \times 1024\) Pixel mit \(3\) Farben: Rot, Gelb, Blau.

In Datenmatrix überführen:

img_rgb <- data.frame(
  x = rep(1:dimension[2], each = dimension[1]), # Bildspalte
  y = rep(dimension[1]:1, dimension[2]), # Bildzeile
  R = as.vector(img[,,1]), # Rotanteil
  G = as.vector(img[,,2]), # Gelbanteil
  B = as.vector(img[,,3]) # Blauanteil
)

# Kontrolle
str(img_rgb)
## 'data.frame':    786432 obs. of  5 variables:
##  $ x: int  1 1 1 1 1 1 1 1 1 1 ...
##  $ y: int  768 767 766 765 764 763 762 761 760 759 ...
##  $ R: num  0.0824 0.0784 0.0706 0.0667 0.0627 ...
##  $ G: num  0.176 0.173 0.165 0.165 0.161 ...
##  $ B: num  0.0745 0.0706 0.0627 0.051 0.0471 ...

Anzahl unterschiedliche Farben:

n_color <- img_rgb %>%
  select(R,G,B) %>%
  unique() %>%
  nrow()

n_color
## [1] 191005

Für die \(786432=1024 \cdot 768\) Pixel (“Beobachtungen”) des Bildes werden 191005 verschiedene Farbtöne verwendet.

3. Clusteranalyse

k-Means Clusterung der Pixel auf Basis der Farben auf \(k=16\) Farbcluster:

set.seed(1896)
k_means <- kmeans(img_rgb[,c("R","G","B")], centers = 16, 
                  iter.max = 25, nstart = 10)

Farbdarstellung der resultierenden 16 Farben:

k_means$centers %>%
  rgb() %>%
  show_col()

Häufigkeitsverteilung der Clusterzentren (Farben):

gf_col(k_means$size ~ 1:16, fill = rgb(k_means$centers))

Es werden überwiegend Grün- und Lilatöne verwendet.

Erzeugung des Bildes, in dem jedem Pixel die Farbe des zugeordneten Zentrums zugewiesen wird:

# Datensatz
reduced.df <- k_means$centers[k_means$cluster,]
# Array
img_new <- array(NA, dimension)
for(i in 1:3) img_new[,,i] <- matrix(reduced.df[,i], nrow=dimension[1]) 
# Speichern
writeJPEG(img_new, "irisversi_reduced_cluster.jpg")

Das Bild, welches anstatt 191005 nur die 16 auf RGB Ebene gelusterten Farben hat sieht wie folgt aus:

Hinweis: Bei 8 Farben würde man weniger Details erkennen:

4. Hauptkomponentenanalyse

Durchführen der Hauptkomponentenanalyse der Farbtöne der Pixel:

pca <-prcomp(img_rgb[,c("R","G","B")])
summary(pca)
## Importance of components:
##                           PC1    PC2     PC3
## Standard deviation     0.4026 0.1595 0.03776
## Proportion of Variance 0.8578 0.1347 0.00754
## Cumulative Proportion  0.8578 0.9925 1.00000

Die erste Hauptkomponente der Farbtöne enthält 0.85779 der Gesamtvarianz.

Berechnung des Scores jedes Pixels auf der ersten Hauptkomponente:

scores <- predict(pca)[,1]

Skalierung auf \([0,1]\) durch \(x_i=\frac{x_i-\min(x)}{\max(x)-\min(x)}\) als Graustufe:

scores <- (scores-min(scores)) / (max(scores)-min(scores))
# Array
img_new <- array(NA, c(dimension[1:2],1))
img_new[,,1] <- scores
# Speichern
writeJPEG(img_new, "irisversi_reduced_pca1.jpg")

Das Bild, welches anstatt 191005 Farben nur die Graustufe der ersten Hauptkomponente enthält sieht wie folgt aus:

Das Originalbild ist auch in nur einem Farbton (Graustufen) sehr gut zu erkennen.

Für die weiteren Hauptkomponenten ergibt sich:

# 2. Hauptkomponente
scores <- predict(pca)[,2]
scores <- (scores-min(scores)) / (max(scores)-min(scores))
# Array
img_new <- array(NA, c(dimension[1:2],1))
img_new[,,1] <- scores
# Speichern
writeJPEG(img_new, "irisversi_reduced_pca2.jpg")

# 3. Hauptkomponente
scores <- predict(pca)[,3]
scores <- (scores-min(scores)) / (max(scores)-min(scores))
# Array
img_new <- array(NA, c(dimension[1:2],1))
img_new[,,1] <- scores
# Speichern
writeJPEG(img_new, "irisversi_reduced_pca3.jpg")

Als Bild:

Der Kontrast der Bilder sinkt mit den jeweiligen Hauptkomponenten.

5. Ergebnisse und Ausblick

Die Komplexitätsreduktion des Bildes (Original; Oben) durch Clusteranalyse auf 16 Farben (Mitte) oder auf die erste Hauptkomponente als Graustufe (Unten) ergibt insgesamt:

Auch wenn hier naive, statistische Verfahren angewendet wurden, ohne die Besonderheiten von Bildern zu berücksichtigen (siehe z. B. (Sonka, Hlavac, and Boyle 2014)), so zeigt das Ergebnis doch, wie klassische Verfahren für Bilder angewendet werden können und das trotz Komplexitätsreduktion die relevante Information erhalten bleiben kann.

Auf Bildebene sind die genannten Verfahren in der Praxis häufig Vorverarbeitungsschritte um z. B. Bilder zu vergleichen oder wiederzuerkennen.

Komplexitätsreduktion

Stellen Sie sich vor, die vielen Pixel wären Ihre Kund*innen o.ä., Daten aus Ihrem Umfeld.

Mit der Clusteranalyse können Sie ähnliche Beobachtungen zusammenfassen: anstatt alle Beobachtungen einzeln zu betrachten können Sie (wenige) Prototypen, die Clusterzentren, analysieren um generelle Muster im Kundenstamm zu erkennen.

Bei der Hauptkomponentenanalyse fassen Sie Variablen zusammen: anstatt alle Variablen einzeln zu betrachten fassen Sie diese zu wenigen Hauptkomponenten zusammen.

In beiden Fällen hat sich die Komplexität Ihrer Aufgabe reduziert.


Anhang: Versionshinweise

Verwendete Pakte:

Literatur

Fisher, R. A. 1936. “The Use of Multiple Measurements in Taxonomic problemsHE Use of Multiple Measurements in Taxonomic Problems.” Annals of Eugenics 7 (2): 179–88. https://doi.org/10.1111/j.1469-1809.1936.tb02137.x.

Hudson, G., A. Léger, B. Niss, and I. Sebestyén. 2017. “JPEG at 25: Still Going Strong.” IEEE MultiMedia 24 (2): 96–103. https://doi.org/10.1109/MMUL.2017.38.

Mudrova, M, and Aleš Procházka. 2005. “Principal Component Analysis in Image Processing.” In Proceedings of the Matlab Technical Computing Conference, Prague.

Paramei, Galina V., and Beata Oakley. 2014. “Variation of Color Discrimination Across the Life Span.” J. Opt. Soc. Am. A 31 (4): A375–A384. https://doi.org/10.1364/JOSAA.31.00A375.

Sonka, Milan, Vaclav Hlavac, and Roger Boyle. 2014. Image Processing, Analysis, and Machine Vision. Cengage Learning.