<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/rainbowing-a-set-of-pictures/"></div></div><div></div></div><div></div></div>
<div>
(This article was first published on <strong><a href="http://www.masalmon.eu/2018/01/07/rainbowing/"> Maëlle</a></strong>, and kindly contributed to <a rel="nofollow" href="https://www.r-bloggers.com/">R-bloggers)</a> </div>
<p>I’ve now down a few collages from R using <code>magick</code>: <a rel="nofollow" href="http://www.masalmon.eu/2017/03/19/facesofr/" target="_blank">the faces of #rstats Twitter</a>, <a rel="nofollow" href="http://livefreeordichotomize.com/2017/07/18/the-making-of-we-r-ladies/" target="_blank">We R-Ladies</a> with Lucy D’Agostino McGowan, and <a rel="nofollow" href="https://github.com/rladies/rladies_holidays" target="_blank">a holiday card for R-Ladies</a>. The faces of #rstats Twitter and holiday card collages were arranged at random, while the We R-Ladies one was a mosaic forming the R-Ladies logo. I got the idea to up my collage skills by trying to learn how to arrange pics by their main colour, like a rainbow. The verb rainbow doesn’t exist, and <a rel="nofollow" href="https://en.wikipedia.org/wiki/Rainbowing" target="_blank">“rainbowing”</a> doesn’t mean ordering by colour, but I didn’t let this stop me.</p>
<p>It was the occasion to grab some useful knowledge about colours, not useless for someone who did not even know about <a rel="nofollow" href="https://en.wikipedia.org/wiki/Pantone#Color_of_the_Year" target="_blank">Pantone’s Colors of the Year</a> a few weeks ago…</p>
<p><em>This post has nothing to do with Kesha’s new album. However, you can listen to it while reading since it’s so good, but maybe switch to something older from her when I use “$”.</em></p>
<p><span></span></p>
<h1>Getting some pics to play with</h1>
<p>The first pictures I tried to arrange were all the pictures ever posted by R-Ladies local chapters on their Twitter account. While it was fun to grab them all, it was not very interesting to play with them as so many of them were pictures of screens. I therefore grabbed “nature” pictures from <a rel="nofollow" href="https://www.pexels.com/" target="_blank">Pexels</a> using the same method [as when creating the Bubblegum Puppies] following <a rel="nofollow" href="https://stackoverflow.com/questions/29861117/r-rvest-scraping-a-dynamic-ecommerce-page" target="_blank">this Stack Overflow thread</a>. I chose “nature” as a keyword because 1) it lead to many hits 2) it offered a good variety of colours.</p>
<div>
<div>
<pre><code><span>library</span><span>(</span><span>&quot;rvest&quot;</span><span>)</span><span>
</span><span>library</span><span>(</span><span>&quot;RSelenium&quot;</span><span>)</span><span>
</span><span>library</span><span>(</span><span>&quot;magrittr&quot;</span><span>)</span><span>
</span><span>rD</span><span> </span><span>&lt;-</span><span> </span><span>rsDriver</span><span>()</span><span>
</span><span>remDr</span><span> </span><span>&lt;-</span><span> </span><span>rD</span><span>[[</span><span>&quot;client&quot;</span><span>]]</span><span>
</span><span># open the webpage</span><span>
</span><span>remDr</span><span>$</span><span>navigate</span><span>(</span><span>&quot;https://www.pexels.com/search/nature/&quot;</span><span>)</span><span>
</span><span># scroll down</span><span>
</span><span>for</span><span>(</span><span>i</span><span> </span><span>in</span><span> </span><span>1</span><span>:</span><span>130</span><span>){</span><span> </span><span>remDr</span><span>$</span><span>executeScript</span><span>(</span><span>paste</span><span>(</span><span>&quot;scroll(0,&quot;</span><span>,</span><span>i</span><span>*</span><span>10000</span><span>,</span><span>&quot;);&quot;</span><span>),</span><span>
</span><span>args</span><span> </span><span>=</span><span> </span><span>list</span><span>(</span><span>&quot;dummy&quot;</span><span>))</span><span>
</span><span># be nice and wait</span><span>
</span><span>Sys.sleep</span><span>(</span><span>1</span><span>)</span><span> </span><span>}</span><span>
</span><span># https://www.pexels.com/faq/</span><span>
</span><span>page_content</span><span> </span><span>&lt;-</span><span> </span><span>remDr</span><span>$</span><span>getPageSource</span><span>()</span><span> </span><span>remDr</span><span>$</span><span>close</span><span>()</span><span>
</span><span>get_link_from_src</span><span> </span><span>&lt;-</span><span> </span><span>function</span><span>(</span><span>node</span><span>){</span><span>
</span><span>xml2</span><span>::</span><span>xml_attrs</span><span>(</span><span>node</span><span>)[</span><span>&quot;src&quot;</span><span>]</span><span> </span><span>%>%</span><span>
</span><span>as.character</span><span>()</span><span> </span><span>%>%</span><span>
</span><span>stringr</span><span>::</span><span>str_replace</span><span>(</span><span>&quot;\\?h.*&quot;</span><span>,</span><span> </span><span>&quot;&quot;</span><span>)</span><span>
</span><span>}</span><span>
</span><span>xtract_pic_links</span><span> </span><span>&lt;-</span><span> </span><span>function</span><span>(</span><span>source</span><span>)</span><span> </span><span>{</span><span>
</span><span>css</span><span> </span><span>&lt;-</span><span> </span><span>'.photo-item__img'</span><span>
</span><span>read_html</span><span>(</span><span>source</span><span>[[</span><span>1</span><span>]])</span><span> </span><span>%>%</span><span>
</span><span>html_nodes</span><span>(</span><span>css</span><span>)</span><span> </span><span>%>%</span><span>
</span><span>purrr</span><span>::</span><span>map_chr</span><span>(</span><span>get_link_from_src</span><span>)</span><span> </span><span>}</span><span>
</span><span>links</span><span> </span><span>&lt;-</span><span> </span><span>xtract_pic_links</span><span>(</span><span>page_content</span><span>)</span><span>
</span><span>links</span><span> </span><span>&lt;-</span><span> </span><span>links</span><span>[</span><span>1</span><span>:</span><span>1400</span><span>]</span><span>
</span><span># save</span><span>
</span><span>dir.create</span><span>(</span><span>&quot;nature&quot;</span><span>)</span><span>
</span><span>save_pic</span><span> </span><span>&lt;-</span><span> </span><span>function</span><span>(</span><span>url</span><span>){</span><span>
</span><span>Sys.sleep</span><span>(</span><span>1</span><span>)</span><span>
</span><span>name</span><span> </span><span>&lt;-</span><span> </span><span>stringr</span><span>::</span><span>str_replace</span><span>(</span><span>url</span><span>,</span><span> </span><span>&quot;.*\\/&quot;</span><span>,</span><span> </span><span>&quot;&quot;</span><span>)</span><span>
</span><span>try</span><span>(</span><span>magick</span><span>::</span><span>image_read</span><span>(</span><span>url</span><span>)</span><span> </span><span>%>%</span><span>
</span><span>magick</span><span>::</span><span>image_write</span><span>(</span><span>paste0</span><span>(</span><span>&quot;nature/&quot;</span><span>,</span><span> </span><span>name</span><span>)),</span><span>
</span><span>silent</span><span> </span><span>=</span><span> </span><span>TRUE</span><span>)</span><span>
</span><span>}</span><span>
</span><span>purrr</span><span>::</span><span>walk</span><span>(</span><span>links</span><span>,</span><span> </span><span>save_pic</span><span>)</span><span>
</span></code></pre>
</div>
</div>
<h1>Extracting the main colour and making pics size-compatible</h1>
<p>In the following code, I extracted the main colour from each pic using <a rel="nofollow" href="http://www.mepheoscience.com/colourful-ecology-part-1-extracting-colours-from-an-image-and-selecting-them-using-community-phylogenetics-theory/" target="_blank">Russel Dinnage’s method</a> as presented <a rel="nofollow" href="http://blog.revolutionanalytics.com/2015/03/color-extraction-with-r.html" target="_blank">in this blog post from David Smith</a>. Before that I had to install two packages from Github, <a rel="nofollow" href="https://github.com/ramnathv/rblocks" target="_blank"><code>rblocks</code></a> and <a rel="nofollow" href="https://github.com/woobe/rPlotter" target="_blank"><code>rPlotter</code></a>.</p>
<p>This code also serves another role: since I wanted to paste pics together at some point, I decided to make them all of the same dimensions by adding a border with <code>magick</code>. I had learnt how to do that when preparing <a rel="nofollow" href="https://github.com/rladies/rladies_holidays" target="_blank">R-Ladies Global holiday card</a>, but this time instead of using the same colour every time (R-Ladies’ official purple), I used the main colour I’d just extracted. The most important points to make a picture a square are to know <code>magick::image_info</code> gives you the height and width of an image… and to somehow understand geometry which was embarrassingly a hurdle when I did that.</p>
<p>The code to extract colours didn’t work in a few cases which I did not investigate a lot: I had downloaded more pics than what I needed because I had experienced the issue when working with R-Ladies meetups pics, and had seen it was because of seemingly bicolor pics.</p>
<div>
<div>
<pre><code><span>dir.create</span><span>(</span><span>&quot;formatted_pics&quot;</span><span>)</span><span>
</span><span>format_image</span><span> </span><span>&lt;-</span><span> </span><span>function</span><span>(</span><span>path</span><span>){</span><span>
</span><span>image</span><span> </span><span>&lt;-</span><span> </span><span>magick</span><span>::</span><span>image_read</span><span>(</span><span>path</span><span>)</span><span>
</span><span>info</span><span> </span><span>&lt;-</span><span> </span><span>magick</span><span>::</span><span>image_info</span><span>(</span><span>image</span><span>)</span><span>
</span><span># find in which direction I need to add pixels</span><span>
</span><span># to make this a square</span><span>
</span><span>direction</span><span> </span><span>&lt;-</span><span> </span><span>ifelse</span><span>(</span><span>info</span><span>$</span><span>height</span><span> </span><span>></span><span> </span><span>info</span><span>$</span><span>width</span><span>,</span><span>
</span><span>&quot;height&quot;</span><span>,</span><span> </span><span>&quot;width&quot;</span><span>)</span><span>
</span><span>scale_number</span><span> </span><span>&lt;-</span><span> </span><span>as.numeric</span><span>(</span><span>info</span><span>[</span><span>direction</span><span>]</span><span>/</span><span>500</span><span>)</span><span>
</span><span>image</span><span> </span><span>&lt;-</span><span> </span><span>magick</span><span>::</span><span>image_scale</span><span>(</span><span>image</span><span>,</span><span> </span><span>paste0</span><span>(</span><span>info</span><span>[</span><span>&quot;width&quot;</span><span>]</span><span>/</span><span>scale_number</span><span>,</span><span>
</span><span>&quot;x&quot;</span><span>,</span><span> </span><span>info</span><span>[</span><span>&quot;height&quot;</span><span>]</span><span>/</span><span>scale_number</span><span>))</span><span>
</span><span>newinfo</span><span> </span><span>&lt;-</span><span> </span><span>magick</span><span>::</span><span>image_info</span><span>(</span><span>image</span><span>)</span><span>
</span><span># colours</span><span>
</span><span>colours</span><span> </span><span>&lt;-</span><span> </span><span>try</span><span>(</span><span>rPlotter</span><span>::</span><span>extract_colours</span><span>(</span><span>path</span><span>,</span><span> </span><span>num_col</span><span> </span><span>=</span><span> </span><span>1</span><span>),</span><span> </span><span>silent</span><span> </span><span>=</span><span> </span><span>TRUE</span><span>)</span><span>
</span><span># one pic at least was problematic </span><span>
</span><span>if</span><span>(</span><span>!</span><span>is</span><span>(</span><span>colours</span><span>,</span><span> </span><span>&quot;try-error&quot;</span><span>)){</span><span>
</span><span>colour</span><span> </span><span>&lt;-</span><span> </span><span>colours</span><span>[</span><span>1</span><span>]</span><span>
</span><span>image</span><span> </span><span>&lt;-</span><span> </span><span>magick</span><span>::</span><span>image_border</span><span>(</span><span>image</span><span>,</span><span> </span><span>colour</span><span>,</span><span> </span><span>paste0</span><span>((</span><span>500</span><span>-</span><span>newinfo</span><span>$</span><span>width</span><span>)</span><span>/</span><span>2</span><span>,</span><span> </span><span>&quot;x&quot;</span><span>,</span><span>
</span><span>(</span><span>500</span><span>-</span><span>newinfo</span><span>$</span><span>height</span><span>)</span><span>/</span><span>2</span><span>))</span><span>
</span><span>info</span><span> </span><span>&lt;-</span><span> </span><span>magick</span><span>::</span><span>image_info</span><span>(</span><span>image</span><span>)</span><span>
</span><span># odd numbers out!</span><span>
</span><span>if</span><span>(</span><span>info</span><span>$</span><span>height</span><span>/</span><span>2</span><span> </span><span>!=</span><span> </span><span>floor</span><span>(</span><span>info</span><span>$</span><span>height</span><span>/</span><span>2</span><span>)){</span><span>
</span><span>image</span><span> </span><span>&lt;-</span><span> </span><span>magick</span><span>::</span><span>image_crop</span><span>(</span><span>image</span><span>,</span><span> </span><span>&quot;0x500+0&quot;</span><span>)</span><span>
</span><span>}</span><span>
</span><span>if</span><span>(</span><span>info</span><span>$</span><span>width</span><span>/</span><span>2</span><span> </span><span>!=</span><span> </span><span>floor</span><span>(</span><span>info</span><span>$</span><span>width</span><span>/</span><span>2</span><span>)){</span><span>
</span><span>image</span><span> </span><span>&lt;-</span><span> </span><span>magick</span><span>::</span><span>image_crop</span><span>(</span><span>image</span><span>,</span><span> </span><span>&quot;500x0+0&quot;</span><span>)</span><span>
</span><span>}</span><span>
</span><span>magick</span><span>::</span><span>image_write</span><span>(</span><span>image</span><span>,</span><span>
</span><span>stringr</span><span>::</span><span>str_replace</span><span>(</span><span>path</span><span>,</span><span> </span><span>&quot;nature&quot;</span><span>,</span><span> </span><span>&quot;formatted_pics&quot;</span><span>))</span><span>
</span><span>tibble</span><span>::</span><span>tibble</span><span>(</span><span>path</span><span> </span><span>=</span><span> </span><span>path</span><span>,</span><span>
</span><span>colour</span><span> </span><span>=</span><span> </span><span>colour</span><span>)</span><span>
</span><span>}</span><span>else</span><span>{</span><span>
</span><span>NULL</span><span>
</span><span>}</span><span>
</span><span>}</span><span>
</span><span>pics_main_colours</span><span> </span><span>&lt;-</span><span> </span><span>purrr</span><span>::</span><span>map_df</span><span>(</span><span>dir</span><span>(</span><span>&quot;nature&quot;</span><span>,</span><span> </span><span>full.names</span><span> </span><span>=</span><span> </span><span>TRUE</span><span>),</span><span> </span><span>format_image</span><span>)</span><span>
</span><span>readr</span><span>::</span><span>write_csv</span><span>(</span><span>pics_main_colours</span><span>,</span><span> </span><span>path</span><span> </span><span>=</span><span> </span><span>&quot;pics_main_colours.csv&quot;</span><span>)</span><span>
</span></code></pre>
</div>
</div>
<p>And because I’m apparently a bad planner, I had to reduce pictures afterwards.</p>
<div>
<div>
<pre><code><span># we need smaller images</span><span>
</span><span>reduce_image</span><span> </span><span>&lt;-</span><span> </span><span>function</span><span>(</span><span>path</span><span>){</span><span>
</span><span>magick</span><span>::</span><span>image_read</span><span>(</span><span>path</span><span>)</span><span> </span><span>%>%</span><span>
</span><span>magick</span><span>::</span><span>image_scale</span><span>(</span><span>&quot;50x50!&quot;</span><span>)</span><span> </span><span>%>%</span><span>
</span><span>magick</span><span>::</span><span>image_write</span><span>(</span><span>path</span><span>)</span><span>
</span><span>}</span><span>
</span><span>purrr</span><span>::</span><span>walk</span><span>(</span><span>dir</span><span>(</span><span>&quot;formatted_pics&quot;</span><span>,</span><span> </span><span>full.names</span><span> </span><span>=</span><span> </span><span>TRUE</span><span>),</span><span>
</span><span>reduce_image</span><span>)</span><span>
</span></code></pre>
</div>
</div>
<h1>Preparing a function to order and paste pictures</h1>
<p>This function has a collage part which you might recognize from my <a rel="nofollow" href="http://www.masalmon.eu/2017/03/19/facesofr/" target="_blank">the faces of #rstats Twitter</a> blog post, and a ordering pictures according to a variable part that’s new and uses a bit of tidy eval… Maybe I’ll really learn tidy eval this year! <code>pics_info</code> needs to be a data.frame with the path to pictures and well the variable one wants to use to order them.</p>
<div>
<div>
<pre><code><span>
</span><span>library</span><span>(</span><span>&quot;rlang&quot;</span><span>)</span><span>
</span><span>make_column</span><span> </span><span>&lt;-</span><span> </span><span>function</span><span>(</span><span>i</span><span>,</span><span> </span><span>files</span><span>,</span><span> </span><span>no_rows</span><span>){</span><span>
</span><span>magick</span><span>::</span><span>image_read</span><span>(</span><span>files</span><span>[(</span><span>i</span><span>*</span><span>no_rows</span><span>+1</span><span>)</span><span>:</span><span>((</span><span>i</span><span>+1</span><span>)</span><span>*</span><span>no_rows</span><span>)])</span><span> </span><span>%>%</span><span>
</span><span>magick</span><span>::</span><span>image_append</span><span>(</span><span>stack</span><span> </span><span>=</span><span> </span><span>TRUE</span><span>)</span><span> </span><span>%>%</span><span>
</span><span>magick</span><span>::</span><span>image_write</span><span>(</span><span>paste0</span><span>(</span><span>&quot;cols/&quot;</span><span>,</span><span> </span><span>i</span><span>,</span><span> </span><span>&quot;.jpg&quot;</span><span>))</span><span>
</span><span>}</span><span>
</span><span>make_collage</span><span> </span><span>&lt;-</span><span> </span><span>function</span><span>(</span><span>pics_info</span><span>,</span><span> </span><span>no_rows</span><span>,</span><span> </span><span>no_cols</span><span>,</span><span> </span><span>ordering_col</span><span>){</span><span>
</span><span>pics_info</span><span> </span><span>&lt;-</span><span> </span><span>dplyr</span><span>::</span><span>arrange</span><span>(</span><span>pics_info</span><span>,</span><span> </span><span>!!!</span><span>syms</span><span>(</span><span>ordering_col</span><span>))</span><span>
</span><span>pics_info</span><span> </span><span>&lt;-</span><span> </span><span>pics_info</span><span>[</span><span>1</span><span>:</span><span>(</span><span>no_rows</span><span>*</span><span>no_cols</span><span>),]</span><span>
</span><span>pics_info</span><span> </span><span>&lt;-</span><span> </span><span>dplyr</span><span>::</span><span>mutate</span><span>(</span><span>pics_info</span><span>,</span><span> </span><span>column</span><span> </span><span>=</span><span> </span><span>rep</span><span>(</span><span>1</span><span>:</span><span>no_cols</span><span>,</span><span> </span><span>each</span><span> </span><span>=</span><span> </span><span>no_rows</span><span>))</span><span>
</span><span>pics_info</span><span> </span><span>&lt;-</span><span> </span><span>dplyr</span><span>::</span><span>group_by</span><span>(</span><span>pics_info</span><span>,</span><span> </span><span>column</span><span>)</span><span> </span><span>%>%</span><span>
</span><span>dplyr</span><span>::</span><span>arrange</span><span>(</span><span>!!!</span><span>syms</span><span>(</span><span>ordering_col</span><span>))</span><span> </span><span>%>%</span><span>
</span><span>dplyr</span><span>::</span><span>mutate</span><span>(</span><span>row</span><span> </span><span>=</span><span> </span><span>1</span><span>:</span><span>no_rows</span><span>)</span><span> </span><span>%>%</span><span>
</span><span>dplyr</span><span>::</span><span>ungroup</span><span>()</span><span>
</span><span>pics_info</span><span> </span><span>&lt;-</span><span> </span><span>dplyr</span><span>::</span><span>arrange</span><span>(</span><span>pics_info</span><span>,</span><span> </span><span>column</span><span>,</span><span> </span><span>row</span><span>)</span><span>
</span><span>dir.create</span><span>(</span><span>&quot;cols&quot;</span><span>)</span><span>
</span><span>purrr</span><span>::</span><span>walk</span><span>(</span><span>0</span><span>:</span><span>(</span><span>no_cols</span><span>-1</span><span>),</span><span> </span><span>make_column</span><span>,</span><span> </span><span>files</span><span> </span><span>=</span><span> </span><span>pics_info</span><span>$</span><span>path</span><span>,</span><span>
</span><span>no_rows</span><span> </span><span>=</span><span> </span><span>no_rows</span><span>)</span><span>
</span><span>banner</span><span> </span><span>&lt;-</span><span> </span><span>magick</span><span>::</span><span>image_read</span><span>(</span><span>dir</span><span>(</span><span>&quot;cols/&quot;</span><span>,</span><span> </span><span>full.names</span><span> </span><span>=</span><span> </span><span>TRUE</span><span>))</span><span> </span><span>%>%</span><span>
</span><span>magick</span><span>::</span><span>image_append</span><span>(</span><span>stack</span><span> </span><span>=</span><span> </span><span>FALSE</span><span>)</span><span> </span><span>unlink</span><span>(</span><span>&quot;cols&quot;</span><span>,</span><span> </span><span>recursive</span><span> </span><span>=</span><span> </span><span>TRUE</span><span>)</span><span>
</span><span>return</span><span>(</span><span>banner</span><span>)</span><span>
</span><span>}</span><span>
</span></code></pre>
</div>
</div>
<p>The function returns a <code>magick</code> object that one can then write to disk as a PNG for instance.</p>
<p>I first tested it using a random approach added to the data.frame created in the next section, and show the result here to give an idea of the variety of pictures. For many of them, however, the main colour that you can see in their border is greyish.</p>
<div>
<div>
<pre><code><span>set.seed</span><span>(</span><span>42</span><span>)</span><span>
</span><span>pics_info</span><span> </span><span>&lt;-</span><span> </span><span>dplyr</span><span>::</span><span>mutate</span><span>(</span><span>pics_info</span><span>,</span><span> </span><span>random</span><span> </span><span>=</span><span> </span><span>sample</span><span>(</span><span>1</span><span>:</span><span>nrow</span><span>(</span><span>pics_info</span><span>),</span><span> </span><span>nrow</span><span>(</span><span>pics_info</span><span>)))</span><span>
</span><span>make_collage</span><span>(</span><span>pics_info</span><span>,</span><span> </span><span>19</span><span>,</span><span> </span><span>59</span><span>,</span><span> </span><span>&quot;random&quot;</span><span>)</span><span> </span><span>%>%</span><span> </span><span>magick</span><span>::</span><span>image_write</span><span>(</span><span>&quot;data/2018-01-07-rainbowing-banner_random.png&quot;</span><span>)</span><span>
</span></code></pre>
</div>
</div>
<p><img alt="" src="https://i0.wp.com/raw.githubusercontent.com/maelle/maelle.github.io/master/_source/data/2018-01-07-rainbowing-banner_random.png?w=456&ssl=1" data-recalc-dims="1"></p>
<h1>Testing a first (bad) approach: using hue</h1>
<p>Once I had the main colour as an hex code, I had no idea how to order the colours and thought a good idea would be to use hue, which is the main wave length in a colour. Most observed colours are a mix of wave lengths unless you’re using a laser for instance. To get hue from a colour identified by its hex code, one needs two functions: <code>colorspace::hex2rgb</code> and <code>grDevices::rgb2hsv</code>. The latter one outputs hue, saturation and value. Hue is the main wavelength, saturation the amount of that wavelength in the colour and value the amount of light in the colour. The smaller the saturation, the less representative the hue is of the main colour. Add to that the fact that the main colour can also be only a little representative of your original picture… Ordering by hue isn’t too perfect, but I tried that anyway.</p>
<div>
<div>
<pre><code><span># now work on getting the hue and value for all pics</span><span>
</span><span># create a data.frame with path, hue, value </span><span>
</span><span>get_values</span><span> </span><span>&lt;-</span><span> </span><span>function</span><span>(</span><span>path</span><span>,</span><span> </span><span>pics_main_colours</span><span>){</span><span>
</span><span>print</span><span>(</span><span>path</span><span>)</span><span>
</span><span># get main color</span><span>
</span><span>colour</span><span> </span><span>&lt;-</span><span> </span><span>pics_main_colours</span><span>$</span><span>colour</span><span>[</span><span>pics_main_colours</span><span>$</span><span>path</span><span> </span><span>==</span><span> </span><span>stringr</span><span>::</span><span>str_replace</span><span>(</span><span>path</span><span>,</span><span>
</span><span>&quot;formatted_pics&quot;</span><span>,</span><span>
</span><span>&quot;nature&quot;</span><span>)]</span><span>
</span><span># translate it</span><span>
</span><span>rgb</span><span> </span><span>&lt;-</span><span> </span><span>colorspace</span><span>::</span><span>hex2RGB</span><span>(</span><span>colour</span><span>)</span><span>
</span><span>values</span><span> </span><span>&lt;-</span><span> </span><span>grDevices</span><span>::</span><span>rgb2hsv</span><span>(</span><span>t</span><span>(</span><span>rgb</span><span>@</span><span>coords</span><span>))</span><span>
</span><span>tibble</span><span>::</span><span>tibble</span><span>(</span><span>path</span><span> </span><span>=</span><span> </span><span>path</span><span>,</span><span>
</span><span>hue</span><span> </span><span>=</span><span> </span><span>values</span><span>[</span><span>1</span><span>,</span><span>1</span><span>],</span><span>
</span><span>saturation</span><span> </span><span>=</span><span> </span><span>values</span><span> </span><span>[</span><span>2</span><span>,</span><span>1</span><span>],</span><span>
</span><span>value</span><span> </span><span>=</span><span> </span><span>values</span><span>[</span><span>3</span><span>,</span><span>1</span><span>])</span><span>
</span><span>}</span><span>
</span><span># all values</span><span>
</span><span>pics_col</span><span> </span><span>&lt;-</span><span> </span><span>purrr</span><span>::</span><span>map_df</span><span>(</span><span>dir</span><span>(</span><span>&quot;formatted_pics&quot;</span><span>,</span><span> </span><span>full.names</span><span> </span><span>=</span><span> </span><span>TRUE</span><span>),</span><span>
</span><span>get_values</span><span>,</span><span> </span><span>pics_main_colours</span><span>)</span><span>
</span><span>make_collage</span><span>(</span><span>pics_info</span><span>,</span><span> </span><span>19</span><span>,</span><span> </span><span>59</span><span>,</span><span> </span><span>&quot;hue&quot;</span><span>)</span><span> </span><span>%>%</span><span> </span><span>magick</span><span>::</span><span>image_write</span><span>(</span><span>&quot;banner_hue.png&quot;</span><span>)</span><span>
</span></code></pre>
</div>
</div>
<p><img alt="" src="https://i0.wp.com/raw.githubusercontent.com/maelle/maelle.github.io/master/_source/data/2018-01-07-rainbowing-banner_hue.png?w=456&ssl=1" data-recalc-dims="1"></p>
<p>So this is not too pretty. Blue and green pictures seem to cluster together but there are very dark pictures which we’d intuitively put aside.</p>
<p>So I thought a bit more and decided to first assign main colours to a reference colour and then order pictures based on this…</p>
<h1>Choosing a better approach: RGB and distances</h1>
<p>The first challenge was to choose reference colours which’d be a rainbow slices. I could have looked up RGB codes corresponding to <a rel="nofollow" href="https://en.wikipedia.org/wiki/ROYGBIV" target="_blank">ROYGBIV (red, orange, yellow, green, blue, indigo and violet.)</a> but I had read about <a rel="nofollow" href="https://blog.xkcd.com/2010/05/03/color-survey-results/" target="_blank">xkcd colors survey</a> in <a rel="nofollow" href="https://blog.algolia.com/how-we-handled-color-identification/" target="_blank">this interesting post</a> and therefore decided to use XKCD colors, available in R via the <code>xkcdcolors</code> package. I chose to use the 18 most common ones, and add black to that lot. It was no longer really a rainbow, I agree. The colors present in the pictures were ordered by hand by my husband, and I like his choices.</p>
<p>Then to assign each pic to a reference colour via its main colour, I calculated the Euclidian distance between that colour and all reference colours to find the closes reference colours, using the RGB values.</p>
<div>
<div>
<pre><code><span>library</span><span>(</span><span>&quot;xkcdcolors&quot;</span><span>)</span><span>
</span><span>library</span><span>(</span><span>&quot;magrittr&quot;</span><span>)</span><span>
</span><span># version of colorspace::hex2RGB returning a df</span><span>
</span><span>hex2rgb</span><span> </span><span>&lt;-</span><span> </span><span>function</span><span>(</span><span>hex</span><span>){</span><span>
</span><span>result</span><span> </span><span>&lt;-</span><span> </span><span>colorspace</span><span>::</span><span>hex2RGB</span><span>(</span><span>hex</span><span>)</span><span>@</span><span>coords</span><span>
</span><span>}</span><span>
</span><span># https://stackoverflow.com/questions/45328221/unnest-one-column-list-to-many-columns-in-tidyr</span><span>
</span><span>colors</span><span> </span><span>&lt;-</span><span> </span><span>tibble</span><span>::</span><span>tibble</span><span>(</span><span>name</span><span> </span><span>=</span><span> </span><span>c</span><span>(</span><span>xcolors</span><span>()[</span><span>1</span><span>:</span><span>18</span><span>],</span><span> </span><span>&quot;black&quot;</span><span>),</span><span>
</span><span>hex</span><span> </span><span>=</span><span> </span><span>name2color</span><span>(</span><span>name</span><span>),</span><span>
</span><span>rgb</span><span> </span><span>=</span><span> </span><span>purrr</span><span>::</span><span>map</span><span>(</span><span>hex</span><span>,</span><span> </span><span>hex2rgb</span><span>))</span><span> </span><span>%>%</span><span> </span><span>dplyr</span><span>::</span><span>mutate</span><span>(</span><span>rgb</span><span> </span><span>=</span><span> </span><span>purrr</span><span>::</span><span>map</span><span>(</span><span>rgb</span><span>,</span><span> </span><span>tibble</span><span>::</span><span>as_tibble</span><span>))</span><span> </span><span>%>%</span><span>
</span><span>tidyr</span><span>::</span><span>unnest</span><span>()</span><span>
</span><span># for each colour I want the closest one.</span><span>
</span><span>find_closest_colour</span><span> </span><span>&lt;-</span><span> </span><span>function</span><span>(</span><span>hex</span><span>,</span><span> </span><span>colors</span><span>){</span><span>
</span><span>test</span><span> </span><span>&lt;-</span><span> </span><span>tibble</span><span>::</span><span>tibble</span><span>(</span><span>hex</span><span> </span><span>=</span><span> </span><span>hex</span><span>)</span><span> </span><span>%>%</span><span> </span><span>dplyr</span><span>::</span><span>mutate</span><span>(</span><span>rgb</span><span> </span><span>=</span><span> </span><span>purrr</span><span>::</span><span>map</span><span>(</span><span>hex</span><span>,</span><span> </span><span>hex2rgb</span><span>),</span><span>
</span><span>rgb</span><span> </span><span>=</span><span> </span><span>purrr</span><span>::</span><span>map</span><span>(</span><span>rgb</span><span>,</span><span> </span><span>tibble</span><span>::</span><span>as_tibble</span><span>))</span><span> </span><span>%>%</span><span>
</span><span>tidyr</span><span>::</span><span>unnest</span><span>()</span><span> </span><span>distance</span><span> </span><span>&lt;-</span><span> </span><span>stats</span><span>::</span><span>dist</span><span>(</span><span>rbind</span><span>(</span><span>test</span><span>[,</span><span> </span><span>c</span><span>(</span><span>&quot;R&quot;</span><span>,</span><span> </span><span>&quot;G&quot;</span><span>,</span><span> </span><span>&quot;B&quot;</span><span>)],</span><span>
</span><span>colors</span><span>[,</span><span> </span><span>c</span><span>(</span><span>&quot;R&quot;</span><span>,</span><span> </span><span>&quot;G&quot;</span><span>,</span><span> </span><span>&quot;B&quot;</span><span>)]))</span><span>
</span><span>colors</span><span>$</span><span>name</span><span>[</span><span>which.min</span><span>(</span><span>as.matrix</span><span>(</span><span>distance</span><span>)[,</span><span>1</span><span>][</span><span>2</span><span>:</span><span>(</span><span>nrow</span><span>(</span><span>colors</span><span>)</span><span> </span><span>+</span><span> </span><span>1</span><span>)])]</span><span>
</span><span>}</span><span>
</span><span>imgs_col</span><span> </span><span>&lt;-</span><span> </span><span>dplyr</span><span>::</span><span>mutate</span><span>(</span><span>pics_main_colours</span><span>,</span><span>
</span><span>xkcd_col</span><span> </span><span>=</span><span> </span><span>purrr</span><span>::</span><span>map_chr</span><span>(</span><span>colour</span><span>,</span><span> </span><span>find_closest_colour</span><span>,</span><span>
</span><span>colors</span><span> </span><span>=</span><span> </span><span>colors</span><span>))</span><span>
</span><span>readr</span><span>::</span><span>write_csv</span><span>(</span><span>imgs_col</span><span>,</span><span> </span><span>path</span><span> </span><span>=</span><span> </span><span>&quot;imgs_xkcd_col.csv&quot;</span><span>)</span><span>
</span></code></pre>
</div>
</div>
<p>Once I had this information about each pic, I could order the pictures, after having defined the order of the reference colours.</p>
<div>
<div>
<pre><code><span>pics_info</span><span> </span><span>&lt;-</span><span> </span><span>readr</span><span>::</span><span>read_csv</span><span>(</span><span>&quot;imgs_xkcd_col.csv&quot;</span><span>)</span><span>
</span><span>pics_info</span><span> </span><span>&lt;-</span><span> </span><span>dplyr</span><span>::</span><span>mutate</span><span>(</span><span>pics_info</span><span>,</span><span> </span><span>path</span><span> </span><span>=</span><span> </span><span>stringr</span><span>::</span><span>str_replace</span><span>(</span><span>path</span><span>,</span><span> </span><span>&quot;nature&quot;</span><span>,</span><span> </span><span>&quot;formatted_pics&quot;</span><span>))</span><span>
</span><span>pics_info</span><span> </span><span>&lt;-</span><span> </span><span>dplyr</span><span>::</span><span>mutate</span><span>(</span><span>pics_info</span><span>,</span><span>
</span><span>xkcd_col</span><span> </span><span>=</span><span> </span><span>factor</span><span>(</span><span>xkcd_col</span><span>,</span><span> </span><span>ordered</span><span> </span><span>=</span><span> </span><span>TRUE</span><span>,</span><span>
</span><span>levels</span><span> </span><span>=</span><span> </span><span>c</span><span>(</span><span>&quot;black&quot;</span><span>,</span><span>&quot;brown&quot;</span><span>,</span><span>&quot;red&quot;</span><span>,</span><span>&quot;magenta&quot;</span><span>,</span><span>&quot;pink&quot;</span><span>,</span><span>
</span><span>&quot;lime green&quot;</span><span>,</span><span>&quot;green&quot;</span><span>,</span><span>&quot;dark green&quot;</span><span>,</span><span>&quot;teal&quot;</span><span>,</span><span>
</span><span>&quot;light blue&quot;</span><span>,</span><span>&quot;sky blue&quot;</span><span>,</span><span>&quot;blue&quot;</span><span>,</span><span>&quot;purple&quot;</span><span>,</span><span>&quot;grey&quot;</span><span>)))</span><span>
</span></code></pre>
</div>
</div>
<p><img alt="" src="https://i0.wp.com/raw.githubusercontent.com/maelle/maelle.github.io/master/_source/data/2018-01-07-rainbowing-banner_xkcd.png?w=456&ssl=1" data-recalc-dims="1"></p>
<p>This looks much better, but of course the initial set (and maybe the used extraction method as well) don’t provide for enough colours to make this extremely pretty. I’m not sure how useful this end product is, but hey I got to look at pretty landscapes full of colours from my grey rainy city, and learnt a lot along the way… Besides, maybe <em>you</em> will find a cool use case of some of the colour methods featured here and will tell me about it in the comments?</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.masalmon.eu/2018/01/07/rainbowing/"> Maëlle</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/P-0pch8cdCA" height="1"></a></div>