Purpose
Use SVD to perform image compression.

> library(grid)
> library(RColorBrewer)
> vplayout <- function(x, y) viewport(layout.pos.row = x, layout.pos.col = y)
> color.data <- matrix(data = 0, nrow = 15, ncol = 40)

Draw HELLO

> grid.newpage()
> pushViewport(viewport(layout = grid.layout(15, 40)))
> for (i in 1:15) {
+     for (j in 1:40) {
+         grid.rect(gp = gpar(fill = "black"), vp = vplayout(i,
+             j))
+     }
+ }
> H <- rbind(cbind(2:9, 2), cbind(2:9, 3), cbind(2:9, 6), cbind(2:9,
+     7), cbind(5, 2:7), cbind(6, 2:7))
> for (i in 1:dim(H)[1]) {
+     grid.rect(gp = gpar(fill = "white"), vp = vplayout(H[i, 1],
+         H[i, 2]))
+     color.data[H[i, 1], H[i, 2]] <- 1
+ }
> E <- rbind(cbind(3, 10:15), cbind(4, 10:15), cbind(6, 10:15),
+     cbind(7, 10:15), cbind(9, 10:15), cbind(10, 10:15), cbind(3:10,
+         10), cbind(3:10, 11))
> for (i in 1:dim(E)[1]) {
+     grid.rect(gp = gpar(fill = "white"), vp = vplayout(E[i, 1],
+         E[i, 2]))
+     color.data[E[i, 1], E[i, 2]] <- 1
+ }
> L <- rbind(cbind(10, 18:23), cbind(11, 18:23), cbind(4:11, 18),
+     cbind(4:11, 19))
> for (i in 1:dim(L)[1]) {
+     grid.rect(gp = gpar(fill = "white"), vp = vplayout(L[i, 1],
+         L[i, 2]))
+     color.data[L[i, 1], L[i, 2]] <- 1
+ }
> L <- rbind(cbind(11, 26:31), cbind(12, 26:31), cbind(5:12, 26),
+     cbind(5:12, 27))
> for (i in 1:dim(L)[1]) {
+     grid.rect(gp = gpar(fill = "white"), vp = vplayout(L[i, 1],
+         L[i, 2]))
+     color.data[L[i, 1], L[i, 2]] <- 1
+ }
> O <- rbind(cbind(6, 34:39), cbind(7, 34:39), cbind(12, 34:39),
+     cbind(13, 34:39), cbind(6:13, 34), cbind(6:13, 35), cbind(6:13,
+         38), cbind(6:13, 39))
> for (i in 1:dim(O)[1]) {
+     grid.rect(gp = gpar(fill = "white"), vp = vplayout(O[i, 1],
+         O[i, 2]))
+     color.data[O[i, 1], O[i, 2]] <- 1
+ }

Exer_9_3-002.jpg

Lets do SVD

> a.svd <- svd(color.data)

Function to draw image

> draw.image <- function(factors, A1, a.svd) {
+     A1 <- a.svd$d[1] * a.svd$u[, 1] %*% t(a.svd$v[, 1])
+     if (factors > 1) {
+         for (fac in 2:factors) {
+             A1 <- A1 + a.svd$d[fac] * a.svd$u[, fac] %*% t(a.svd$v[,
+                 fac])
+         }
+     }
+     for (i in 1:15) {
+         for (j in 1:40) {
+             if (A1[i, j] < 10^(-9))
+                 A1[i, j] <- 0
+             A1[i, j] <- A1[i, j] + 10^(-12)
+         }
+     }
+     grid.newpage()
+     pushViewport(viewport(layout = grid.layout(15, 40)))
+     for (i in 1:15) {
+         for (j in 1:40) {
+             if (A1[i, j] > 0 & A1[i, j] < 1) {
+                 grid.rect(gp = gpar(fill = grey(A1[i, j])), vp = vplayout(i,
+                   j))
+             }
+             if (A1[i, j] > 1) {
+                 grid.rect(gp = gpar(fill = "white"), vp = vplayout(i,
+                   j))
+             }
+         }
+     }
+ }

Store 15 + 40 numbers instead of 600

> factors <- 1
> draw.image(factors, A1, a.svd)

Exer_9_3-005.jpg

Store 2(15 + 40) numbers instead of 600

> factors <- 2
> draw.image(factors, A1, a.svd)

Exer_9_3-006.jpg

Store 3(15 + 40) numbers instead of 600

> factors <- 3
> draw.image(factors, A1, a.svd)

Exer_9_3-007.jpg

Store 4(15 + 40) numbers instead of 600

> factors <- 4
> draw.image(factors, A1, a.svd)

Exer_9_3-008.jpg

Store 5(15 + 40) numbers instead of 600

> factors <- 5
> draw.image(factors, A1, a.svd)

Exer_9_3-009.jpg

Store 6(15 + 40) numbers instead of 600

> factors <- 6
> draw.image(factors, A1, a.svd)

Exer_9_3-010.jpg

Store 7(15 + 40) numbers instead of 600

> factors <- 7
> draw.image(factors, A1, a.svd)

Exer_9_3-011.jpg

Store 8(15 + 40) numbers instead of 600

> factors <- 8
> draw.image(factors, A1, a.svd)

Exer_9_3-012.jpg

Store 9(15 + 40) numbers instead of 600

> factors <- 9
> draw.image(factors, A1, a.svd)

Exer_9_3-013.jpg

Store 10(15 + 40) numbers instead of 600

> factors <- 10
> draw.image(factors, A1, a.svd)

Exer_9_3-014.jpg

Learnings

  1. Pivot is about 10 and hence 10 rank 1 matrices reproduce the graph entirely 2.As you add more rank 1 matrices the clarity of the picture improves
  2. Instead of storing 600 numbers, you can just store 15+40 times number of rank 1 matrices