Community Spring Cleaning week is here! Join your fellow Maveryx in digging through your old posts and marking comments on them as solved. Learn more here!

Data Science

Machine learning & data science for beginners and experts alike.
BenMoss
ACE Emeritus
ACE Emeritus

LEGOLYTICS.png

 

Legolytics Part 1: Extracting Colours From an Image With Alteryx and R (you are here)

Legolytics Part 2: Assigning the Lego Colour Palette

Legolytics Part 3: All Possible Bricks

Legolytics Part 4: Optimizing Cost

Legolytics Part 5: The Product

Setting the Scene

Around 18 months ago I visited the Lego store with my dad, brother, and nephew (using my nephew as an excuse to act like children). On the visit we came across something that we thought was an ingenious idea, the Lego Mosaic Maker.

It’s essentially a photo booth, but instead of printing out a tiny passport-sized photo of your face, it gives you your own personal Lego set, allowing you to construct a self-portrait with 1x1 lego bricks.

https://petapixel.com/2017/03/02/lego-photo-booth-helps-build-portrait-bricks/https://petapixel.com/2017/03/02/lego-photo-booth-helps-build-portrait-bricks/

Fantastic idea, right? I thought so; but what I didn’t think was a fantastic idea was the price, I thought it was a bit steep at £100, or $130 (mind, I am a bit tight, so some might think that’s quite well priced for such a personalised product).

The maths (at least in my case) looked something like…

£100 = cost of set

£178 = cost of sending just my dad to the store to get picture taken (Yes trains are expensive in the UK!)

So, it comes out at £278 for the experience: not good.

I then did some basic math based on the size of the image and the cost of Lego bricks.

The image is a 48x48 grid, that’s 2304 pixels.

Each 1x1 Lego piece costs £0.06, so that’s £138.04 to build the image.

Then you need a base plate, this is one of those big flat square things that you stick your Lego to, this is £13. So, at the very worst, if I can build a mechanism to do this myself, it will cost me £151.04. That’s a saving of 54% (imagine if you reported that kind of saving In a business environment, your bosses would love you!).

So, for the reason of math, and some Alteryx enjoyment, I thought what the heck, let’s try this, and this blog (or 5 blogs), will detail the key stepping stones which allowed me to build a Lego portrait with Alteryx.

Streaming Image Into Alteryx

 

The first task that we face is actually extracting, pixel by pixel, the different colours within the image. For the sake of this exercise, I will use my friend (and current US Alteryx Grand Prix Champion) @PhilipMannering's face.

BenMoss_1-1585582587803.jpeg

 

Now, unfortunately, there is no native way to perform this task using Alteryx, but thankfully, Alteryx is a code-friendly platform, and thanks to the integration with R, this task becomes possible.

I can take very little credit for the development of the script, which is largely ripped from this post on RBloggers, but it did take some small adaptions for the task in-hand.

BenMoss_2-1585582587891.png


So, step 1: let’s load the libraries that we need to use for this task.

 

 

library("jpeg")
library("EBImage")

 

 

We can then use a command, which forms part of the jpeg library, to read our image as a dataframe (because Alteryx loves dataframes!). Here I create a table titled original.

 

 

original <- readJPEG("C:/Users/BenMoss/Desktop/Selfie.jpg")

 

 

Now, I don’t know about you, but my phone takes pictures in a slightly higher resolution than 48x48 (that’s a measly 0.0023 megapixels, whereas your phone is probably something like 12), so we also need to reduce the size of the image, which is where the function resize comes in, which forms part of the second library loaded, EBImage.

 

Here I am creating a second dataframe, titled Resized, which is our original image reduced to the pixel size needed, in this case, 48x48. 

 

 

resized <- resize(original, w = 48, h = 48)

 

 

We should then transform our object into a dataframe which contains a single row per pixel, with 3 columns, one for each of the three colours (red, green and blue), which forms RGB. Here I create a final object called df.

 

 

