library(png)
library(OpenImageR)
Since the large dimensions of the shoe images was causing me some memory issues at first, I used a set of smaller (40 x 40) images for this project instead. The images I used are sprites from the Gameboy Color game Pokemon Yellow. Below, I load the image data into arrays, vectorize the RGB data, and create a matrix of the vectorized image data.
img_names <- list.files(pattern = "\\.png$")
img_num <- length(img_names)
img_test <- readPNG(img_names[1])
img_dim <- dim(img_test)
img_h <- img_dim[1]
img_w <- img_dim[2]
img_z <- img_dim[3]
a <- array(rep(0, img_num * img_h * img_w * img_z), dim =
c(img_num, img_h, img_w, img_z))
for (i in 1:img_num){
img <- readPNG(img_names[i])
a[i,,,] <- array(img, dim = c(1, img_h, img_w, img_z))
}
A <- matrix(0, img_num, prod(img_dim))
for (i in 1:img_num){
img <- readPNG(img_names[i])
r <- as.vector(img[,,1])
g <- as.vector(img[,,2])
b <- as.vector(img[,,3])
A[i,] <- t(c(r, g, b))
}
pokemon <- as.data.frame(t(A))
Below, I plot the original images from which I will be developing eigenpokemon later.
plot_png <- function(path, add = FALSE){
img = readPNG(path, native = TRUE)
res = dim(img)[2:1]
if (!add){
plot(1,1,xlim=c(1,res[1]),ylim=c(1,res[2]),asp=1,type='n',xaxs='i',
yaxs='i',xaxt='n',yaxt='n',xlab='',ylab='',bty='n')
rasterImage(img,1,1,res[1],res[2])
}
}
par(mfrow=c(9,5))
par(mai=c(.05,.05,.05,.05))
for (i in 1:img_num){
plot_png(writePNG(a[i,,,]))
}
Below, I calculate the covariance matrix.
scaled <- scale(pokemon, center = TRUE, scale = TRUE)
mean_pokemon <- attr(scaled, "scaled:center")
std_pokemon <- attr(scaled, "scaled:scale")
Sigma_ <- cor(scaled)
Then I retrieve the eigencomponents from the covariance matrix.
myeigen <- eigen(Sigma_)
b <- cumsum(myeigen$values) / sum(myeigen$values)
The number of principle components needed to capture at least 80% of the variability in the pokemon images in my original data set is 27, so that is the number of eigenimages I plot below.
scaling <- diag(myeigen$values[1:27]^(-1/2)) / (sqrt(nrow(scaled)-1))
eigenpokemon <- scaled %*% myeigen$vectors[,1:27] %*% scaling
par(mfrow=c(2,3))
a_new <- a
dim(a_new) <- c(img_num, img_h * img_w * img_z)
mypca <- princomp(t(as.matrix(a_new)), scores = TRUE, cor = TRUE)
mypca2 <- t(mypca$scores)
dim(mypca2) <- c(img_num, img_h, img_w, img_z)
par(mfrow=c(6,5))
par(mai=c(.05,.05,.05,.05))
for (i in 1:27){
plot_png(writePNG(mypca2[i,,,]))
}
Now I can finally save the new (much reduced) data set, which only contains the 27 principle components for each image needed to capture 80% of the variability in all the images.
x = t(t(eigenpokemon) %*% scaled)
Here is a list of the resources I used to complete this project:
https://rpubs.com/R-Minator/eigenshoes
https://rpubs.com/dherrero12/543854
https://pyimagesearch.com/2021/05/10/opencv-eigenfaces-for-face-recognition