In this brief lecture I want to introduce you to one of the more advanced features
of the Jupyter notebook development environment called widgets.
Sometimes you want to interact with a function you've created,
and call it multiple times with different parameters.
For instance, if we wanted to draw a red box around a portion of an image to try
and fine tune the crop location.
Widgets are one way to do this quickly in the browser,
without having to learn how to write a whole large desktop application.
Let's check it out.
First we want to import the Image and ImageDraw classes from the pillow package.
So from PIL, we'll bring in Image and ImageDraw.
Then we want to import the interact class from the widgets package.
So from ipywidgets, so this is included automatically because we're
using the IPython interpreter, we'll bring in interact.
We will use interact to annotate a function.
Let's bring in an image that we know we're interested in.
Like the storefront image from a previous lecture.
So I'll bring that in from read_only, and save that into the image object.
Okay so our setup is done.
Now we're going to use the interact decorator to
indicate that we want to wrap the python function.
We do this using the at sign.
This will take a set of parameters which are identical to the function
to be called.
Then Jupyter will draw some sliders on the screen to let us manipulate those values.
Decorators, which again is the at sign is describing this,
are standard Python statements.
And just a shorthand for functions which wrap other functions.
They're a bit advanced those, so we haven't talked about them in this course,
and you might just have to have some faith.
So we do at sign interact.
This is our annotation, our decorator, and we're going to put in four values.
So we'll give it the left and the top.
I'll set the defaults for these at 100.
And the right and the bottom.
And so this is where we actually want to draw our red box.
So now we just write the function as though we had it before.
So def draw_border, again its got to take the exact same parameters as
the decorator, so left, top, right, bottom.
We'll make a copy of the image.
So we're working here with a global image, and we're just making a copy.
We'll create a drawing object based on the image that we've made a copy of.
And then we'll draw a rectangle.
And so we'll just pass in left, top, right, bottom.
And we'll set the filt to none, and the outline to red.
And you can go back and look in the PIL lectures if this doesn't look so
familiar to you.
And then we'll just display it in line.
Let's execute that.
And so here we have that we actually have our storefront image.
We have four sliders, left, top, right, and bottom.
You'll see that as we take one of these, and we drag them over, it changes.
So this is changing the left hand side if we wanted to.
If we take the top, or why don't we take the right and stretch this out a bit.
So you can see that we can stretch that out.
You'll see that it's a little laggy.
There's a lot of documentation about how to use these well.
And there's ways that you can speed it up so
it's not doing all these intermittent values.
But I essentially just did this, and built out my my sliders nicely so
that I could actually just pull out the text that I was interested in.
So Jupyter widgets is certainly advanced territory.
But if you'd like to learn more to explore,
you can check out the website for ipythonwidgets at readthedocs.
And I would encourage you to do so, and play with this nice platform for
doing Python.