<p><div><div><div><div data-show-faces="false" data-height="21" data-width="100" data-layout="button_count" data-send="true" data-href="https://www.r-bloggers.com/utilizing-k-means-to-extract-colours-from-your-favourite-images/"></div></div><div></div></div><div></div></div>
<div>
(This article was first published on <strong><a href="https://chichacha.netlify.com/2018/11/12/utilizing-k-means-to-extract-colours-from-your-favourite-images/"> R on Chi's Impe[r]fect Blog</a></strong>, and kindly contributed to <a rel="nofollow" href="https://www.r-bloggers.com/">R-bloggers)</a> </div>
<p><br>
<br>
<br>




</p>
<p>I have been playing with package called <a rel="nofollow" href="https://cran.r-project.org/web/packages/imager/index.html" target="_blank">imager</a>, documentation on this package was extremely helpful! I have read through “<a rel="nofollow" href="https://cran.r-project.org/web/packages/imager/vignettes/gettingstarted.html" target="_blank">getting started</a>” as well as <a rel="nofollow" href="http://dahtah.github.io/imager/" target="_blank">few other tutorial &amp; examples</a>.</p>
<p>I love colours… Tools like <a rel="nofollow" href="https://www.colourlovers.com/" target="_blank">colourlovers</a>, <a rel="nofollow" href="https://color.adobe.com/" target="_blank">Adobe Color CC</a>, <a rel="nofollow" href="https://www.canva.com/color-palette/" target="_blank">Canva Color Palette Generators</a> are great extracting colours from photo (or in general just getting <a rel="nofollow" href="https://www.canva.com/learn/100-color-combinations/" target="_blank">inspirations</a> for colour palette), but I wanted to figure out the way to extract colours from image using R.</p>
<div>
<h2>Preps</h2>
<p>Loading up packages &amp; loading up image to R, and extracting RGB info out of image. First I need to load up image. I’m using below abstract image with bunch of different colours that I’ve created with Photoshop just for fun.</p>
<pre><code>library(tidyverse) ##
library(imager) ## such a fun package.  I want to learn more.
library(treemap) ## 
library(ggvoronoi) ## because I'm currently addicted to voronoi diagram.

## Load up the image using load.image function! 
im &lt;- load.image(&quot;https://farm4.staticflickr.com/3316/3333507738_9d36d39f6d_b.jpg&quot;) ## colourful abstract image. 
#im &lt;- load.image(&quot;https://farm9.staticflickr.com/8125/8659010017_54a885f12a_z.jpg&quot;) ## mainly blue
#im &lt;- load.image(&quot;https://farm2.staticflickr.com/1939/30915465767_2d9a733510_z.jpg&quot;) ## animoji! 

## View the image I just loaded. 
plot(im, main=&quot;Original Image I Want To Get Some Colours Out Of!&quot;)</code></pre>
<p><img src="https://i2.wp.com/chichacha.netlify.com/post/2018-11-12-utilizing-k-means-to-extract-colours-from-your-favourite-images_files/figure-html/preperation-1.png?w=450&ssl=1" data-recalc-dims="1"></p>
<pre><code>df_size &lt;-dim(im)[1]*dim(im)[2]  ## numbers of row I'd get if i use it as it is...
max_row_num &lt;- 150000 ## number of maximum row I want (just to limit my size!)

## If df is too big, it's too slow to process on my computer, so shrink the image
shrink_ratio  &lt;- if(df_size > max_row_num) {max_row_num / df_size } else {1}
im &lt;- im %>% imresize(shrink_ratio)
# plot(im) if you want to check how the image has been resized.

## get RGB value at each pixel
im_rgb &lt;- im %>% 
  as.data.frame(wide=&quot;c&quot;) %>%
  rename(red=c.1,green=c.2,blue=c.3) %>%
  mutate(hexvalue = rgb(red,green,blue)) ## you can create hexvalue using red, green blue value!

## turn image into Grayscale and get luminance &quot;value&quot; too. 
im_gray &lt;- im %>%
  grayscale() %>%
  as.data.frame() 

## combine RGB info and Luminance Value Dataset together.
im_df &lt;- im_rgb %>% 
  inner_join(im_gray) 

im_df %>% head()</code></pre>
<pre><code>##   x y         red     green      blue hexvalue     value
## 1 1 1 0.001528153 0.6012714 0.7346048  #0099BB 0.4360151
## 2 2 1 0.003336439 0.5943815 0.7305651  #0198BA 0.4320482
## 3 3 1 0.005112951 0.6265604 0.7657791  #01A0C3 0.4554402
## 4 4 1 0.005520480 0.6726386 0.8097380  #01ACCE 0.4875841
## 5 5 1 0.011926270 0.7021898 0.8367487  #03B3D5 0.5099122
## 6 6 1 0.011128983 0.6695389 0.8149510  #03ABD0 0.4880113</code></pre>
</div>
<div>
<h2>Applying K-Means Algorithm on RGB value from Image</h2>
<p>Using kmeans function is pretty simple, I’m selecting 12 as k in below example, simply because I wanted to get 12 distinct colours from the picture.</p>
<pre><code>## Pick k value to run kMean althorithm.
## But to extract colours, I'd pick k as number I want back! 
my_k &lt;- 12

## Running kmeans algorithm on red, green and blue value to gather similar colour together
kmean_rgb &lt;- kmeans(im_df %>% select(red,green,blue), centers=my_k)

## append cluster id to im_df datasets.
im_df$cluster_num &lt;- kmean_rgb$cluster

## center values can be used as cluster colour! 
kmean_center &lt;- kmean_rgb$centers %>% as.data.frame() %>% 
  mutate(group_hex = rgb(red,green,blue), cluster_num = row_number()) %>%
  inner_join(im_df %>% count(cluster_num))

## I can also save the colour palette for future use as well.
my_colour &lt;- kmean_center$group_hex
my_colour</code></pre>
<pre><code>##  [1] &quot;#12AAD8&quot; &quot;#F178C3&quot; &quot;#E9E0CE&quot; &quot;#DF3658&quot; &quot;#933DB6&quot; &quot;#659634&quot; &quot;#E62AB1&quot;
##  [8] &quot;#73D2B0&quot; &quot;#F5E86F&quot; &quot;#EAC547&quot; &quot;#4363C2&quot; &quot;#93D55F&quot;</code></pre>
<div>
<h3>Viewing Colour Palettes</h3>
<p>I wanted to view the colour palette more visually, instead of HexValues….</p>
<pre><code>num_row = floor(my_k/4)
kmean_center %>% 
  ggplot(aes(x=(cluster_num-1)%%num_row,y=floor((cluster_num-1)/num_row))) + 
  geom_tile(aes(fill=group_hex)) +
  geom_label(aes(label=paste(cluster_num,&quot;:&quot;,group_hex,&quot;\n&quot;,n,&quot;distinct hexvalues&quot;)), 
             family=&quot;Roboto Condensed&quot;, lineheight=0.8) +
  scale_fill_manual(values=sort(kmean_center$group_hex), guide=&quot;none&quot;) +
  theme_void(base_family=&quot;Roboto Condensed&quot;) +
  labs(subtitle=paste0(&quot;k-Mean clustering center colour with &quot;, my_k, &quot; clusters&quot; )) +
  scale_y_reverse()</code></pre>
<p><img src="https://i2.wp.com/chichacha.netlify.com/post/2018-11-12-utilizing-k-means-to-extract-colours-from-your-favourite-images_files/figure-html/colour_palette-1.png?w=450&ssl=1" data-recalc-dims="1"></p>
</div>
</div>
<div>
<h2>Which colours get clustered together?</h2>
<p>I wanted to see which colours were bundled together in same cluster. I took a sample because plotting more colours simply just took way too long on my machine…</p>
<pre><code>im_df %>% 
  sample_n(size=10000) %>% ## I'm just going to take sample to make the drawing bit faster...
  count(cluster_num,hexvalue) %>%
  treemap(index=c(&quot;cluster_num&quot;,&quot;hexvalue&quot;),
          type=&quot;color&quot;,
          vSize=&quot;n&quot;, 
          vColor=&quot;hexvalue&quot;,
          algorithm = &quot;squarified&quot;,
          fontfamily.labels=&quot;Roboto Condensed&quot;, 
          fontfamily.title=&quot;Roboto Condensed&quot;,
          border.col=c(&quot;#ffffff&quot;,&quot;#ffffff50&quot;),
          fontsize.labels=c(24,0),
          aspRatio=16/9,
          title=&quot;Clustering with RGB&quot;)</code></pre>
<p><img src="https://i0.wp.com/chichacha.netlify.com/post/2018-11-12-utilizing-k-means-to-extract-colours-from-your-favourite-images_files/figure-html/treemap_clustered_colour-1.png?w=450&ssl=1" data-recalc-dims="1"></p>
</div>
<div>
<h2>Bonus: Voronoi Abstract Art</h2>
<p>Below is more fun to do on other images, but I wanted to just use <a rel="nofollow" href="https://cran.r-project.org/web/packages/ggvoronoi/index.html" target="_blank">ggvoronoi</a> package because I’m <a rel="nofollow" href="https://chichacha.netlify.com/2018/11/10/voronoi-diagram-with-ggvoronoi-package-with-train-station-data/" target="_blank">currently in love</a>…</p>
<p>Looks like stained glass! <img alt="🙂" src="https://s.w.org/images/core/emoji/2.4/72x72/1f642.png" class="wp-smiley"></p>
<pre><code>## Create Mini sets, choose to select grayscale value that are bigger more often.
im_df_mini &lt;-im_df %>%
  sample_n(size=1000, weight=(1-value)) 

im_df_mini %>%
  ggplot(aes(x=x,y=y)) +
  geom_voronoi(aes(fill=hexvalue), color=&quot;#000000&quot;, size=0.1) +
  scale_fill_manual(values=sort(unique(im_df_mini$hexvalue)), guide=&quot;none&quot;) +
  theme_void() +
  scale_y_reverse() +
  coord_fixed()</code></pre>
<p><img src="https://i1.wp.com/chichacha.netlify.com/post/2018-11-12-utilizing-k-means-to-extract-colours-from-your-favourite-images_files/figure-html/voronoi_art-1.png?w=450&ssl=1" data-recalc-dims="1"></p>
</div>
<div>
<h2>Using Plotly package</h2>
<p>I’ve always been curious to use plotly, but I haven’t had chance to yet. Since RGB values are 3 different values, I wanted to use xyz axis to plot (and I didn’t know how to do that in ggplot2), so here’s yet another way to view how the colour got clustered more visually.</p>
<pre><code>library(plotly)
im_df %>% sample_n(size=2000) %>% 
  plot_ly(x = ~red, y=~blue, z=~green, color=~cluster_num, colors=my_colour, size=~value) %>%
  add_markers()   </code></pre>
<div></div>
<p>
</div>
	<p>
<div>
<div>To <strong>leave a comment</strong> for the author, please follow the link and comment on their blog: <strong><a href="https://chichacha.netlify.com/2018/11/12/utilizing-k-means-to-extract-colours-from-your-favourite-images/"> R on Chi's Impe[r]fect Blog</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 rel="nofollow" href="https://www.r-project.org/" title="The R Project for Statistical Computing">R</a> news and <a rel="nofollow" href="https://www.r-bloggers.com/search/tutorial" title="R tutorials">tutorials</a> on topics such as: <a rel="nofollow" href="https://www.r-bloggers.com/search/data%20science" title="Data science">Data science</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/Big%20Data" title="Big Data">Big Data, <a rel="nofollow" href="https://www.r-users.com/" title="R jobs">R jobs</a>, visualization (<a rel="nofollow" href="https://www.r-bloggers.com/search/ggplot2" title="ggplot and ggplot2 tutorials">ggplot2</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/boxplot" title="Boxplots using lattice and ggplot2 tutorials">Boxplots</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/map" title="Maps and gis">maps</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/animation" title="Animation in R">animation</a>), programming (<a rel="nofollow" href="https://www.r-bloggers.com/search/RStudio" title="RStudio IDE for R">RStudio</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/sweave" title="Sweave and literate programming">Sweave</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/LaTeX" title="LaTeX in R">LaTeX</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/SQL" title="SQL and databases">SQL</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/eclipse" title="Eclipse IDE for R">Eclipse</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/git" title="git and github, Version Control System">git</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/hadoop" title="Large data in R using Hadoop">hadoop</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/Web+Scraping" title="Web Scraping of google, facebook, yahoo, twitter and more using R">Web Scraping</a>) statistics (<a rel="nofollow" href="https://www.r-bloggers.com/search/regression" title="Regressions and ANOVA analysis tutorials">regression</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/PCA" title="principal component analysis tutorial">PCA</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/time+series" title="Time series">time series</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/trading" title="finance trading">trading</a>) and more...
<img width="1" alt="" src="http://feeds.feedburner.com/~r/RBloggers/~4/5SJLKcrNeMw" height="1"></a></div>