df = data.frame(
  red = matrix(resized[,,1], ncol=1),
  green = matrix(resized[,,2], ncol=1),
  blue = matrix(resized[,,3], ncol=1)
)

 

 

The final step is to stream this dataframe into Alteryx, so we can work with it as if it were a data table. This is done very simply with the write.Alteryx function. Here I write the data table to the output node labeled 1 on the R tool.

 

 

write.Alteryx(df, 1)

 

 

BenMoss_3-1585582587906.png

 

Thankfully, even in the images reduced image state, we can still tell that this is the Alteryx master himself, Phil Mannering.

Next Steps

 

Now we’ve brought our image into Alteryx, we must now perform the task of assigning actual Lego colours to the image, which involves a process of clustering, but that’s for part 2!

Comments
kelly_gilbert
13 - Pulsar

Ooh, looking forward to the rest of this series! I regretted not being able to attend this session at Inspire.

I'm working on my own pixellated art project (with paint instead of LEGOs)... For this one, I used a website that converts photos into cross-stitch patterns, but I'd love to get into some Alteryx + R fun for the next one!

kelly_gilbert_0-1586269403772.png

TuvyL
Alteryx Alumni (Retired)

@kelly_gilbert I've been wanting to get into cross-stitching but it's a bit intimidating! What's the design you're working on?

kelly_gilbert
13 - Pulsar

@TuvyL - it's a pixellated photo of Hank Aaron hitting his 715th home run (we love baseball and live in Atlanta 🙂)

TuvyL
Alteryx Alumni (Retired)

SO cool, @kelly_gilbert, it's like a fancy paint by numbers. I'm seriously loving seeing people's creativity (and commitment) in their hobbies these days.

 

@BenMoss, what's going to be your 2020 Alteryx Art project? 😛 Every year you should come with a cool DIY preso.

cgoodman3
14 - Magnetar
14 - Magnetar

@BenMoss which version of Alteryx did you use for this? When installing the package EBImage I got an error to say it wasn’t available with the version of R (3.4.4) installed as part of the 2018.4 install?

cgoodman3
14 - Magnetar
14 - Magnetar

Found this, but still not working 😞

 

Need to install it in two steps:

install.packages("BiocManager")

BiocManager::install("EBImage")

 

https://www.bioconductor.org/packages/release/bioc/vignettes/EBImage/inst/doc/EBImage-introduction.h...

BenMoss
ACE Emeritus
ACE Emeritus

Hi @cgoodman3 the script that you say in your latest post is what I used (it's going to be referenced in the last blog of this series).

It's quite likely when I first attempted this a a year and a half or so ago that I was on 2018.4 at the time, so it surprises me that you are getting the error you mention.

 

What error do you get when attempting the install using that code?

NeilR
Alteryx Alumni (Retired)

Part 2 is here!

cgoodman3
14 - Magnetar
14 - Magnetar

@BenMoss so the installation works fine (I need to install it via the tip in one of your other posts via the R.exe in the Alteryx folder, instead of via the R tool.)

 

The error says “Error: package or namespace load failed for ‘EBImage’ in loadNamespace(j <-[[1L]],c(lib.loc, .libPaths()), versionCheck = vI[[j]]):”

BenMoss
ACE Emeritus
ACE Emeritus

Can you try and install them again (as per the blog you mention) and share any screenshots of the results.

I've had trouble with this in the past, make sure you do each line separately, i.e. execute...

 

install.packages("BiocManager")

 

wait for it to complete, then execute...

 

BiocManager::install("EBImage")

 

I think you may be prompted to update some libraries which they use, I believe I hit Y in those cases.

 

Ben

cgoodman3
14 - Magnetar
14 - Magnetar

I've dug out the post where you mentioned a way of installing the packages - https://community.alteryx.com/t5/Alteryx-Designer-Discussions/Error-when-trying-to-use-the-R-tool-un...

 

So I just put it on a VM running 2019.3 and had no problems. I'll try and get round to going back to 2018.4 and see it there was an issue with the packages being installed.

 

Need to just find a better picture than my work one.

 

Capture.PNG