First, let's import the PIL library and the image object.
Import PIL then from pill we'll import image.
Let's import the display functionality from
IPython so from IPython.display will import display.
Finally, let's load the image
we were working with last time.
So that image is in read_only/msi_recruitment.gif.
I will open it into the image object.
Let's execute that so.
Great. Now, let's check out
a few more methods of the image library.
First, we're going to look at copy.
If you remember, we can do this using
the built-in Python help command.
So help image.copy. All right.
Here's some information about copy.
We see that the copy takes no arguments and that
the return object is an image object itself.
Now, let's look at save.
So help image.save.
Okay. There's quite a bit to the image.save object.
The image save method has
a couple of parameters which are interesting.
The first called fp,
is the filename we want to save the object to.
The second format is interesting.
It allows us to change the type of
the image but the docs tells us that this should
be done automatically by looking at
the file extension as well. Let's give it a try.
This file was originally a Gif image file,
but I bet if we save it with
a.png format and read it again,
we'll get a different kind of file.
Let's image.save and we'll just call it
msi_recruitment.png and that's going
to save it in your home directory.
Then we'll open a new image.
So image.open msi_recruitment.png and
take that into an image variable.
Now, let's inspect like we did
in the previous lecture and call
inspect.getmro and wrap image in the type function.
Indeed, this created a new file
which we could view by going into
the Jupyter Notebook file list by clicking
on the logo at the top of the browser,
and we can see this new object is
actually a png image file object.
For the purposes of this class,
the difference between the image formats
really isn't so important,
but it's nice that you can explore how a library works
using the functions of help, dir and getmro.
The Pillow library also has
some nice image filters to add some effects.
It does this through the filter function.
The filter function takes
a filter object and those are all
stored in the image filter object. Let's take a look.
So from PIL, we'll import
the image filter object
and then run help on image filter.
There are a bunch of different filters here,
but let's just try and apply the blur filter.
Before we do this,
we have to convert the image to what's called RGB mode.
This is a bit magical.
Images like Gifs are limited into how many colors
can be displayed at once based on the size of the pallet.
This is similar to
a painter's palette which only has so much room.
This is actually a very old image format.
If we convert the image
into something more sophisticated,
we can apply these interesting image transforms.
Sometimes, learning a new library means digging a
bit deeper into the domain the library is about.
We could convert this image using the convert function.
So image and then we'll just call
image.convertRGB and this stands for red,
green and blue mode which
is a pretty common mode for images.
Then I will create a new variable
blurred image and we'll set that to
image.filter and we'll pass
in the PIL.imagefilter.blur parameter.
You'll note that the parameter that we're passing in
is really a placeholder,
it's not a function that
we're running it's an object we're passing in.
Then, let's display that blurred image.
I encourage you to pause the video here and jump into
the notebooks and start
experimenting with some of the other filters.
The emboss and sharpen
filters for instance are interesting.
Or for a challenge,
check out the box blur or
the median filter functions and look
at their parameters to get
a sense of how they're being used.
Okay. Let me show you
one more function in this lecture, which is crop.
This removes portions of
the image except for the bounding box that you describe.
When you think of images think of individual dots or
pixels which make up the image being lined up on a grid.
You can actually see the number of pixels high
the image is and the width of the image.
So let's do that here,
we'll print the image.
We'll use the string
formatting to pass in two parameters.
The first is going to be image.width,
the width of the image in pixels and
image.height the height of the image in pixels.
We see it's 800 by 450.
This means that this image is
800 pixels wide and we call that
the x-axis and 450 pixels
high and we call that the y-axis.
If we take a look at the crop documentation,
we see that the first parameter
to the function is a tuple,
which is the left upper,
right and lower values of the x, y coordinates.
So the two corners of the image.
So help image.crop, we run
that and we see that there's a box that we provide.
With PIL images, we define
the bounding box using
the upper left corner and lower right corner.
We count the number of pixels out from
the upper left corner which is zero zero.
This might seem odd if you're used to
coordinate systems which start in the lower left,
a lot of us learned these in primary school mathematics.
Just remember that we define our box in
the same way we count out the positions in the image.
So if we wanted to get
the Michigan logo out of this image,
we might start with the left,
I'd say 50 pixels and the top at zero pixels.
Then we might walk to the right another 190
pixels and set the lower bound to say a 150 pixels.
Let's display and we'll call image.crop and we
pass it a parameter is a tuple.
Remember that we're going to put all four of
these parameters in one tuple object and
pass it in and this should display
the image. There we go.
That's the School of
Information logo cropped out of the image.
Of course, crop like other functions only returns
a copy of the image and doesn't change the image itself.
A strategy I like to do is to try and draw
the bounding box directly on
the image where I'm trying to line things up.
We can draw on images using the image draw object.
I'm not going to go into this in detail,
but here's a quick example of how I
might draw the bounding box in this particular case.
So from PIL we'll import the image draw object,
we'll instantiate this, so we'll call
imagedraw.draw and we pass it the image.
You can check the documentation to learn more
about how you would use this object.
Then we say drawing
object.rectangle and we give it the rectangle
the outline that we're actually
interested in and we give it a fill value.
You can set the fill to different colors or
types and an outline,
in this case we want to make it red.
Because we ran this on the drawing object,
it actually executes it and
the drawing object has a reference
to the underlying image.
So let's display this image now in
the Jupyter Notebook. There we go.
We have an image which is our main image of
the logo that's outlined in the red box for our flier.
Okay. That's been an overview of how
to use PIL for single images,
but a lot of work might involve
multiple images and in fact,
your assignment involves multiple images.
So in the next lecture, we're going to tackle that and
set you up for this assignment. I'll see you there.