YouTube2Text

Изучение Python OpenCV / Урок #2 – Работа с изображениями и видео — Transcript

by Гоша Дударь · 5,778 words · 839 segments · language en · Watch on YouTube

Full transcript

  1. 0:00Hello. In this lesson, we'll learn how
  2. 0:02to work with images and videos using
  3. 0:04OpenCV. But before we explore the
  4. 0:08library and its capabilities, we should
  5. 0:10first understand what an image is made
  6. 0:11of and how to describe an image
  7. 0:13numerically in programming. But before
  8. 0:16we begin, I recommend itproger.com. On
  9. 0:19this site, you'll find code, homework
  10. 0:21assignments, and a lot of other useful
  11. 0:23information. The link to this lesson on
  12. 0:24the site will be in the description of
  13. 0:26this video. Go ahead, you won't regret
  14. 0:28it. It's no secret that images are made
  15. 0:30up of pixels. First, let's look at a
  16. 0:33simple example image. Imagine we need
  17. 0:35to display a black number on a white
  18. 0:37background. In this case, we only have
  19. 0:40two colors. To describe all the white
  20. 0:42dots, we can use the number one, or a
  21. 0:44white pixel. And to describe all the
  22. 0:47black dots, we'll use the number zero,
  23. 0:49or a black pixel. Such an image is easy
  24. 0:52to display and represent numerically,
  25. 0:54since we only have two numbers and two
  26. 0:55colors. Accordingly, when it comes to
  27. 0:58large black-and-white photographs, the
  28. 1:00principle is the same: you just need to
  29. 1:02create more black dots and more white
  30. 1:04dots. Describing such an image is as
  31. 1:06simple as describing a regular number.
  32. 1:08It still uses a binary format, meaning
  33. 1:10only ones and zeros. So far, we've
  34. 1:13looked at an image with two levels:
  35. 1:15black and white. Adding more levels
  36. 1:18creates more color gamut formats.
  37. 1:21Typically, 256 layers are used, from
  38. 1:23pure black to pure white. This gradient
  39. 1:26contains all shades of gray, allowing
  40. 1:28for images of a completely different
  41. 1:30quality. To describe such an image, we
  42. 1:34designate each cell from zero (pure
  43. 1:36black) to 255 (pure white). It turns
  44. 1:40out that an image consisting of a set
  45. 1:42of grayscale colors can be described
  46. 1:43just as simply. After all, the
  47. 1:46principle is the same, but the number
  48. 1:48of numbers increases to 255. Color
  49. 1:50images consist of three grayscale
  50. 1:52images, each converted to red, green,
  51. 1:55and blue, respectively. When these
  52. 1:57three images are superimposed, we
  53. 1:59obtain a color gamut. To describe such
  54. 2:02a photo numerically, we need to specify
  55. 2:04three values for each pixel: a value
  56. 2:07from zero to 255 from the first red
  57. 2:09image, a value from zero to 255 from
  58. 2:11the second green image, and finally, a
  59. 2:14value from zero to 255 from the third
  60. 2:16blue image. This format is also called
  61. 2:19RGB, and it is very common in
  62. 2:21programming when specifying different
  63. 2:23colors. If we are talking about videos,
  64. 2:26they, in turn, consist of hundreds or
  65. 2:28even thousands of images that quickly
  66. 2:30switch between each other. This creates
  67. 2:32the effect of animation. We can
  68. 2:34describe a video numerically by
  69. 2:36describing each individual image using
  70. 2:38the same principle we discussed earlier
  71. 2:40. Now that we know how images work and
  72. 2:43are read, we can move on to exploring
  73. 2:45the library itself. In this lesson, we
  74. 2:48will learn how to open and work with
  75. 2:49images and videos, and also become
  76. 2:51familiar with several basic functions
  77. 2:53for working with them. So, first of all
  78. 2:56, let's create a new file. This file
  79. 2:59itself can have any name. For example,
  80. 3:02I will call it main.p. At the very top,
  81. 3:04we need to import our Open CV library.
  82. 3:07That's why we specify the keyword. And
  83. 3:10our library, it's called CV2. That's
  84. 3:13why we import it by that name. That is,
  85. 3:16to import Open CV, we specify "CV."
  86. 3:19Then, after importing, we can easily
  87. 3:21access this library and access its
  88. 3:23various capabilities. First, I suggest
  89. 3:28exploring how to load and display
  90. 3:29images to the user. To implement this,
  91. 3:34we first need to create a variable.
  92. 3:37Let's call it image. Next, we access
  93. 3:40our CV2 library. And then, using a dot,
  94. 3:44we can access one of its possible
  95. 3:45functions. We're interested in a
  96. 3:48function called "I am read." Or,
  97. 3:50literally, it stands for "image read,"
  98. 3:52that is, read an image. And here, one
  99. 3:55parameter must be passed to this
  100. 3:57function. This is the full path to the
  101. 3:59image that needs to be loaded. Well,
  102. 4:02let me now create a new folder here.
  103. 4:05Let's call this folder, for example,
  104. 4:07images. And inside this folder, I'll
  105. 4:09place the image I've already prepared.
  106. 4:12That is, this image is simply an icon
  107. 4:14for this video lesson. Let me add this
  108. 4:16icon here. And after adding it, I can
  109. 4:19easily—it's also open for me—go to
  110. 4:22the Images folder. And then from the
  111. 4:25Images folder, I need to select this
  112. 4:27photo. I have it here as OpenCV.Pack.
  113. 4:30You can add any photo you want to the
  114. 4:32project. You can simply download it
  115. 4:34from Google. And, accordingly, you can
  116. 4:36attach it here in the same format.
  117. 4:40After loading the image, we need to
  118. 4:42display it, so we access our library
  119. 4:44and call a method called Show, that is,
  120. 4:46to display the image. This method takes
  121. 4:50two parameters. The first parameter is
  122. 4:52the caption for our image. The caption
  123. 4:55can be anything. Just don't enter it in
  124. 4:57Russian, because otherwise, it will
  125. 4:59most likely be displayed incorrectly,
  126. 5:01since we haven't set the encoding. I
  127. 5:03suggest entering it in English. Well,
  128. 5:05let's say it says Rzle here, yes,
  129. 5:07that's the result. As the second
  130. 5:09parameter, we need to specify the image
  131. 5:11itself. I have this image, it's in a
  132. 5:14separate variable in the EMG variable,
  133. 5:16so I'm passing it here. Also, if we try
  134. 5:19to run the program now, unfortunately,
  135. 5:21we won't notice anything yet. That is,
  136. 5:23the image will open and then
  137. 5:25immediately close. The thing is, we
  138. 5:27need to specify a time. And this time
  139. 5:30will be the time while the image will
  140. 5:31be displayed. To specify the time, we
  141. 5:34again access the library, we access the
  142. 5:37weight key method. And here I can
  143. 5:39specify the number of milliseconds. For
  144. 5:41example, if I specify a value of 1.000
  145. 5:43here, it will be 1.000 milliseconds, or
  146. 5:46, in other words, 1 second. And this is
  147. 5:48exactly how long the image will be
  148. 5:50displayed. So, at this point, my
  149. 5:51program will start, the image will be
  150. 5:53displayed for one second, and then the
  151. 5:55image will simply disappear. You can
  152. 5:57also specify 10 seconds here or 100
  153. 5:59seconds there. Well, for example, you
  154. 6:01can simply increase this number. I want
  155. 6:04to specify that the image will be
  156. 6:05displayed indefinitely. That is, it
  157. 6:09will be displayed until I manually stop
  158. 6:11the program or until I manually close
  159. 6:13the image. To specify this, I simply
  160. 6:16need to enter a zero here. This means
  161. 6:20that the image will be displayed
  162. 6:21indefinitely until I manually stop it.
  163. 6:25Now let's try testing all this. To do
  164. 6:28this, I right-click on our main file
  165. 6:29and simply click run. You might also
  166. 6:32think that an error occurred. In fact,
  167. 6:34it's just a notification text. Well, if
  168. 6:37you look closely, the image actually
  169. 6:38opened correctly. We have a caption for
  170. 6:41this image. And the image itself, here
  171. 6:43it is displayed. Everything is fine
  172. 6:44with it. Now, to stop the program, we
  173. 6:46can simply go to the PRM, here, as if
  174. 6:48clicking on stop the program. So, we
  175. 6:50see that the program has finished, and
  176. 6:52everything seems to have been processed
  177. 6:54correctly. Now, in addition to photos,
  178. 6:56let's learn how to display various
  179. 6:58videos. To begin, I suggest creating a
  180. 7:01new folder. Let's call this folder
  181. 7:03Windows, and I'll place the video I've
  182. 7:05already prepared in this folder. It's a
  183. 7:07fairly simple video, and a short one at
  184. 7:09that. I also recommend finding a short
  185. 7:13video, because if you're simply
  186. 7:14processing a very long video, it will
  187. 7:16take a long time to process. Therefore,
  188. 7:19it's better to find a video up to 20
  189. 7:21seconds long. I have just such a video.
  190. 7:24Now, I suggest commenting out all this
  191. 7:26code for now, so it doesn't get in the
  192. 7:27way. And just below, let's write the
  193. 7:31code for displaying a video. Here, we
  194. 7:34first need to create a variable. This
  195. 7:36variable can be called anything, but
  196. 7:38it's usually called cap, which stands
  197. 7:40for capture, or, in other words, a
  198. 7:42recording. And here we place the
  199. 7:44following. We access our library. Next,
  200. 7:48we call a method called video capture.
  201. 7:53We pass the full path to the file we
  202. 7:54want to work with to this method. I
  203. 7:57have this file, it's in the Window
  204. 7:58folder. And then the file itself, it's
  205. 8:01called rot.mp 4. Accordingly, I'm
  206. 8:05passing that exact name here. Next,
  207. 8:08since we're working with video, we need
  208. 8:10to create a loop. Again, let me remind
  209. 8:14you that a video consists of many
  210. 8:16different images that smoothly switch
  211. 8:18between each other, thereby creating an
  212. 8:20animation effect. Accordingly, we need
  213. 8:23to create a loop. And in this same loop
  214. 8:26, we'll completely loop through all of
  215. 8:28these images that make up the video
  216. 8:29itself. And we'll show each individual
  217. 8:32image to the user. This is how we
  218. 8:35create the video effect. And here we
  219. 8:37simply create a loop. Our loop is
  220. 8:39pretty trivial. We simply specify while
  221. 8:41true. That is, we create an infinite
  222. 8:43loop. And in fact, this loop will be
  223. 8:45terminated in two cases. First, if the
  224. 8:48video plays to the end, the loop will
  225. 8:50end. We'll even get a small error in
  226. 8:52the terminal. Well, that won't affect
  227. 8:55anything, but if the video ends, the
  228. 8:57loop will also end, plus there will be
  229. 8:59a small error. That's it. And the
  230. 9:02second way we'll end the loop is when
  231. 9:04we press a key. Let's say I press the Q
  232. 9:08key. If I press that key, the video
  233. 9:11will also end. We'll finish this check
  234. 9:14a little later. So, to start, let's
  235. 9:17define a few variables here. First, I
  236. 9:20suggest we define a variable, let's
  237. 9:22call it success. We'll also create a
  238. 9:26second variable here, which I'll call
  239. 9:28G. And I'll put the following in these
  240. 9:29variables. I'm accessing our video and
  241. 9:34calling the read method, which is the
  242. 9:36method that allows us to read the video
  243. 9:38itself. What will we store in these
  244. 9:42variables? Look, the success variable
  245. 9:45will be set to either true or false.
  246. 9:49True will be the value if we were able
  247. 9:51to read the current video image. False
  248. 9:55will be the value if we were unable to
  249. 9:57read the current video image. And then,
  250. 10:00the image variable, our second variable
  251. 10:02, will be set to the current image
  252. 10:03itself. And then, to simply display
  253. 10:07this image itself for now, we, of
  254. 10:09course, need to call the method we're
  255. 10:11already familiar with. This is show,
  256. 10:14which means to display an image. Yes,
  257. 10:17this method. We can pass any caption
  258. 10:19here. I'll specify the caption here
  259. 10:21again, let's call it result. And then
  260. 10:23we pass our image. In my case, it's G.
  261. 10:27At this point, nothing will be
  262. 10:28processed, since we still need to add
  263. 10:30one more condition here. In this
  264. 10:33condition, we'll simply specify a call
  265. 10:35to the weight key method. And here,
  266. 10:37we'll simply specify some minimum value
  267. 10:39, for example, 1 millisecond. Well,
  268. 10:41it's not possible to simply specify a
  269. 10:43smaller value. We simply need to call
  270. 10:45this method so that the video itself is
  271. 10:47displayed correctly. And we can specify
  272. 10:50a minimum value here. This way, each
  273. 10:53image in the video itself will be
  274. 10:54displayed for a minimum amount of time,
  275. 10:56right? That is, they will switch
  276. 10:59between each other as quickly as
  277. 11:00possible, so we will essentially see
  278. 11:02the video itself. We also need to add
  279. 11:06another operation here, or rather,
  280. 11:07another condition. And here we will
  281. 11:11track a key like Q. You can track
  282. 11:13different keys. We will track the Q key
  283. 11:16specifically. And here we simply need
  284. 11:19to write the code for this key. It, in
  285. 11:21turn, is like this. Well, if any of
  286. 11:24these match, then we will, as it were,
  287. 11:27break out of the loop itself. Now let's
  288. 11:30run our entire project and see what
  289. 11:32we've got. Here, our video is playing.
  290. 11:35If you press Q, unfortunately, nothing
  291. 11:37will happen at this point. So, let's
  292. 11:39probably just stop the program for now.
  293. 11:43And nothing happens because we need to
  294. 11:45change the order of these conditions,
  295. 11:46right? So, we need to check, well,
  296. 11:49initially write the code, and then
  297. 11:51check for the OR function. In this case
  298. 11:54, this key will be processed correctly.
  299. 11:56So, here we go again. We've started the
  300. 11:58video, everything works correctly. I
  301. 12:00press Q. And then the video stops,
  302. 12:02everything works correctly.
  303. 12:04Additionally, thanks to Open CV, you
  304. 12:06can also read data from a webcam. To do
  305. 12:10this, instead of the full path to a
  306. 12:12video, you just need to specify zero.
  307. 12:16This way, you'll access the only
  308. 12:18current webcam on your computer. If you
  309. 12:22have multiple webcams, you can specify
  310. 12:24their numbers. So, for example, zero
  311. 12:26means accessing the first camera, one
  312. 12:28means accessing the second camera, and
  313. 12:30so on. I only have one webcam, so I'm
  314. 12:33leaving it at zero here. Also, before
  315. 12:36we test and run this, we need to
  316. 12:38specify the dimensions for the image
  317. 12:40itself. To do this, we specify here,
  318. 12:43well, that is, we access our capture,
  319. 12:46our video, and access the set method.
  320. 12:49We need to pass two parameters here.
  321. 12:51These are the ID, uh, the
  322. 12:52characteristics that we'll be setting,
  323. 12:55and the value itself. For example, if I
  324. 12:58want to set the width, the width's ID
  325. 13:00is three, so I enter three here. You
  326. 13:03can also specify any width you like.
  327. 13:05Let's say I specify it as 500. I also
  328. 13:07want to specify the height. The height
  329. 13:11is identified by ID four, so I specify
  330. 13:13that here. And let's say we specify the
  331. 13:16height as 300. So, my image will be 500
  332. 13:19by 300. If we run this now, we'll
  333. 13:21notice that our webcam opens correctly.
  334. 13:24It displays the correct image. If you
  335. 13:26want to exit the webcam, you can simply
  336. 13:28press the Q key. Now let's explore some
  337. 13:31image manipulation functions. Since the
  338. 13:37Open CV library works with images and
  339. 13:39video, it naturally includes a ton of
  340. 13:40different functions for transforming
  341. 13:42various videos and images. We'll
  342. 13:47explore some of these functions now,
  343. 13:49and we'll continue to explore them
  344. 13:50throughout the video course. Then, in
  345. 13:54the final lessons of this course, we'll
  346. 13:56be able to use this knowledge to
  347. 13:58develop a neural network, for example,
  348. 14:00for face recognition or license plate
  349. 14:02tracking. For now, let's reduce the
  350. 14:06image size. My image is way too big. So
  351. 14:11, before we reduce it, let's perhaps
  352. 14:13display its dimensions on the screen.
  353. 14:15To do this, I simply access our image,
  354. 14:18my EMG variable, and access the shape
  355. 14:20value. I also suggest commenting out
  356. 14:23the image output itself so that we
  357. 14:25simply output the data to the terminal.
  358. 14:27And so we get a tuple consisting of
  359. 14:29three elements. The first element is
  360. 14:31the height of our image, 720 pixels.
  361. 14:34The second element is the image width,
  362. 14:361,280 pixels. And the third element is
  363. 14:39the number of layers. The thing is, our
  364. 14:41image is in the standard RGB format,
  365. 14:43meaning we have three layers. These are
  366. 14:46red, green, and blue, or, in other
  367. 14:48words, red, green, and blue. And,
  368. 14:51accordingly, this is the number that
  369. 14:52was output here. If we need to change
  370. 14:56the dimensions of the image itself, we
  371. 14:58can do it as follows. First, we can
  372. 15:01create a new variable. Let's call it
  373. 15:04new image. Well, let's say this is its
  374. 15:06name. And then I set the following to
  375. 15:09this variable. I access our library and
  376. 15:12call a method called resй. Here, in
  377. 15:16this method, I first pass the image I
  378. 15:18need to change. In my case, it's our
  379. 15:22standard image. And as the second
  380. 15:25parameter, I pass a tuple containing
  381. 15:27two elements: the new width and the new
  382. 15:29height. What's interesting is that you
  383. 15:32can specify new dimensions here that
  384. 15:34will be larger than the current value.
  385. 15:36That is, you can specify, for example,
  386. 15:382000 by 2000, and it will be processed
  387. 15:40absolutely correctly. But let's specify
  388. 15:43here, perhaps, something like 300 by
  389. 15:45500; let's say, those are the
  390. 15:46dimensions here. And a little lower,
  391. 15:50I'd like to display not the image we
  392. 15:52initially uploaded, but a new image. So
  393. 15:56, let's write new image here, and,
  394. 15:58accordingly, we will display this image
  395. 16:00. So, let's run the program. And if we
  396. 16:04look now, you can see that our width is
  397. 16:06300 pixels, right? And the height is
  398. 16:09500 pixels. So, when we specify the
  399. 16:12Rйiz method, we first specify the
  400. 16:14width, then the height. But when we
  401. 16:17output these values, they're output in
  402. 16:19a slightly different format. The height
  403. 16:22is output first, then the width. If you
  404. 16:25want to scale the image down
  405. 16:26proportionally, you can do it this way.
  406. 16:29We first access our main image. Then we
  407. 16:33access its size. And we take it here,
  408. 16:35that is, we initially need to take the
  409. 16:37width. The width is like the second
  410. 16:39element for us. It will be indexed as
  411. 16:42the first element, yes, because indexes
  412. 16:44start at zero. So, we take the current
  413. 16:48width of our image and simply divide it
  414. 16:50by two. But I'd also like to round this
  415. 16:54all down to a whole number, so I put
  416. 16:56two division signs here. This way, we
  417. 16:59get a whole number. I do exactly the
  418. 17:01same thing with the height, only I
  419. 17:03specify a different index here. Again,
  420. 17:05let me remind you that the first
  421. 17:07element in the shape tuple was
  422. 17:08responsible for the height, so we take
  423. 17:10it here at index zero. And we also end
  424. 17:12up dividing it by two. Furthermore, we
  425. 17:15could actually avoid creating a new
  426. 17:16variable here. Let's not do that. I'll
  427. 17:19simply assign a new value to the same
  428. 17:21variable. That's perfectly fine. There
  429. 17:23won't be any problems with that. Now,
  430. 17:25if we run this, we'll notice that our
  431. 17:27image has become exactly half as big,
  432. 17:29right? That is, it's proportionally
  433. 17:31smaller, both in width and height. If
  434. 17:35you don't need to reduce the image's
  435. 17:37size, but simply crop it, you can use
  436. 17:39indices and slices. For example, when I
  437. 17:43display the image here, I'll
  438. 17:44immediately try to crop it. That is,
  439. 17:46I'll try to display only a specific
  440. 17:48part of the image. And for that, I need
  441. 17:50to use indices and slices. Here, look,
  442. 17:52I want to, for example, specify that
  443. 17:55I'll take the first 100 pixels of the
  444. 17:57image by width. I'll take them and
  445. 17:59display them on the screen. And also,
  446. 18:00let's say, I want to take the first 100
  447. 18:02pixels by height, or even the first 150
  448. 18:04pixels, and I want to display them on
  449. 18:06the screen too. To specify this, I
  450. 18:09specify here that it's as if the
  451. 18:11zero-based coordinate is located at
  452. 18:13this point, that is, in the upper left
  453. 18:15corner, we have the zero-based
  454. 18:16coordinate. Everything is calculated
  455. 18:18from it, right. So, if I specify it
  456. 18:21from zero, then, accordingly, it's from
  457. 18:23this point. So, from zero to 100 pixels
  458. 18:27, we'll crop this image by width. And
  459. 18:31also, from zero to 150 pixels by height
  460. 18:33, we'll crop this image. Well, in fact,
  461. 18:37this cropped piece will be shown. Well,
  462. 18:40user, right. Let's restart the project.
  463. 18:42Here I restarted it. And now we notice
  464. 18:44that, you see, everything was processed
  465. 18:46absolutely correctly. That is, we got
  466. 18:48an image that consists of a small piece
  467. 18:50of our previous image. I don’t need
  468. 18:53to crop the image at the moment. So,
  469. 18:56let me cut this code out anyway. I’ll
  470. 18:59also leave it here so you just remember
  471. 19:01how to crop an image by the required
  472. 19:02number of pixels. In addition, let’s
  473. 19:06now study some methods that allow us to
  474. 19:08transform the image itself. For now,
  475. 19:13let’s study a method that allows us
  476. 19:14to add additional blur to an image.
  477. 19:18First, we need to create a variable. We
  478. 19:21can create a new variable, or I’ll
  479. 19:23write everything to an existing
  480. 19:24variable. This won’t be fundamentally
  481. 19:27important. Here we access our library
  482. 19:30and call a method called Gusen Blur.
  483. 19:34Here I need to specify several
  484. 19:35parameters. First, this is the image we
  485. 19:37are working with. In my case, this is
  486. 19:39the image stored in the EMG variable.
  487. 19:42The second parameter is the kernel size
  488. 19:44. This is how much blur we'll apply to
  489. 19:47our image. The second parameter is a
  490. 19:51map. We pass two values here. Let's say
  491. 19:53I'm not going to have a super strong
  492. 19:55blur right now. Let's say I specify
  493. 19:57three and three. We'll change that a
  494. 19:59little later. You'll be able to see a
  495. 20:00stronger blur format. We also need to
  496. 20:03specify sig. For now, let's just set
  497. 20:06the value to zero here. Sig x is
  498. 20:08essentially a multiplier for this blur
  499. 20:11applied to the image, yes. Right now,
  500. 20:15we won't have this enhanced blur in the
  501. 20:17image. If we run this now, we'll notice
  502. 20:22that the image is still a little blurry
  503. 20:23. It's not super noticeable, but if we
  504. 20:28increase the value now, let's say we
  505. 20:30set the value to nine. Incidentally,
  506. 20:33there's an important point here. If you
  507. 20:35set values like, for example, 8 or 4—
  508. 20:38that is, if you set even values—then
  509. 20:40all of this will generate an error. You
  510. 20:42can only set odd values here, like 3, 5
  511. 20:46, 7, 9, and so on. Let's set 9.9. If I
  512. 20:50run this now, you'll notice that the
  513. 20:52image is actually quite blurry. We can
  514. 20:56easily see this here. So, with Gusin BL
  515. 20:59, you can quickly blur the image you
  516. 21:01need. The Open CV library also has a
  517. 21:05variety of functions that allow us to
  518. 21:07convert the image to the desired format
  519. 21:09. Currently, our image format is RGB,
  520. 21:13meaning we use three layers: red, green
  521. 21:16, and blue. But we can also convert the
  522. 21:19image to any other format. If we
  523. 21:24convert an image to, say, black and
  524. 21:26white or grayscale, then working with
  525. 21:28it is much easier because the number of
  526. 21:30colors is reduced, and processing the
  527. 21:32photo itself is significantly faster.
  528. 21:38So, let's now try converting our RGB
  529. 21:40image to grayscale. To do this, we need
  530. 21:44to create a new variable. Again, I'll
  531. 21:46be storing everything in the same
  532. 21:48variable. Here, we simply access our
  533. 21:52library, accessing a method called CVT
  534. 21:54color, or, in full, convert color. Here
  535. 21:58, we specify several parameters. First,
  536. 22:01the image we're working with. We also
  537. 22:03simply specify the ghost format. For
  538. 22:06this, we need to access our library
  539. 22:08again. And here, we access the format
  540. 22:11we need. Look, our image is in RGB
  541. 22:14format, but if we're talking about Open
  542. 22:16CV, this format is called BGR. So, it's
  543. 22:20essentially the same thing as RGB. RGB
  544. 22:23is simply red, green, blue, and BGR is
  545. 22:26blue, green, red. Well, it's sort of
  546. 22:29flipped, but essentially, it's the same
  547. 22:31thing. So, we need to use a format like
  548. 22:33BGR to grade, right? So, we're
  549. 22:35converting the RGB format—or what's
  550. 22:37called BGR here—to a format like this
  551. 22:40. If we run this now, we'll notice that
  552. 22:43our image is blurry and gray. So, it's
  553. 22:47really just gray. There aren't any
  554. 22:49additional layers here. Now there's one
  555. 22:51layer, and it's kind of a gray layer.
  556. 22:54By the way, we can even try to display
  557. 22:56information about the image now. Let me
  558. 22:59just uncomment this. And let's stop the
  559. 23:01program and run it again. And now we
  560. 23:03can see that, you see, we have a third
  561. 23:05parameter. It's not even passed here,
  562. 23:07but in fact, if it were specified here,
  563. 23:09it would simply be a one, yes, because
  564. 23:11we are really only using one layer now.
  565. 23:13This is a gray layer, so to speak.
  566. 23:16Previously, three layers were used: red
  567. 23:19, green, and blue. Later, we will need
  568. 23:22to find the corners of the image. The
  569. 23:25thing is, if we find the corners of the
  570. 23:27image, then we can determine key points
  571. 23:29, so to speak. And this will make it
  572. 23:32easier for us to understand what is in
  573. 23:33a particular image. To find the corners
  574. 23:36of the image, we need to use a special
  575. 23:38built-in function that exists in Open
  576. 23:40CV. We will study it now. Again, we
  577. 23:44will set a new value in the same
  578. 23:46variable. That is, we turn to our
  579. 23:49library and then call a method called
  580. 23:51Cany. This method accepts, well, three
  581. 23:55required parameters. The first
  582. 23:57parameter is, of course, our image. And
  583. 24:00as the second parameter, we need to
  584. 24:02pass threshold 1, or the first
  585. 24:03threshold. And as the third parameter,
  586. 24:06threshold 2, or the second threshold.
  587. 24:08What are thresholds? Thresholds are
  588. 24:11something like the precision of
  589. 24:12determining all these angles. And let's
  590. 24:15now specify a value here, say, like 90
  591. 24:17and 90, and just run it and try to see
  592. 24:20what we get, and then change these
  593. 24:22values. Well, look, at this point, what
  594. 24:25we get is that our image now looks
  595. 24:27completely different from how it looked
  596. 24:29before. That is, our image is now a
  597. 24:32binary image. There are only two colors
  598. 24:35here: black and white. And thanks to
  599. 24:38this white color, we have all the
  600. 24:40outlines, so to speak. For example, I
  601. 24:43had text here, I had various circles
  602. 24:45here, and I had some other image here.
  603. 24:49And, accordingly, it's all outlined,
  604. 24:51plus this and that image, it's now
  605. 24:53actually in binary format. That is,
  606. 24:56from a programming perspective,
  607. 24:58describing such an image is very, very
  608. 25:00simple, since there are only two colors
  609. 25:02, and, accordingly, either zeros or
  610. 25:04ones are used here. Again, ones are
  611. 25:07needed to describe everything, well,
  612. 25:09white, and zeros are needed to describe
  613. 25:11black. That's all. And, by the way,
  614. 25:15converting such an image to binary
  615. 25:17format without initially converting it
  616. 25:19to grayscale would be difficult,
  617. 25:21because converting from RGB to binary
  618. 25:23format directly would be, well, quite
  619. 25:25problematic, since we have so many
  620. 25:27colors, and most likely, the library
  621. 25:28simply won't understand where exactly
  622. 25:30it needs to place all these outlines.
  623. 25:35But when we have grayscale format, when
  624. 25:37we only have one layer instead of three
  625. 25:39, as before, then, accordingly,
  626. 25:41converting from one layer to binary
  627. 25:43format and to an even simpler format is
  628. 25:45no longer, well, a particular problem.
  629. 25:48Well, look, here we specify thresholds,
  630. 25:50so to speak. This is like the precision
  631. 25:53of defining all these outlines. And
  632. 25:54right now, I've set it to 90. And in
  633. 25:56fact, it's already worked absolutely
  634. 25:58correctly. Well, since I have a fairly
  635. 26:01simple image, everything worked
  636. 26:03absolutely correctly here, but you
  637. 26:05could specify a value here, say, like
  638. 26:0730 or 30. And let's just try to see
  639. 26:09what we get in that case. And in that
  640. 26:14case, we can notice that, see, our
  641. 26:15precision for this particular drawing
  642. 26:17has improved, right, because more
  643. 26:19contours have appeared and more small
  644. 26:21details have been involved, right? That
  645. 26:25is, if you need greater precision, then
  646. 26:27, accordingly, you can decrease this
  647. 26:29value. If I specify, say, 300 here, and
  648. 26:32let's stop this and run it again, we
  649. 26:34can see that, see, how few contours
  650. 26:36were outlined here, right? In fact, for
  651. 26:39this drawing, we just drew a tiny bit
  652. 26:43of contours here, yes. We'll probably
  653. 26:45leave the value at 100x100 or 90x90.
  654. 26:48This value suited me just fine, so
  655. 26:50we'll probably leave it as is for now.
  656. 26:55Furthermore, we can add additional
  657. 26:57width to all these contours or,
  658. 26:58conversely, decrease this width. That
  659. 27:01is, we can increase or decrease the
  660. 27:03stroke width. To implement this, we
  661. 27:06need to use some additional functions.
  662. 27:09Let's look at them now. So, let's turn
  663. 27:12to the library. We'll use a method
  664. 27:15called delate. This method takes
  665. 27:19several parameters. First, it's the
  666. 27:21image itself. Second, it's a kpnel. And
  667. 27:26kpnel is essentially the number of
  668. 27:28points with which we will, well,
  669. 27:30describe this width. And here, to
  670. 27:34specify the number of points, we need
  671. 27:36to create a matrix. A matrix comes in a
  672. 27:40format where we write a single list,
  673. 27:42and within that list, each element is
  674. 27:44some other list, right? So, let's say,
  675. 27:47if I write something like this, then
  676. 27:49that would be a matrix, right? So, we
  677. 27:52have one list, and within it, there are
  678. 27:54other different lists. So, of course,
  679. 27:58we can create such a list ourselves,
  680. 28:00but why bother creating it ourselves if
  681. 28:02we have a library called whatever we
  682. 28:04like? So, I'll import it here too. If
  683. 28:11you don't have this library here, you
  684. 28:12can go to the terminal. Here you can
  685. 28:16type pip install and then num. Well,
  686. 28:19I'll even do this just in case, to make
  687. 28:21sure it's installed. I already have it
  688. 28:23installed, so nothing was downloaded.
  689. 28:25Well, if you don't have it installed,
  690. 28:27it would have been downloaded. And here
  691. 28:29I can probably add an alias. Mm, of
  692. 28:31course, you don't have to add it, but
  693. 28:33for some reason, they always add an
  694. 28:35alias in any documentation. I'll
  695. 28:36probably do the same. And I'll simply
  696. 28:40refer to this library, the PAY library,
  697. 28:42by its shorter name, but you don't have
  698. 28:44to add the alias. That's up to you, of
  699. 28:48course. So what do I want to do? I want
  700. 28:51to create this matrix. Again, it's very
  701. 28:54convenient to create a matrix if we're
  702. 28:56using PAY. Let's initially create a
  703. 28:58variable. Let's call it KNNEL. Since
  704. 29:00we'll be substituting kрnel here, yes,
  705. 29:02we'll name the parameter that way, too.
  706. 29:05Here, we're accessing our library,
  707. 29:07accessing a method called. And what
  708. 29:12this method does is create a matrix in
  709. 29:14which all elements will have the value
  710. 29:16one. And here we simply specify the
  711. 29:20number of elements in the first list
  712. 29:22and the number of elements in all
  713. 29:23subsequent lists. So, for example, I'll
  714. 29:26just say that our first list here will
  715. 29:28have five elements. So, well,
  716. 29:29essentially, there will be five more
  717. 29:32lists like this. And each of these
  718. 29:33lists will have five elements. For
  719. 29:35example, one 1 one. And so on. So, five
  720. 29:38elements. To indicate this, I specify a
  721. 29:41tuple here and specify that our first
  722. 29:43list consists of five elements. And
  723. 29:45each of the following lists will also
  724. 29:47have five elements. Plus, we can
  725. 29:50additionally specify the format of
  726. 29:52these numbers themselves. For this, we
  727. 29:55again turn to us. And here we simply
  728. 29:58specify the data type. I'll use a data
  729. 30:00type like u in. Let's write it
  730. 30:03correctly. U in 8. So, this means that
  731. 30:06we can only have numbers that are
  732. 30:08greater than zero. And these are
  733. 30:11integers, yes, 1 2 3 4 and so on. We've
  734. 30:14specified this format here. Now,
  735. 30:15finally, we can specify the kernel here
  736. 30:18. So, we'll create the matrix we need.
  737. 30:21We also need to specify the iteration
  738. 30:23value here. Iteration is simply a loop
  739. 30:26—yes, how many times will the code we
  740. 30:28need execute? Well, in fact, if I
  741. 30:30specify, for example, a value of 10
  742. 30:32here, then a very, very large outline
  743. 30:35will be added. Let's start with a value
  744. 30:37of one and just try to test it, and
  745. 30:39then increase this value a little later
  746. 30:40. And so, we can see that, see, if I
  747. 30:43specify one, we notice that all our
  748. 30:45outlines become much larger, right? In
  749. 30:49fact, we understand that all these
  750. 30:50numbers, or rather, all these outlines,
  751. 30:52are already connected to each other. If
  752. 30:55there were any gaps somewhere before,
  753. 30:57now these gaps are clearly gone. And,
  754. 31:00of course, in this case, if we actually
  755. 31:02use additional increase in the outline,
  756. 31:05then in fact, we can, of course,
  757. 31:06increase the precision here. Let's say
  758. 31:10we set 150 here, or maybe even 250, or
  759. 31:13better yet, let's just set it to 200.
  760. 31:15Again, we stop the program and restart
  761. 31:18it. And here's what we get, right? So,
  762. 31:22we've reduced the precision of all
  763. 31:24these outlines, while increasing the
  764. 31:25thickness of these outlines, and what
  765. 31:27we get is a picture that essentially
  766. 31:32looks exactly the same as before. But
  767. 31:34since there are fewer lines, further
  768. 31:36processing of the picture will be
  769. 31:38faster, right? So, the more of these
  770. 31:41angles, the more of these lines, the
  771. 31:42longer the further processing of the
  772. 31:44picture will take. At this point, we've
  773. 31:46done everything logically. We've
  774. 31:48reduced, well, the number of angles,
  775. 31:50but increased the thickness. And
  776. 31:55finally, to optimize all of this even
  777. 31:57more thoroughly, after we've converted
  778. 31:59the image to binary format, after we've
  779. 32:01specified all these angles (and we've
  780. 32:03specified them quite small), after
  781. 32:05we've increased the line weight, we'll
  782. 32:07further decrease this line weight a
  783. 32:08little. That is, by using the line
  784. 32:13weight, we were able to simply outline
  785. 32:15all the necessary contours. Moreover,
  786. 32:18once we've outlined all these
  787. 32:19additional contours, we were able to
  788. 32:21specify a lower precision. And now,
  789. 32:24after we've clearly found everything we
  790. 32:26need, we can simply reduce these
  791. 32:28contours. We can reduce this outline's
  792. 32:30thickness. After this, we'll get
  793. 32:34exactly the same image as the original,
  794. 32:36but we'll now specify a lower precision
  795. 32:38here, which will speed up future image
  796. 32:40processing. So, let's implement this.
  797. 32:43To do this, we'll again place
  798. 32:45everything in the same variable. Here
  799. 32:47I'm using a method where we specify
  800. 32:49which image we're working with. That's
  801. 32:51G. We also need to specify the kernel
  802. 32:53here, plus we need to specify the
  803. 32:55number of iterations. Let's say there's
  804. 32:57only one iteration here, right? If we
  805. 33:00run this now, this is what we get. Yes,
  806. 33:03in some cases, we didn't process
  807. 33:05everything perfectly, but for the
  808. 33:07computer, everything was simply perfect
  809. 33:09. What's the main thing we got? We got
  810. 33:14the image, it's in binary format. We
  811. 33:18used lower precision to process it, and
  812. 33:20thereby increased the overall
  813. 33:22processing speed of the entire image.
  814. 33:26We also initially increased the outline
  815. 33:28so that we could 100%cover all the
  816. 33:30necessary corners. And then, to make it
  817. 33:35all more pleasant to look at—or
  818. 33:36rather, not even more pleasant, but so
  819. 33:38that the computer could process it all
  820. 33:40faster—we reduced the number of these
  821. 33:42white dots, and essentially got the
  822. 33:44image we needed. So, it's very easy to
  823. 33:47recognize such an image in the future.
  824. 33:49So, in the future, we'll be working
  825. 33:51with images like these. And we'll be
  826. 33:53recognizing various objects in them.
  827. 33:55For example, we'll be recognizing
  828. 33:57numbers or symbols, right? So, we'll be
  829. 33:59reading license plates. And in the
  830. 34:02future, we'll also be recognizing
  831. 34:04various faces, right? And to do that,
  832. 34:07we'll also be converting the image to
  833. 34:09binary format. Well, that concludes our
  834. 34:11lesson. I hope you enjoyed it. If so,
  835. 34:14don't forget to subscribe to the
  836. 34:16channel and join our social media
  837. 34:17accounts. All the links will be in the
  838. 34:19description of this video. That's all
  839. 34:21for now from me. See you soon. Bye. M.

About this transcript

This page contains the full transcript of Изучение Python OpenCV / Урок #2 – Работа с изображениями и видео by Гоша Дударь, generated from the public captions YouTube serves with the video. The transcript has 5,778 words across 839 segments, with the original timestamps preserved so you can click any line to jump to that moment in the embedded player.

What you can do with it

Use the transcript to take notes, quote the speaker, build a study guide, generate a summary with ChatGPT or Claude via the YouTube Summary tool, or export it as a timed subtitle file with YouTube to SRT. You can also re-open it in the transcriber to translate the transcript into 100+ languages.

Free YouTube transcript tool

YouTube2Text is a free YouTube transcript generator — no signup, no daily limit. Paste any YouTube link and get the full transcript instantly, with timestamps, click-to-jump, translation to 100+ languages, AI prompts for ChatGPT, Claude, and Gemini, and exports to TXT, SRT, VTT, or Markdown.