1 00:00:00,000 --> 00:00:04,318 Hi, and welcome to this new lecture. So 2 00:00:04,319 --> 00:00:06,749 what I'll do here is I'll give the final 3 00:00:06,749 --> 00:00:08,789 thoughts to our motion detection program. 4 00:00:09,479 --> 00:00:13,199 And specifically, I'll build a plot using 5 00:00:13,199 --> 00:00:15,719 the Bokeh library, where I will 6 00:00:15,749 --> 00:00:17,879 visualize the times that the object 7 00:00:17,879 --> 00:00:20,831 enters and exits the frame, the video frame, 8 00:00:21,448 --> 00:00:24,593 and the final output will look something like this. 9 00:00:24,594 --> 00:00:26,814 [No audio] 10 00:00:26,816 --> 00:00:30,149 So what we've got here is a plot with an x axis 11 00:00:31,618 --> 00:00:35,764 which is plotting the datetime, while the y axis 12 00:00:35,789 --> 00:00:38,099 doesn't have any sense actually. So 13 00:00:38,099 --> 00:00:40,859 it just vertical extension of these 14 00:00:40,889 --> 00:00:44,009 bars, which you see here, and so what we've 15 00:00:44,009 --> 00:00:47,669 got here is, let's say, I started the 16 00:00:47,669 --> 00:00:52,949 camera this day on 17th of March, and so 17 00:00:52,949 --> 00:00:56,219 this first capture here is, you can see it 18 00:00:56,219 --> 00:01:00,059 started at this date and it ended after 19 00:01:00,059 --> 00:01:02,669 4 seconds. So this object entered the 20 00:01:02,669 --> 00:01:05,159 frame in the start date and stayed for 21 00:01:05,159 --> 00:01:07,467 4 seconds there and then exited 22 00:01:07,492 --> 00:01:10,409 the video frame. So similarly, we 23 00:01:10,409 --> 00:01:15,599 have this other object, so still on 17th of 24 00:01:15,599 --> 00:01:19,739 March and then we've got this hour 25 00:01:19,739 --> 00:01:23,249 here. And then here starts the other day, 26 00:01:23,249 --> 00:01:26,489 so 18th of March, and these are the 27 00:01:26,489 --> 00:01:28,382 hours between these days. So 28 00:01:29,359 --> 00:01:34,499 4 o'clock, 8, 12, 16, and 20, and you can also 29 00:01:34,499 --> 00:01:37,199 see that I've added hover capabilities 30 00:01:37,199 --> 00:01:38,969 here so that when I hover the mouse over 31 00:01:38,969 --> 00:01:43,469 these bars, I get this information, and 32 00:01:43,709 --> 00:01:45,629 you can also zoom in here. So if you 33 00:01:45,629 --> 00:01:48,239 want more information about this, you 34 00:01:48,239 --> 00:01:51,689 can see the information clearly here. So 35 00:01:51,719 --> 00:01:55,229 that's the product. Now what the script 36 00:01:55,229 --> 00:01:57,659 is doing at the moment is it is 37 00:01:57,659 --> 00:02:00,479 producing the start time and end time 38 00:02:00,479 --> 00:02:03,029 of the object entering the frame in 39 00:02:03,054 --> 00:02:07,104 a csv file. So specifically, the program 40 00:02:08,489 --> 00:02:10,559 is triggered in the video from a webcam. 41 00:02:11,639 --> 00:02:13,649 And then, you got some objects in there. 42 00:02:13,650 --> 00:02:22,648 [No audio] 43 00:02:22,650 --> 00:02:28,445 Press Q for quitting, and so what you get is this Times.csv, 44 00:02:28,446 --> 00:02:30,837 [No audio] 45 00:02:30,862 --> 00:02:33,257 where each row represents all the start 46 00:02:34,722 --> 00:02:37,546 time and end time. Okay, you know this already. 47 00:02:37,968 --> 00:02:41,610 And so other moment, what we've got here is 48 00:02:41,610 --> 00:02:45,780 also a list with a status of the 49 00:02:45,794 --> 00:02:49,574 current frame. So this is let's say, 100 50 00:02:49,800 --> 00:02:53,190 items. So that means we had 100 frames 51 00:02:53,190 --> 00:02:57,120 in this 7 second video. Now, the 52 00:02:57,120 --> 00:03:01,170 first thing you may want to do is small 53 00:03:01,170 --> 00:03:05,040 improvement here very quickly. This 54 00:03:05,040 --> 00:03:07,470 list if you having a webcam capture a 55 00:03:07,470 --> 00:03:10,290 long video, so if you are running it for 56 00:03:10,350 --> 00:03:13,410 many hours, this list may get too 57 00:03:13,410 --> 00:03:18,930 big. So to avoid memory problems, you 58 00:03:18,930 --> 00:03:22,440 may want to go here. So here you're 59 00:03:22,440 --> 00:03:25,050 checking the last item of the list, and 60 00:03:25,050 --> 00:03:27,720 the item before the last item. So the 61 00:03:27,720 --> 00:03:31,170 last two items, and that means we don't need 62 00:03:31,950 --> 00:03:35,130 this other items, so we only need to 63 00:03:35,130 --> 00:03:39,870 keep two last items only. That means 64 00:03:39,871 --> 00:03:42,958 [No audio] 65 00:03:42,960 --> 00:03:45,240 just after we append the new status 66 00:03:45,240 --> 00:03:50,250 here, so we say status_list equals to 67 00:03:50,250 --> 00:03:55,920 status_list, but with only the last two 68 00:03:55,920 --> 00:04:00,150 items. So if I execute this now what 69 00:04:00,150 --> 00:04:04,170 I'll get is only the last two statuses 70 00:04:04,195 --> 00:04:06,801 of the video frame printed all this as a list. 71 00:04:07,366 --> 00:04:08,860 So the list is printing here. 72 00:04:08,861 --> 00:04:11,342 [No audio] 73 00:04:11,344 --> 00:04:13,290 So that's an improvement plot for the sake 74 00:04:13,290 --> 00:04:17,370 of memory. Now, how do we get around 75 00:04:17,370 --> 00:04:20,970 building a plot with Bokeh? So 76 00:04:20,970 --> 00:04:22,740 first, we have to think about the 77 00:04:22,740 --> 00:04:26,220 structure of our scripts. So this 78 00:04:26,220 --> 00:04:29,850 plotting object that should be creating using a 79 00:04:29,850 --> 00:04:32,895 quadrant. So this will expect a DataFrame 80 00:04:32,919 --> 00:04:35,190 to be sent as an input. So we 81 00:04:35,190 --> 00:04:36,562 actually have a DataFrame here 82 00:04:36,563 --> 00:04:41,406 [No audio] 83 00:04:41,407 --> 00:04:45,704 and we are sending that DataFrame to the Times.csv file. 84 00:04:45,705 --> 00:04:48,270 [No audio] 85 00:04:48,271 --> 00:04:53,101 What I'll do here is I would create another file. 86 00:04:53,667 --> 00:04:58,020 So Python script say plotting.py, and here is where 87 00:04:58,020 --> 00:05:00,630 I would write the script, the code 88 00:05:00,630 --> 00:05:04,805 for plotting the data. In that case, 89 00:05:04,830 --> 00:05:08,021 that means we need to fetch the DataFrame 90 00:05:08,045 --> 00:05:11,850 of this motion_detector program to 91 00:05:11,850 --> 00:05:15,750 the script. So, what you can do is you 92 00:05:15,750 --> 00:05:21,955 want to say from motion_detector import df. 93 00:05:22,098 --> 00:05:24,696 So that will make available the df 94 00:05:24,698 --> 00:05:26,820 DataFrame, that is being generated 95 00:05:26,820 --> 00:05:28,438 in this motion_detector program. 96 00:05:30,157 --> 00:05:32,700 Which means that when you want to run 97 00:05:32,700 --> 00:05:34,920 the program later, you'll be running 98 00:05:34,920 --> 00:05:38,310 the plotting.py with Python. So, when 99 00:05:38,310 --> 00:05:42,480 you execute plotting.py, plotting.py will 100 00:05:42,510 --> 00:05:45,441 call for execution this motion_detector.py 101 00:05:45,443 --> 00:05:47,850 script. So, the video from the 102 00:05:47,850 --> 00:05:52,590 webcam will start, and then when this 103 00:05:52,590 --> 00:05:54,870 loops ends, this DataFrame will be 104 00:05:54,870 --> 00:05:59,220 generated. That means, after that the 105 00:05:59,220 --> 00:06:01,560 script, the code of the plotting.py 106 00:06:01,920 --> 00:06:04,080 will be executed. So here we will be 107 00:06:04,080 --> 00:06:06,301 getting the DataFrame and plotting and so on. 108 00:06:06,303 --> 00:06:08,307 [No audio] 109 00:06:08,309 --> 00:06:10,350 I hope that is clear. So 110 00:06:10,350 --> 00:06:12,450 let's go ahead now and import the 111 00:06:12,480 --> 00:06:15,540 plotting interface of Bokeh. So from 112 00:06:15,540 --> 00:06:18,840 bokeh.plotting, actually, we'll not 113 00:06:18,840 --> 00:06:21,270 be importing the entire plotting 114 00:06:21,270 --> 00:06:27,150 interface, we only need figure, show, and 115 00:06:27,270 --> 00:06:29,430 output_file. 116 00:06:29,431 --> 00:06:31,502 [No audio] 117 00:06:31,504 --> 00:06:35,078 Let's keep it tied there, and then let's 118 00:06:35,079 --> 00:06:38,580 go ahead and create the figure object, and 119 00:06:40,446 --> 00:06:46,656 x_axis_type will be of type datetime. 120 00:06:46,681 --> 00:06:50,488 [Author typing] 121 00:06:50,490 --> 00:06:55,862 Let's set the height of 100, and the width of 500, 122 00:06:55,863 --> 00:06:58,017 [Author typing] 123 00:06:58,019 --> 00:06:59,718 and let's make it responsive, 124 00:06:59,719 --> 00:07:03,691 [Author typing] 125 00:07:03,692 --> 00:07:04,921 title of the graph, 126 00:07:04,945 --> 00:07:06,945 [Author typing] 127 00:07:06,947 --> 00:07:08,346 Motion Graph, okay. 128 00:07:08,371 --> 00:07:11,998 [No audio] 129 00:07:12,000 --> 00:07:15,240 So once we have a figure there, we want 130 00:07:15,240 --> 00:07:17,370 to plot a glyph in that figure, 131 00:07:18,930 --> 00:07:21,210 and that I believe in this case would be a 132 00:07:21,210 --> 00:07:24,756 quadrant, so quad. So a quadrant 133 00:07:24,758 --> 00:07:27,270 would be more appropriate to plot these 134 00:07:27,270 --> 00:07:29,700 time intervals there, and so the trick 135 00:07:29,700 --> 00:07:33,030 to have this quad glyph to visualize 136 00:07:33,030 --> 00:07:35,970 your date and your times along this x 137 00:07:36,013 --> 00:07:41,052 axis is to pass left, right, and bottom, 138 00:07:41,370 --> 00:07:45,210 and top parameters. So for left, you'd 139 00:07:45,235 --> 00:07:50,142 want to pass the Start time. So left 140 00:07:50,188 --> 00:07:52,011 of the box of these 141 00:07:52,012 --> 00:07:54,218 [No audio] 142 00:07:54,219 --> 00:07:57,437 boxes that you see here. So the left border 143 00:07:57,438 --> 00:08:01,297 would be the Start time, while the right border. 144 00:08:01,298 --> 00:08:04,294 [Author typing] 145 00:08:04,296 --> 00:08:09,180 So df would be the End time. So here is our 146 00:08:09,180 --> 00:08:11,430 csv, which is not what you were using, 147 00:08:11,430 --> 00:08:13,950 but this is the structure of the data. 148 00:08:15,635 --> 00:08:18,605 So Start time on the left, and 149 00:08:18,630 --> 00:08:21,810 then End time on bordering the right of the 150 00:08:21,840 --> 00:08:24,720 rectangle of quadrant, and then here is 151 00:08:24,720 --> 00:08:28,680 a trick we can do for bottom, we would want to 152 00:08:28,680 --> 00:08:33,240 keep a fixed value. So 0 for every 153 00:08:33,240 --> 00:08:36,570 quadrant and then 1 for every quadrant 154 00:08:36,570 --> 00:08:40,410 as well, and that's it. Color is not 155 00:08:40,410 --> 00:08:44,160 a problem, let's say green, and I'd like 156 00:08:44,160 --> 00:08:49,200 to try this for now. So output_file, 157 00:08:49,470 --> 00:08:52,554 that should be Graph.html 158 00:08:52,555 --> 00:08:55,196 [No audio] 159 00:08:55,198 --> 00:08:57,508 and show the p figure. 160 00:08:57,509 --> 00:08:59,697 [No audio] 161 00:08:59,699 --> 00:09:01,956 And let's see what there is going to happen, 162 00:09:02,839 --> 00:09:06,413 this for say Python, and we don't want to execute 163 00:09:06,445 --> 00:09:10,796 motion_detector now but we want to execute plotting.py. 164 00:09:10,797 --> 00:09:13,203 [No audio] 165 00:09:13,205 --> 00:09:16,996 So that's our main script where we get sorted. 166 00:09:16,997 --> 00:09:20,669 [No audio] 167 00:09:20,671 --> 00:09:22,852 And I've got a stupid syntax error here 168 00:09:23,279 --> 00:09:27,450 from bokeh.plotting figure. I bet you knew it that 169 00:09:28,055 --> 00:09:30,335 I missed import keyword here. So 170 00:09:30,360 --> 00:09:32,250 from bokeh.plotting import figure, show, 171 00:09:32,250 --> 00:09:35,100 output_file. Save and try again. 172 00:09:35,101 --> 00:09:39,478 [No audio] 173 00:09:39,480 --> 00:09:43,590 And here is the webcam, objects. Object 174 00:09:43,590 --> 00:09:48,750 again, another time, quit, and let's see 175 00:09:48,750 --> 00:09:51,390 what is going to happen now, and yet 176 00:09:51,420 --> 00:09:56,940 another error responsive. Good. Sorry 177 00:09:56,940 --> 00:09:58,351 about that. Try again. 178 00:09:58,352 --> 00:10:02,566 [No audio] 179 00:10:02,567 --> 00:10:08,490 First object, and second object there, and one more, 180 00:10:09,400 --> 00:10:13,834 Quit, and we should see the graph here. 181 00:10:15,128 --> 00:10:18,515 Yeah, it's looking good. So I can see here, 182 00:10:18,549 --> 00:10:21,635 and you can also notice that we've got 183 00:10:21,697 --> 00:10:25,597 quite an unnecessarily granularity here. 184 00:10:26,352 --> 00:10:28,482 So we don't need all the stickers here. 185 00:10:29,010 --> 00:10:33,510 And also, you can see here that this 186 00:10:33,510 --> 00:10:37,050 says 19 seconds, which means that it's 187 00:10:37,050 --> 00:10:40,650 19 seconds past the last minute. So if 188 00:10:40,650 --> 00:10:44,250 it was, let's say, 15 minutes and 19 189 00:10:44,250 --> 00:10:47,730 seconds, and so 20 seconds of the 15 minute, 190 00:10:47,732 --> 00:10:51,420 and so on. So you don't really see the 191 00:10:51,420 --> 00:10:54,360 big picture in just 10 seconds of video. 192 00:10:54,900 --> 00:10:57,870 But also, to make it more informative, I 193 00:10:57,870 --> 00:11:00,810 would add a hover tool to this bar so 194 00:11:00,810 --> 00:11:03,330 that when I hover the mouse here, as 195 00:11:03,330 --> 00:11:06,150 you know, you should see the start and the end 196 00:11:06,150 --> 00:11:08,310 time, so that you can see the complete 197 00:11:08,340 --> 00:11:11,970 time there if the labels here are not enough. 198 00:11:13,080 --> 00:11:15,180 But first, let's remove the stickers 199 00:11:15,180 --> 00:11:19,260 here. So we go back to the script, and 200 00:11:20,760 --> 00:11:23,610 let me pull this down. The way to do 201 00:11:23,610 --> 00:11:25,890 that would be we need to modify the 202 00:11:25,890 --> 00:11:29,310 figure object, so the p variable. So 203 00:11:29,310 --> 00:11:32,730 we're working on the y axis, so y axis. 204 00:11:34,530 --> 00:11:37,890 So we access the y axis objects of the 205 00:11:37,912 --> 00:11:43,409 figure object, then minor_tick_color. 206 00:11:43,410 --> 00:11:45,642 [No audio] 207 00:11:45,644 --> 00:11:47,006 And we want to set it to None. 208 00:11:47,007 --> 00:11:49,203 [No audio] 209 00:11:49,205 --> 00:11:51,207 So this sticks here. 210 00:11:51,208 --> 00:11:54,367 [No audio] 211 00:11:54,368 --> 00:11:56,614 Also you can see that we also have a grid. 212 00:11:57,508 --> 00:12:00,150 So we don't want this intermediate lines here. 213 00:12:01,560 --> 00:12:05,430 We can do that by accessing the grid 214 00:12:05,820 --> 00:12:09,300 object which is list, so you need to 215 00:12:09,360 --> 00:12:11,400 access the first item of the list. So 216 00:12:11,400 --> 00:12:12,999 there's quite a trick there. But you 217 00:12:13,499 --> 00:12:18,150 have to make peace with that. So ticker, say 218 00:12:18,330 --> 00:12:24,360 desired number of ticks. So that's 219 00:12:24,360 --> 00:12:29,190 the method and set it to 1. So let's 220 00:12:29,190 --> 00:12:32,100 see how the graph of change this time. 221 00:12:33,120 --> 00:12:35,790 And it's a good idea to put the graph 222 00:12:35,850 --> 00:12:38,250 another name so that we compare the two 223 00:12:38,250 --> 00:12:41,910 graphs so graph one for this. Let's see. 224 00:12:41,911 --> 00:12:47,308 [No audio] 225 00:12:47,310 --> 00:12:49,328 Here, yeah. 226 00:12:49,329 --> 00:12:53,145 [No audio] 227 00:12:53,147 --> 00:12:54,240 And Quit. 228 00:12:54,241 --> 00:12:57,958 [No audio] 229 00:12:57,960 --> 00:12:59,338 And I've got an attribute 230 00:12:59,340 --> 00:13:04,140 error, and minor_tick_color. I tend to put this 231 00:13:04,140 --> 00:13:07,620 wrongly, the good thing is Bokeh is quitted 232 00:13:07,620 --> 00:13:10,740 good error handling. So it says similar 233 00:13:10,740 --> 00:13:13,830 attributes are minor_tick_line_color. So 234 00:13:13,830 --> 00:13:15,810 it's actually able to read what you 235 00:13:15,840 --> 00:13:18,330 input there, and it suggests you want to 236 00:13:18,330 --> 00:13:22,470 input, so minor_tick_line_color. So we've 237 00:13:22,470 --> 00:13:26,160 got a line here. So try again. 238 00:13:26,176 --> 00:13:34,438 [No audio] 239 00:13:34,440 --> 00:13:39,750 Let's see this time we'll get so now it 240 00:13:39,750 --> 00:13:43,080 looks cleaner as you can see. Here is 241 00:13:43,080 --> 00:13:45,690 our previous graph. This is the new one, 242 00:13:45,690 --> 00:13:48,390 so we don't have a horizontal gridlines 243 00:13:48,930 --> 00:13:54,510 the ticks in here, and I thought off 244 00:13:54,510 --> 00:13:56,790 stopping this lecture at this point, and 245 00:13:56,790 --> 00:13:59,520 the other lecture I'll show you how to 246 00:13:59,550 --> 00:14:01,470 add these hover capabilities to your 247 00:14:01,470 --> 00:14:05,930 graph. So I'll talk to you in the next lecture.