<p><div><div><div><div data-width="100" data-show-faces="false" data-send="true" data-layout="button_count" data-height="21" data-href="https://www.r-bloggers.com/image-compression-with-principal-component-analysis/"></div></div><div></div></div><div></div></div>
<div>
(This article was first published on <strong><a href="http://www.aaronschlegel.com/image-compression-principal-component-analysis/"> R – Aaron Schlegel</a></strong>, and kindly contributed to <a rel="nofollow" href="https://www.r-bloggers.com/">R-bloggers)</a> </div>
<p>Image compression with <a target="_blank" rel="nofollow" href="http://wp.me/p4aZEo-5Q0">principal component analysis</a> is a frequently occurring application of the dimension reduction technique. Recall from a previous post that employed <a target="_blank" rel="nofollow" href="http://wp.me/p4aZEo-5Od">singular value decomposition to compress an image</a>, that an image is a matrix of pixels represented by RGB color values. Thus, principal component analysis can be used to reduce the dimensions of the matrix (image) and project those new dimensions to reform the image that retains its qualities but is smaller in k-weight. We will use PCA to compress the image of a cute kitty cat below. As the number of principal components used to project the new data increases, the quality and representation compared to the original image improve.</p>
<p><a target="_blank" rel="nofollow" href="http://www.aaronschlegel.com/?attachment_id=22455"><img sizes="(max-width: 600px) 100vw, 600px" alt="" class="wp-image-22455" src="https://i0.wp.com/www.aaronschlegel.com/wp-content/uploads/cat.jpg?resize=600%2C398" data-recalc-dims="1"></a></p>
<h6>Image Compression with Principal Component Analysis</h6>
<p>The <a target="_blank" rel="nofollow" href="https://cran.r-project.org/web/packages/jpeg/">jpeg package</a> is very handy for reading and writing .jpeg files.</p>
<pre>
library(jpeg)
</pre>
<p>The <code>readJPEG</code> function is used to convert the image into its matrix representation.</p>
<pre>
cat &lt;- readJPEG('cat.jpg')
ncol(cat)
## [1] 600
</pre>
<pre>
nrow(cat)
## [1] 398
</pre>
<p>The cat image is now represented as three 600×398 matrices as an array with each matrix corresponding to the RGB color value scheme. Extract the individual color value matrices to perform PCA on each.</p>
<pre>
r &lt;- cat[,,1]
g &lt;- cat[,,2]
b &lt;- cat[,,3]
</pre>
<p>Principal component analysis is performed on each color value matrix. As this example is focused on image compression and not description or interpretation of the variables, the data does not require centering (subtracting the variable means from the respective observation vectors), and the <code>center</code> argument is set to <code>FALSE</code>. If the argument is not set to <code>FALSE</code>, the returned image will not have the right RGB values due to having their respective means subtracted from each pixel color vector.</p>
<pre>
cat.r.pca &lt;- prcomp(r, center = FALSE)
cat.g.pca &lt;- prcomp(g, center = FALSE)
cat.b.pca &lt;- prcomp(b, center = FALSE)
</pre>
<p>Collect the PCA objects into a list.</p>
<pre>
rgb.pca &lt;- list(cat.r.pca, cat.g.pca, cat.b.pca)
</pre>
<p>We are now ready to compress the image! Now that the principal components are found for each color value matrix, we have new dimensions that describe the original data (pixels). The pixel values are then projected onto the new dimensions of the data for each respective matrix.</p>
<p>The following loop reconstructs the original image using the projections of the data using increasing amounts of principal components. We will see that as the number of principal components increase, the more representative of the original image the reconstruction becomes. This sequential improvement in quality is because as more principal components are used, the more the variance (information) is described. The first few principal components will have the most drastic change in quality while the last few components will not make much if any, difference to quality.</p>
<pre>
for (i in seq.int(3, round(nrow(cat) - 10), length.out = 10)) {
  pca.img &lt;- sapply(rgb.pca, function(j) {
    compressed.img &lt;- j$x[,1:i] %*% t(j$rotation[,1:i])
  }, simplify = 'array')
  writeJPEG(pca.img, paste('compressed/cat_compressed_', round(i,0), '_components.jpg', sep = ''))
}
</pre>
<p>With three components, the resulting image retains very few of the original image’s characteristics.</p>
<p>
3 Components
</p>
<p><a target="_blank" rel="nofollow" href="http://www.aaronschlegel.com/?attachment_id=22456"><img sizes="(max-width: 600px) 100vw, 600px" alt="cat image with 3 principal components" class="wp-image-22456" src="https://i1.wp.com/www.aaronschlegel.com/wp-content/uploads/cat_compressed_3_components.jpg?resize=600%2C398" data-recalc-dims="1"></a></p>
<p>
46 Components
</p>
<p><a target="_blank" rel="nofollow" href="http://www.aaronschlegel.com/?attachment_id=22456"><img sizes="(max-width: 600px) 100vw, 600px" alt="cat image with 46 principal components" class="wp-image-22456" src="https://i1.wp.com/www.aaronschlegel.com/wp-content/uploads/cat_compressed_3_components.jpg?resize=600%2C398" data-recalc-dims="1"></a></p>
<p>Wow! With just 43 additional components (out of 398 total), the image is much clearer and representative of the original. Remember the first principal components retain the most variation, so we are likely to see significant gains in quality for the first few iterations.</p>
<p>The images reconstructed from 89 to 260 components are very similar, and only slight gains in quality are made after each iteration.</p>
<p>
89 Components
</p>
<p><a target="_blank" rel="nofollow" href="http://www.aaronschlegel.com/?attachment_id=22458"><img sizes="(max-width: 600px) 100vw, 600px" alt="cat image with 89 principal components" class="wp-image-22458" src="https://i1.wp.com/www.aaronschlegel.com/wp-content/uploads/cat_compressed_89_components.jpg?resize=600%2C398" data-recalc-dims="1"></a></p>
<p>
131 Components
</p>
<p><a target="_blank" rel="nofollow" href="http://www.aaronschlegel.com/?attachment_id=22459"><img sizes="(max-width: 600px) 100vw, 600px" alt="cat image with 131 principal components" class="wp-image-22459" src="https://i2.wp.com/www.aaronschlegel.com/wp-content/uploads/cat_compressed_131_components.jpg?resize=600%2C398" data-recalc-dims="1"></a></p>
<p>
174 Components
</p>
<p><a target="_blank" rel="nofollow" href="http://www.aaronschlegel.com/?attachment_id=22460"><img sizes="(max-width: 600px) 100vw, 600px" alt="cat image with 174 principal components" class="wp-image-22460" src="https://i2.wp.com/www.aaronschlegel.com/wp-content/uploads/cat_compressed_174_components.jpg?resize=600%2C398" data-recalc-dims="1"></a></p>
<p>
217 Components
</p>
<p><a target="_blank" rel="nofollow" href="http://www.aaronschlegel.com/?attachment_id=22461"><img sizes="(max-width: 600px) 100vw, 600px" alt="cat image with 217 principal components" class="wp-image-22461" src="https://i0.wp.com/www.aaronschlegel.com/wp-content/uploads/cat_compressed_217_components.jpg?resize=600%2C398" data-recalc-dims="1"></a></p>
<p>
260 Components
</p>
<p><a target="_blank" rel="nofollow" href="http://www.aaronschlegel.com/?attachment_id=22462"><img sizes="(max-width: 600px) 100vw, 600px" alt="cat image with 260 principal components" class="wp-image-22462" src="https://i0.wp.com/www.aaronschlegel.com/wp-content/uploads/cat_compressed_260_components.jpg?resize=600%2C398" data-recalc-dims="1"></a></p>
<p>The recreated image with 302 components is identical to the original (at least to me). The remaining iterations will, therefore, have little improvement.</p>
<p>
302 Components
</p>
<p><a target="_blank" rel="nofollow" href="http://www.aaronschlegel.com/?attachment_id=22463"><img sizes="(max-width: 600px) 100vw, 600px" alt="cat image with 302 principal components" class="wp-image-22463" src="https://i0.wp.com/www.aaronschlegel.com/wp-content/uploads/cat_compressed_302_components.jpg?resize=600%2C398" data-recalc-dims="1"></a></p>
<p>
345 Components
</p>
<p><a target="_blank" rel="nofollow" href="http://www.aaronschlegel.com/?attachment_id=22464"><img sizes="(max-width: 600px) 100vw, 600px" alt="cat image with 345 principal components" class="wp-image-22464" src="https://i2.wp.com/www.aaronschlegel.com/wp-content/uploads/cat_compressed_345_components.jpg?resize=600%2C398" data-recalc-dims="1"></a></p>
<p>
388 Components
</p>
<p><a target="_blank" rel="nofollow" href="http://www.aaronschlegel.com/?attachment_id=22465"><img sizes="(max-width: 600px) 100vw, 600px" alt="cat image with 388 principal components" class="wp-image-22465" src="https://i0.wp.com/www.aaronschlegel.com/wp-content/uploads/cat_compressed_388_components.jpg?resize=600%2C398" data-recalc-dims="1"></a></p>
<p>We can check the compression ratio for each iteration compared to the original image with a quick loop.</p>
<pre>
original &lt;- file.info('cat.jpg')$size / 1000
imgs &lt;- dir('compressed/')

