As part of the lesson resources that you've downloaded, under "SpamData" > "01_Processing", there's a folder 1
called "wordcloud_resources" and there you should see a "whale-icon.png" file and this is gonna 2
be our mask that we will project the words from the word cloud onto. If you scroll back up in the notebook 3
to where we've put all our constants, 4
we can add another one here. Let's add the relative path to this PNG file. So I'm going to add a new line and 5
here we'll add a constant called "WHALE_FILE" and set that equal to to what it says in the 6
previous string 7
at first, save us some time typing. The first two bits will stay the same, it will still be "SpamData/01_ 8
Processing", but after that forward slash, we have to write "wordcloud_resources/ 9
whale-icon.png". This bit here needs to be the relative path that points to our "whale 10
-icon.png" file. As always with these things, 11
everything's case sensitive. Now before we scroll back down, 12
let's go up to our notebook imports and import another tool. 13
This will be some functionality from the PIL package. 14
So "from PIL", all caps, "import image". PIL is short for "Pillow". Pillow is the name of a package that will help 15
us with image manipulation and processing. 16
Pillow can actually do quite a lot of things like pixel manipulation, image blurring or smoothing, or 17
adding text. We're going to be using it to convert our starting image of the whale to grayscale and then to an 18
array of RGB values. 19
And the reason for that is that wordcloud has some very specific requirements as to what kinds of images 20
can and cannot be used as a mask. And also it's quite particular. 21
what kind of format the mask is in and that's why we need to do a little prep. 22
Also, 23
I suspect that at one point you want to use your own custom masks with wordcloud, 24
at some point in the future. 25
So it's a good idea to have seen this workflow of the image preparation once before. In fact, let's take 26
a look at wordcloud's requirements. 27
If I scroll down here and hit Shift+Tab on my keyboard to bring up the quick documentation, I can see 28
that there is a parameter called "mask". By default 29
it has the value None and scrolling down. 30
we can take a quick look at a more detailed description and this reads: 31
"If not None, gives a binary mask on where to draw words." 32
So the mask will specify the location of where the words are drawn on the canvas. 33
Further down it says "All white entries will be considered 'masked out' and all the other entries will 34
be free to draw on.". And the format that we need to supply this mask in is an nd-array, an n-dimensional 35
array like one from numpy. 36
Now that sounds a little strange, right. 37
Why would we provide an array? 38
And the reason is is that wordcloud actually expects pixel by pixel information on the image in this 39
array format. 40
And when I say pixel by pixel information, what I really mean is pixel color because what the word cloud 41
code cares about is if it's dealing with a white pixel or a pixel in another color. The way that we will 42
be providing this pixel color information is in RGB format. 43
RGB stands for Red Green Blue. 44
We're already acquainted with color hex codes from previous lessons. 45
So this time we'll use our RGB to mix things up a little bit. 46
The RGB format is particularly relevant because it relates very closely to how colors are shown on your 47
TV or your phone screens. 48
If you were to take a magnifying glass and go up really close to your phone, you will actually see tiny 49
little red green and blue LED. With RGB 50
you essentially supply three values, namely how bright each of these little LEDs should shine. 51
The RGB values themselves have a scale between zero and 255. 52
If all the numbers are on 255 then we get pure white. 53
If all the numbers are on 0 then we get pure black. And with any combination between we get all the 54
other colors. Back in our Python code, 55
we now know that our goal is to get an array of RGB values to our word cloud. 56
The first step will be opening the image file. 57
You'll recall that we've added the constant up top that points to the "whale-icon.png" file, 58
so we can use pillows "Image.open()" and then supply the relative file path, 59
our "WHALE_FILE" to the open method. In fact, let's say "icon = Image.open(WHALE_FILE)". 60
Step two will be creating a new blank image object from Pillow. 61
So again we'll use "Image.new()" and then we'll supply three arguments, 62
the first of which is the mode and this will be RGB; 63
the second of which will be the size, 64
so we're kind of setting the size of our canvas here and I'm gonna set that equal to "icon.size", 65
so the same size as the whale image and the third thing is I'll set a base colour and that will be 66
equal to "(255, 255, 255)". 67
So this is a tuple of three integers and they correspond to the red green and blue values. With all of 68
them set to 255, 69
we get white. 70
I'll store our blank canvas in a variable called "image_mask". 71
Now what I'll do, I'll take our image_mask and put a dot after it and say "paste(icon, 72
box = icon)". 73
What this will do is it will paste the picture of our whale onto our blank canvas. 74
And the reason we're doing this is because now we can easily convert our image mask to an array of 75
RGB values. 76
This is why we went through all this trouble, so I'll say "rgb_array = np. 77
array(image_mask)". 78
This is the key. 79
This converts the image object to an array. And with that in hand we can supply the mask argument to 80
our word cloud. 81
So we'll say "mask = rgb_array". Now let's hit Shift+Enter and see what we get - "name 'np' 82
is not defined". 83
Looks like we forgot to import numpy as np. 84
Let's go to the very top on our notebook imports and indeed we're missing it. 85
So this shall not do. Any self respecting Python notebook needs to import numpy, right? 86
So let's add "import numpy as np" and hit Shift+Enter. 87
Now we can refresh this cell and see if it runs. Giving it a little bit of time, 88
we now see our words superimposed on the whale. 89
Brilliant. 90
So this is really cool, but I think we can style this a little better and the way we're gonna do that 91
is we're going to supply some more arguments to our word cloud here. 92
In particular, I'm interested in changing the background colour here and I'm also interested in changing 93
the colour of these words and we can do that by supplying something called a "colormap". 94
Also I want to play with this "max_words" parameter here which is currently set to 200. 95
Let's see what happens when we change this to say 50 or 400, but the very first thing I'm gonna do is change 96
the size of this image. 97
And this is good old's matplotlib's "plt.figure" method that I'm going to call here. 98
So "figure(figsize = [16, 8])". I think that will do nicely and make it a little 99
larger and easier to see what the styling changes are going to look like. 100
So here's our whale now. Let's change the background color to white. 101
I'll add a comma here, 102
change the background color to 'white' and hit Shift+Enter. 103
Now this is starting to look a lot better in my opinion. 104
But let's play with some of the other parameters as well. 105
Before we add those though, I'm noticing that this line is getting a little long. 106
So instead of chaining this method call here I'm going to come down here, hit Enter and say "word_cloud. 107
generate" on a separate line of code. Here 108
after background color, 109
I'll insert a comma, 110
hit Enter and then change the "max_words" to say 50 and update our graphic. 111
So that's a very different look. 112
Right. 113
On the upside this image was generated a lot faster than the other ones. 114
But on the downside I can't really tell that this is a whale anymore because a lot of the edges and 115
so on depend on smaller words being present to flesh out this image. 116
So what I'll do instead is change this "max_words" argument to 400 and refresh this cell. 117
At this point, 118
our code will have taken a little longer but we get a much, much more beautiful word cloud with all the 119
small words on the perimeter of this mask. 120
But if you recall what's actually determining the location of where these words are drawn on the 121
canvas it's this "rgb_array". 122
If we take a closer look at this "rgb_array", and hit Shift+Enter on it, 123
we see that it looks something like this. 124
Now that doesn't tell us a whole lot, 125
maybe. A better way to look at it might be "rgb_array.shape". 126
And there we see it's 1024 by 2048 by 3. 127
The reason we see those numbers here is because the whale icon itself has a width of 2048 pixels by 128
1024 pixels 129
and the 3 is for the red green and blue RGB values. In other words this array has pixel by pixel 130
information on the color. 131
If we take our rgb_array, we can actually pull up a particular pixel. 132
So if I say for example "[1023, 2047]" then I can see what the RGB values 133
are for this particular pixel. Given that this pixel is white, 134
the word cloud will not draw in this area, but let's take the pixel at say 500 and 1000. 135
Here we see the values 0, 0, 0, meaning that at this particular location in the image the pixel is black. 136
So word cloud is free to use this particular pixel to draw on. Now one of the nice things about matplotlib 137
is that we have access to these wonderful color maps and we can play with the styling of our 138
words by say providing one of these color maps as an argument. 139
There's quite a few to choose from. 140
We can go with "plasma", we could go with "blues" or "greens" or "oranges". 141
But one that I found that works particularly well I think for the whale image is a color map called 142
"ocean". Refreshing our cell, 143
our whale will now start looking something like this and I think thematically this color map seems to 144
work rather well. 145
Having worked a little bit now with the NLTK resources and our word cloud code I want to throw it 146
over to you. 147
I want to propose a challenge. 148
I'd like you to use the skull image in the lesson resources as a mask to create a word cloud for Shakespeare's 149
play Hamlet. 150
The skull image that I've included looks like this. 151
So have a go at this and have a play with different color maps and different number of maximum words 152
to make this look good. 153
And you can find Shakespeare's entire play under "gutenberg" and then "shakespeare-hamlet. 154
txt". 155
This is something that we've downloaded as part of the NLTK resources. 156
The file is actually in the same folder as Melville's Moby Dick. 157
If you're particularly brave then you can try and tackle the Hamlet play in the form of XML as opposed 158
to a TXT file.