First, we will run the installment of our packages that we will use later on. Second is selection of libraries. Next is the jpg file that we will use in order to demonstrate how the method works.

photo<-readJPEG("panda-bamboo.jpg")

Then we will look at both methods of visualizing our image.

1 is the essential way -

image_read(photo)

But there is 2nd way too - by plotting

plot(1, type="n") 
rasterImage(photo, 0.6, 0.6, 1.4, 1.4)

photo.sum<-photo[,,1]+photo[,,2]+photo[,,3] 
photo.bw<-photo.sum/max(photo.sum)

Next is same plotting as in first time, but now in B&W style

plot(1, type="n")   
rasterImage(photo.bw, 0.6, 0.6, 1.4, 1.4)

Each color scale (R,G,B) gets own matrix and own PCA Individual matrix of R colour component

r<-photo[,,1] 
g<-photo[,,2]
b<-photo[,,3]

r.pca<-prcomp(r, center=FALSE, scale.=FALSE)
g.pca<-prcomp(g, center=FALSE, scale.=FALSE)
b.pca<-prcomp(b, center=FALSE, scale.=FALSE)
rgb.pca<-list(r.pca, g.pca, b.pca)

Below we will see why it is important to use In my case we can see that in my image we have more of Green color, which is followed by Red and Blue, respectively.

f1<-fviz_eig(r.pca, main="Red", barfill="red", ncp=8, addlabels=TRUE)
f2<-fviz_eig(g.pca, main="Green", barfill="green", ncp=8, addlabels=TRUE)
f3<-fviz_eig(b.pca, main="Blue", barfill="blue", ncp=8, addlabels=TRUE)

grid.arrange(f1, f2, f3, ncol=3)

However, there are 2 ways One is with percentage as I showed above, and the other would be with number of pixels of each color We can again observe that the number of pixels will be ordered in same way - GREEn,RED,BLUE

e1<-fviz_eig(r.pca, choice = 'eigenvalue', main="Red", barfill="red", ncp=8, addlabels=TRUE)
e2<-fviz_eig(g.pca, choice = 'eigenvalue', main="Green", barfill="green", ncp=8, addlabels=TRUE)
e3<-fviz_eig(b.pca, choice = 'eigenvalue', main="Blue", barfill="blue", ncp=8, addlabels=TRUE)

grid.arrange(e1, e2, e3, ncol=3)

vec<-seq.int(3, round(nrow(photo)), length.out=9)

for(i in vec){
  photo.pca<-sapply(rgb.pca, function(j) {
    new.RGB<-j$x[,1:i] %*% t(j$rotation[,1:i])}, simplify="array")
  assign(paste("photo_", round(i,0), sep=""), photo.pca) # saving as object
  writeJPEG(photo.pca, paste("photo_", round(i,0), "_princ_comp.jpg", sep=""))
}
par(mfrow=c(4,4)) 
par(mar=c(1,1,1,1))

plot(image_read(get(paste("photo_", round(vec[1],0), sep=""))))
plot(image_read(get(paste("photo_", round(vec[1],0), sep=""))))
plot(image_read(get(paste("photo_", round(vec[2],0), sep=""))))
plot(image_read(get(paste("photo_", round(vec[3],0), sep=""))))
plot(image_read(get(paste("photo_", round(vec[4],0), sep=""))))
plot(image_read(get(paste("photo_", round(vec[5],0), sep=""))))
plot(image_read(get(paste("photo_", round(vec[6],0), sep=""))))
plot(image_read(get(paste("photo_", round(vec[7],0), sep=""))))
plot(image_read(get(paste("photo_", round(vec[8],0), sep=""))))
plot(image_read(get(paste("photo_", round(vec[9],0), sep=""))))

We can see above how with each time we increase the number, the photo gets sharper and sharper, the reason is that those are the number of principal components, which are directly related to the quality. especially the difference is see when shifting from n=1 to n=2.

And now after all previous iformation on PCs, we can look at how much there is a difference between original and the compressed photos of our Panda. And we’ll look at how the size will decrease under the PC compression

sizes<-matrix(0, nrow=9, ncol=4)

colnames(sizes)<-c("Number of PC", "Photo size", "Compression ratio", "MSE-Mean Squared Error")

sizes[,1]<-round(vec,0)

for(i in 1:9) {
  path<-paste("photo_", round(vec[i],0), "_princ_comp.jpg", sep="")
  sizes[i,2]<-file.info(path)$size 
  photo_mse<-readJPEG(path)
  sizes[i,4]<-mse(photo, photo_mse) # from Metrics::
}
sizes[,3]<-round(as.numeric(sizes[,2])/as.numeric(sizes[9,2]),3)
sizes
##       Number of PC Photo size Compression ratio MSE-Mean Squared Error
##  [1,]            3      55279             0.780           0.0725503376
##  [2,]           66     120440             1.699           0.0235384240
##  [3,]          130     114692             1.618           0.0117734596
##  [4,]          193     100890             1.423           0.0059531000
##  [5,]          256      87232             1.230           0.0030938713
##  [6,]          320      79151             1.116           0.0019431249
##  [7,]          383      75392             1.063           0.0013951126
##  [8,]          447      72221             1.019           0.0008702037
##  [9,]          510      70897             1.000           0.0007282784

Now when we look at the size we can see, how much of compression actually there is We can also see how many PCs there are in each one of them And we can witness the relation between the ratio of compression and number of components. The more there are principal components the more is the ratio of compression, meaning that the photo will come out more and more detailed.

But the most interesting thing is the title of our project - dimensionality reduction - size Looking at size we can see that by reducing the dimensionality we were able to decrease the size of photo, with keeping the quality.

We can see it evidently from the moment when the number of Principal Components are 193. We witness a decrease of 29.993 from 193 to 510.

So we not only kept the quality but also reduced the size of photo.

In conclusion, I can say that it is a great tool for reduction of size but with preserving the quality of initial photo.

P.S. Taking into consideration my lack of expertise in coding I might assume that this method might also be used in reverse, by that I mean that this method can be used in order to detect faces(blurry faces) on security cameras etc. but I might be wrong.