1 00:00:10,640 --> 00:00:14,468 In this brief lecture I want to introduce you to one of the more advanced features 2 00:00:14,468 --> 00:00:17,775 of the Jupyter notebook development environment called widgets. 3 00:00:17,775 --> 00:00:21,059 Sometimes you want to interact with a function you've created, 4 00:00:21,059 --> 00:00:23,926 and call it multiple times with different parameters. 5 00:00:23,926 --> 00:00:28,615 For instance, if we wanted to draw a red box around a portion of an image to try 6 00:00:28,615 --> 00:00:30,685 and fine tune the crop location. 7 00:00:30,685 --> 00:00:33,643 Widgets are one way to do this quickly in the browser, 8 00:00:33,643 --> 00:00:37,677 without having to learn how to write a whole large desktop application. 9 00:00:37,677 --> 00:00:38,830 Let's check it out. 10 00:00:38,830 --> 00:00:43,191 First we want to import the Image and ImageDraw classes from the pillow package. 11 00:00:43,191 --> 00:00:46,553 So from PIL, we'll bring in Image and ImageDraw. 12 00:00:46,553 --> 00:00:50,371 Then we want to import the interact class from the widgets package. 13 00:00:50,371 --> 00:00:55,231 So from ipywidgets, so this is included automatically because we're 14 00:00:55,231 --> 00:00:59,362 using the IPython interpreter, we'll bring in interact. 15 00:00:59,362 --> 00:01:02,005 We will use interact to annotate a function. 16 00:01:02,005 --> 00:01:04,591 Let's bring in an image that we know we're interested in. 17 00:01:04,591 --> 00:01:07,495 Like the storefront image from a previous lecture. 18 00:01:07,495 --> 00:01:11,379 So I'll bring that in from read_only, and save that into the image object. 19 00:01:11,379 --> 00:01:13,603 Okay so our setup is done. 20 00:01:13,603 --> 00:01:16,453 Now we're going to use the interact decorator to 21 00:01:16,453 --> 00:01:19,454 indicate that we want to wrap the python function. 22 00:01:19,454 --> 00:01:21,454 We do this using the at sign. 23 00:01:21,454 --> 00:01:24,949 This will take a set of parameters which are identical to the function 24 00:01:24,949 --> 00:01:25,678 to be called. 25 00:01:25,678 --> 00:01:30,877 Then Jupyter will draw some sliders on the screen to let us manipulate those values. 26 00:01:30,877 --> 00:01:34,573 Decorators, which again is the at sign is describing this, 27 00:01:34,573 --> 00:01:36,684 are standard Python statements. 28 00:01:36,684 --> 00:01:40,849 And just a shorthand for functions which wrap other functions. 29 00:01:40,849 --> 00:01:44,366 They're a bit advanced those, so we haven't talked about them in this course, 30 00:01:44,366 --> 00:01:46,240 and you might just have to have some faith. 31 00:01:46,240 --> 00:01:48,153 So we do at sign interact. 32 00:01:48,153 --> 00:01:52,715 This is our annotation, our decorator, and we're going to put in four values. 33 00:01:52,715 --> 00:01:54,444 So we'll give it the left and the top. 34 00:01:54,444 --> 00:01:56,828 I'll set the defaults for these at 100. 35 00:01:56,828 --> 00:01:58,380 And the right and the bottom. 36 00:01:58,380 --> 00:02:02,877 And so this is where we actually want to draw our red box. 37 00:02:02,877 --> 00:02:05,862 So now we just write the function as though we had it before. 38 00:02:05,862 --> 00:02:10,321 So def draw_border, again its got to take the exact same parameters as 39 00:02:10,321 --> 00:02:13,455 the decorator, so left, top, right, bottom. 40 00:02:13,455 --> 00:02:15,904 We'll make a copy of the image. 41 00:02:15,904 --> 00:02:20,774 So we're working here with a global image, and we're just making a copy. 42 00:02:20,774 --> 00:02:26,074 We'll create a drawing object based on the image that we've made a copy of. 43 00:02:26,074 --> 00:02:28,423 And then we'll draw a rectangle. 44 00:02:28,423 --> 00:02:31,162 And so we'll just pass in left, top, right, bottom. 45 00:02:31,162 --> 00:02:34,269 And we'll set the filt to none, and the outline to red. 46 00:02:34,269 --> 00:02:38,079 And you can go back and look in the PIL lectures if this doesn't look so 47 00:02:38,079 --> 00:02:39,070 familiar to you. 48 00:02:39,070 --> 00:02:41,495 And then we'll just display it in line. 49 00:02:41,495 --> 00:02:42,798 Let's execute that. 50 00:02:44,702 --> 00:02:48,804 And so here we have that we actually have our storefront image. 51 00:02:48,804 --> 00:02:53,367 We have four sliders, left, top, right, and bottom. 52 00:02:53,367 --> 00:02:57,660 You'll see that as we take one of these, and we drag them over, it changes. 53 00:02:57,660 --> 00:03:01,556 So this is changing the left hand side if we wanted to. 54 00:03:01,556 --> 00:03:06,531 If we take the top, or why don't we take the right and stretch this out a bit. 55 00:03:06,531 --> 00:03:08,557 So you can see that we can stretch that out. 56 00:03:08,557 --> 00:03:12,030 You'll see that it's a little laggy. 57 00:03:12,030 --> 00:03:15,991 There's a lot of documentation about how to use these well. 58 00:03:15,991 --> 00:03:18,455 And there's ways that you can speed it up so 59 00:03:18,455 --> 00:03:21,273 it's not doing all these intermittent values. 60 00:03:21,273 --> 00:03:26,535 But I essentially just did this, and built out my my sliders nicely so 61 00:03:26,535 --> 00:03:31,814 that I could actually just pull out the text that I was interested in. 62 00:03:35,477 --> 00:03:38,430 So Jupyter widgets is certainly advanced territory. 63 00:03:38,430 --> 00:03:41,435 But if you'd like to learn more to explore, 64 00:03:41,435 --> 00:03:45,996 you can check out the website for ipythonwidgets at readthedocs. 65 00:03:45,996 --> 00:03:50,185 And I would encourage you to do so, and play with this nice platform for 66 00:03:50,185 --> 00:03:51,114 doing Python.