for (i in imgs) {
  full.path &lt;- paste('compressed/', i, sep='')
  print(paste(i, ' size: ', file.info(full.path)$size / 1000, ' original: ', original, ' % diff: ', round((file.info(full.path)$size / 1000 - original) / original, 2) * 100, '%', sep = ''))
}
## [1] &quot;cat_compressed_131_components.jpg size: 31.221 original: 51.579 % diff: -39%&quot;
## [1] &quot;cat_compressed_174_components.jpg size: 31.644 original: 51.579 % diff: -39%&quot;
## [1] &quot;cat_compressed_217_components.jpg size: 31.63 original: 51.579 % diff: -39%&quot;
## [1] &quot;cat_compressed_260_components.jpg size: 31.256 original: 51.579 % diff: -39%&quot;
## [1] &quot;cat_compressed_3_components.jpg size: 17.113 original: 51.579 % diff: -67%&quot;
## [1] &quot;cat_compressed_302_components.jpg size: 31.028 original: 51.579 % diff: -40%&quot;
## [1] &quot;cat_compressed_345_components.jpg size: 31.009 original: 51.579 % diff: -40%&quot;
## [1] &quot;cat_compressed_388_components.jpg size: 31.013 original: 51.579 % diff: -40%&quot;
## [1] &quot;cat_compressed_46_components.jpg size: 29.133 original: 51.579 % diff: -44%&quot;
## [1] &quot;cat_compressed_89_components.jpg size: 30.616 original: 51.579 % diff: -41%&quot;
</pre>
<p>Image compression with principal component analysis reduced the original image by 40% with little to no loss in image quality. Although there are more sophisticated algorithms for image compression, PCA can still provide good compression ratios for the cost of implementation.</p>
<h6>Summary</h6>
<p>Image compression with principal component analysis is a useful and relatively straightforward application of the technique by imaging an image as a <span data-display="false" class="wp-katex-eq">(n \times p)</span> or <span data-display="false" class="wp-katex-eq">(n \times n)</span> matrix made of pixel color values. There are many other real-world applications of PCA, including face and handwriting recognition, and other situations when dealing with many variables such as gene expression experiments.</p>
<h6>References</h6>
<p><a target="_blank" rel="nofollow" href="http://www.scielo.br/scielo.php?script=sci_arttext&pid=S1679-45082012000200004">http://www.scielo.br/scielo.php?script=sci_arttext&amp;pid=S1679-45082012000200004</a></p>
<p>The post <a target="_blank" rel="nofollow" href="http://www.aaronschlegel.com/image-compression-principal-component-analysis/">Image Compression with Principal Component Analysis</a> appeared first on <a target="_blank" rel="nofollow" href="http://www.aaronschlegel.com/">Aaron Schlegel</a>.</p>
<p>
<div>
<div>To <strong>leave a comment</strong> for the author, please follow the link and comment on their blog: <strong><a href="http://www.aaronschlegel.com/image-compression-principal-component-analysis/"> R – Aaron Schlegel</a></strong>.</div>
<hr>
<a rel="nofollow" href="https://www.r-bloggers.com/">R-bloggers.com</a> offers <strong><a rel="nofollow" href="https://feedburner.google.com/fb/a/mailverify?uri=RBloggers">daily e-mail updates</a></strong> about <a title="The R Project for Statistical Computing" rel="nofollow" href="https://www.r-project.org/">R</a> news and <a title="R tutorials" rel="nofollow" href="https://www.r-bloggers.com/search/tutorial">tutorials</a> on topics such as: <a title="Data science" rel="nofollow" href="https://www.r-bloggers.com/search/data%20science">Data science</a>, <a title="Big Data" rel="nofollow" href="https://www.r-bloggers.com/search/Big%20Data">Big Data, <a title="R jobs" rel="nofollow" href="https://www.r-users.com/">R jobs</a>, visualization (<a title="ggplot and ggplot2 tutorials" rel="nofollow" href="https://www.r-bloggers.com/search/ggplot2">ggplot2</a>, <a title="Boxplots using lattice and ggplot2 tutorials" rel="nofollow" href="https://www.r-bloggers.com/search/boxplot">Boxplots</a>, <a title="Maps and gis" rel="nofollow" href="https://www.r-bloggers.com/search/map">maps</a>, <a title="Animation in R" rel="nofollow" href="https://www.r-bloggers.com/search/animation">animation</a>), programming (<a title="RStudio IDE for R" rel="nofollow" href="https://www.r-bloggers.com/search/RStudio">RStudio</a>, <a title="Sweave and literate programming" rel="nofollow" href="https://www.r-bloggers.com/search/sweave">Sweave</a>, <a title="LaTeX in R" rel="nofollow" href="https://www.r-bloggers.com/search/LaTeX">LaTeX</a>, <a title="SQL and databases" rel="nofollow" href="https://www.r-bloggers.com/search/SQL">SQL</a>, <a title="Eclipse IDE for R" rel="nofollow" href="https://www.r-bloggers.com/search/eclipse">Eclipse</a>, <a title="git and github, Version Control System" rel="nofollow" href="https://www.r-bloggers.com/search/git">git</a>, <a title="Large data in R using Hadoop" rel="nofollow" href="https://www.r-bloggers.com/search/hadoop">hadoop</a>, <a title="Web Scraping of google, facebook, yahoo, twitter and more using R" rel="nofollow" href="https://www.r-bloggers.com/search/Web+Scraping">Web Scraping</a>) statistics (<a title="Regressions and ANOVA analysis tutorials" rel="nofollow" href="https://www.r-bloggers.com/search/regression">regression</a>, <a title="principal component analysis tutorial" rel="nofollow" href="https://www.r-bloggers.com/search/PCA">PCA</a>, <a title="Time series" rel="nofollow" href="https://www.r-bloggers.com/search/time+series">time series</a>, <a title="finance trading" rel="nofollow" href="https://www.r-bloggers.com/search/trading">trading</a>) and more...
<img height="1" alt="" width="1" src="http://feeds.feedburner.com/~r/RBloggers/~4/tuGLk7EwDQg"></a></div>