1 added
1 removed
Original
2026-01-01
Modified
2026-02-21
1
<p><a>#статьи</a></p>
1
<p><a>#статьи</a></p>
2
<ul><li>16 авг 2023</li>
2
<ul><li>16 авг 2023</li>
3
<li>0</li>
3
<li>0</li>
4
</ul><p>Рассказываем, как компьютеры анализируют изображения, и учим их распознавать лица.</p>
4
</ul><p>Рассказываем, как компьютеры анализируют изображения, и учим их распознавать лица.</p>
5
<p>Иллюстрация: Оля Ежак для Skillbox Media</p>
5
<p>Иллюстрация: Оля Ежак для Skillbox Media</p>
6
<p>Журналист, изучает Python. Любит разбираться в мелочах, общаться с людьми и понимать их.</p>
6
<p>Журналист, изучает Python. Любит разбираться в мелочах, общаться с людьми и понимать их.</p>
7
<p>Обучая маленьких детей, родители показывают им книжки с яркими цветными картинками: вот кошечка, вот цветочек, а вот машинка. И дети учатся отличать объекты друг от друга.</p>
7
<p>Обучая маленьких детей, родители показывают им книжки с яркими цветными картинками: вот кошечка, вот цветочек, а вот машинка. И дети учатся отличать объекты друг от друга.</p>
8
<p>Компьютеры обучают распознавать изображения похожим образом - только изображений показывают в тысячи раз больше. Эта технология называется компьютерным зрением.к</p>
8
<p>Компьютеры обучают распознавать изображения похожим образом - только изображений показывают в тысячи раз больше. Эта технология называется компьютерным зрением.к</p>
9
<ul><li><a>Как устроено компьютерное зрение</a></li>
9
<ul><li><a>Как устроено компьютерное зрение</a></li>
10
<li><a>Что такое OpenCV</a></li>
10
<li><a>Что такое OpenCV</a></li>
11
<li><a>Где применяют компьютерное зрение и OpenCV</a></li>
11
<li><a>Где применяют компьютерное зрение и OpenCV</a></li>
12
<li><a>Как работать с OpenCV в Python</a></li>
12
<li><a>Как работать с OpenCV в Python</a></li>
13
</ul><ul><li><a>Установка OpenCV</a></li>
13
</ul><ul><li><a>Установка OpenCV</a></li>
14
<li><a>Как OpenCV видит изображения</a></li>
14
<li><a>Как OpenCV видит изображения</a></li>
15
<li><a>Чтение, режимы отображения и запись</a></li>
15
<li><a>Чтение, режимы отображения и запись</a></li>
16
<li><a>Изменение цвета пикселей</a></li>
16
<li><a>Изменение цвета пикселей</a></li>
17
<li><a>Изменение размера изображения</a></li>
17
<li><a>Изменение размера изображения</a></li>
18
<li><a>Обрезка</a></li>
18
<li><a>Обрезка</a></li>
19
<li><a>Поворот</a></li>
19
<li><a>Поворот</a></li>
20
</ul><ul><li><a>Примеры скриптов OpenCV</a></li>
20
</ul><ul><li><a>Примеры скриптов OpenCV</a></li>
21
</ul><ul><li><a>Отображение координат точки</a></li>
21
</ul><ul><li><a>Отображение координат точки</a></li>
22
<li><a>Распознавание лиц</a></li>
22
<li><a>Распознавание лиц</a></li>
23
</ul><ul><li><a>Что дальше</a></li>
23
</ul><ul><li><a>Что дальше</a></li>
24
</ul><p><strong>Компьютерное зрение</strong> - область искусственного интеллекта, связанная с получением, обработкой и анализом визуальной информации: изображений и видео.</p>
24
</ul><p><strong>Компьютерное зрение</strong> - область искусственного интеллекта, связанная с получением, обработкой и анализом визуальной информации: изображений и видео.</p>
25
<p>Разберём определение на примере. Взгляните на эту картинку и опишите, что на ней изображено:</p>
25
<p>Разберём определение на примере. Взгляните на эту картинку и опишите, что на ней изображено:</p>
26
<em>Кадр: фильм "Матрица" / Warner Bros.</em><p>Взгляд сразу выхватывает отдельные объекты. Тёмные очки, в одной линзе отражается человек, ладонь, красная таблетка, в другой - тот же человек, другая ладонь, синяя таблетка.</p>
26
<em>Кадр: фильм "Матрица" / Warner Bros.</em><p>Взгляд сразу выхватывает отдельные объекты. Тёмные очки, в одной линзе отражается человек, ладонь, красная таблетка, в другой - тот же человек, другая ладонь, синяя таблетка.</p>
27
<p>Если человек смотрел "Матрицу", он назовёт фильм, узнает персонажей и, возможно, даже вспомнит имена актёров - в зависимости от того, насколько он любит кинематограф и как много смотрел фильмов.</p>
27
<p>Если человек смотрел "Матрицу", он назовёт фильм, узнает персонажей и, возможно, даже вспомнит имена актёров - в зависимости от того, насколько он любит кинематограф и как много смотрел фильмов.</p>
28
<p>Что на этом изображении увидит программа, зависит от её бэкграунда, то есть от информации, которая у неё есть, и уровня сложности кода:</p>
28
<p>Что на этом изображении увидит программа, зависит от её бэкграунда, то есть от информации, которая у неё есть, и уровня сложности кода:</p>
29
<ul><li>Простенькая программа сможет только распознать, что это файл с расширением .jpg - то есть изображение.</li>
29
<ul><li>Простенькая программа сможет только распознать, что это файл с расширением .jpg - то есть изображение.</li>
30
<li>Программа посложнее откроет файл и поймёт, что он состоит из набора пикселей разного цвета. Она сможет вывести изображение на экран и, возможно, даже отредактировать: изменит цвет части пикселей на другой, обрежет картинку и так далее.</li>
30
<li>Программа посложнее откроет файл и поймёт, что он состоит из набора пикселей разного цвета. Она сможет вывести изображение на экран и, возможно, даже отредактировать: изменит цвет части пикселей на другой, обрежет картинку и так далее.</li>
31
<li>Если программа работает с помощью нейронных сетей, то она проанализирует изображение и извлечёт из него дополнительную информацию, помимо технической: определит, где на картинке очки, руки, таблетки, лица, найдёт похожие изображения, узнает, из какого фильма кадр и какие актёры в нём играют. Это и есть компьютерное зрение. Набор извлечённой информации будет зависеть от того, чему программу учили.</li>
31
<li>Если программа работает с помощью нейронных сетей, то она проанализирует изображение и извлечёт из него дополнительную информацию, помимо технической: определит, где на картинке очки, руки, таблетки, лица, найдёт похожие изображения, узнает, из какого фильма кадр и какие актёры в нём играют. Это и есть компьютерное зрение. Набор извлечённой информации будет зависеть от того, чему программу учили.</li>
32
</ul><p>Чтобы программа умела смотреть на изображение не как на набор пикселей, а как на набор известных ей объектов, используют<strong>машинное обучение.</strong></p>
32
</ul><p>Чтобы программа умела смотреть на изображение не как на набор пикселей, а как на набор известных ей объектов, используют<strong>машинное обучение.</strong></p>
33
<p>Помимо компьютерного зрения, есть также<strong>машинное зрение</strong>. По сути, это то же компьютерное зрение, но применяется оно для решения конкретной прикладной задачи. Например, на производстве ставят камеру, которая следит за качеством продукции на конвейере. Если такая камера увидит брак, то она предупредит об этом человека-оператора - и это единственная её задача. В этом случае компьютерное зрение можно назвать машинным зрением.</p>
33
<p>Помимо компьютерного зрения, есть также<strong>машинное зрение</strong>. По сути, это то же компьютерное зрение, но применяется оно для решения конкретной прикладной задачи. Например, на производстве ставят камеру, которая следит за качеством продукции на конвейере. Если такая камера увидит брак, то она предупредит об этом человека-оператора - и это единственная её задача. В этом случае компьютерное зрение можно назвать машинным зрением.</p>
34
<p><strong>OpenCV (Open Source Computer Vision Library)</strong>- это библиотека с открытым исходным кодом для работы с компьютерным зрением. Изначально она была написана на C++, но адаптирована для использования на Python, С, Java и MATLAB.</p>
34
<p><strong>OpenCV (Open Source Computer Vision Library)</strong>- это библиотека с открытым исходным кодом для работы с компьютерным зрением. Изначально она была написана на C++, но адаптирована для использования на Python, С, Java и MATLAB.</p>
35
<p>В OpenCV есть встроенные алгоритмы компьютерного зрения на основе машинного обучения в виде отдельных модулей с разной функциональностью. Вот некоторые из них:</p>
35
<p>В OpenCV есть встроенные алгоритмы компьютерного зрения на основе машинного обучения в виде отдельных модулей с разной функциональностью. Вот некоторые из них:</p>
36
<ul><li><strong>Core Functionality</strong>(основная функциональность) - определяет основные структуры данных и функции библиотеки, которые используются в других модулях.</li>
36
<ul><li><strong>Core Functionality</strong>(основная функциональность) - определяет основные структуры данных и функции библиотеки, которые используются в других модулях.</li>
37
<li><strong>Image Processing</strong>(обработка изображений) - позволяет работать со статичными изображениями: простыми картинками в форматах PNG, JPG и других.</li>
37
<li><strong>Image Processing</strong>(обработка изображений) - позволяет работать со статичными изображениями: простыми картинками в форматах PNG, JPG и других.</li>
38
<li><strong>Video Analysis</strong>(анализ видео) - используется для отслеживания движений объектов и работы с фоном.</li>
38
<li><strong>Video Analysis</strong>(анализ видео) - используется для отслеживания движений объектов и работы с фоном.</li>
39
<li><strong>Camera Calibration and 3D Reconstruction</strong>(калибровка камеры и 3D-реконструкция)<strong></strong>- работает с геометрией объектов, позволяя создавать их 3D-модели на основе нескольких изображений или видео.</li>
39
<li><strong>Camera Calibration and 3D Reconstruction</strong>(калибровка камеры и 3D-реконструкция)<strong></strong>- работает с геометрией объектов, позволяя создавать их 3D-модели на основе нескольких изображений или видео.</li>
40
<li><strong>2D Features Framework</strong>(фреймворк двумерных особенностей) - определяет фрагменты изображения, которые отличаются от других, запоминая их контуры, и может находить похожие среди них.</li>
40
<li><strong>2D Features Framework</strong>(фреймворк двумерных особенностей) - определяет фрагменты изображения, которые отличаются от других, запоминая их контуры, и может находить похожие среди них.</li>
41
<li><strong>Object Detection</strong>(обнаружение объектов) - находит объекты, например лица, автомобили, птиц и другое.</li>
41
<li><strong>Object Detection</strong>(обнаружение объектов) - находит объекты, например лица, автомобили, птиц и другое.</li>
42
<li><strong>High-level GUI</strong>(высокоуровневый графический интерфейс) - позволяет рисовать графические интерфейсы для выполнения простых операций.</li>
42
<li><strong>High-level GUI</strong>(высокоуровневый графический интерфейс) - позволяет рисовать графические интерфейсы для выполнения простых операций.</li>
43
<li><strong>Video I/O</strong>(ввод и вывод видео) - позволяет считывать и обрабатывать видеофайлы.</li>
43
<li><strong>Video I/O</strong>(ввод и вывод видео) - позволяет считывать и обрабатывать видеофайлы.</li>
44
</ul><p>Это только часть модулей OpenCV. Подробнее о них и о других возможностях библиотеки можно прочитать в<a>документации</a>.</p>
44
</ul><p>Это только часть модулей OpenCV. Подробнее о них и о других возможностях библиотеки можно прочитать в<a>документации</a>.</p>
45
<p>Компьютерное зрение уже повсюду в нашей жизни: роботы-пылесосы и автомобили объезжают препятствия, а соцсети находят фотографии с вами и спрашивают, вы ли это.</p>
45
<p>Компьютерное зрение уже повсюду в нашей жизни: роботы-пылесосы и автомобили объезжают препятствия, а соцсети находят фотографии с вами и спрашивают, вы ли это.</p>
46
<p>Компьютерное зрение используют для решения разных задач.</p>
46
<p>Компьютерное зрение используют для решения разных задач.</p>
47
<p><strong>Распознавать текст.</strong>Например, чтобы перевести этикетку, можно включить на телефоне приложение-переводчик и навести его на текст. Приложение распознает его и переведёт на нужный язык.</p>
47
<p><strong>Распознавать текст.</strong>Например, чтобы перевести этикетку, можно включить на телефоне приложение-переводчик и навести его на текст. Приложение распознает его и переведёт на нужный язык.</p>
48
<p><strong>Искать по изображениям.</strong>Можно сфотографировать незнакомый цветок и узнать его название, загрузив фотографию в поисковик Google или "Яндекс".</p>
48
<p><strong>Искать по изображениям.</strong>Можно сфотографировать незнакомый цветок и узнать его название, загрузив фотографию в поисковик Google или "Яндекс".</p>
49
<p><strong>Модерировать контент.</strong>Многие форумы и соцсети анализируют контент и автоматически удаляют его, если он нарушает правила платформы.</p>
49
<p><strong>Модерировать контент.</strong>Многие форумы и соцсети анализируют контент и автоматически удаляют его, если он нарушает правила платформы.</p>
50
<p><strong>Использовать биометрию.</strong>Чтобы вы могли разблокировать телефон или войти в сервис по отпечатку пальца или лицу, ваши данные обрабатываются алгоритмами компьютерного зрения.</p>
50
<p><strong>Использовать биометрию.</strong>Чтобы вы могли разблокировать телефон или войти в сервис по отпечатку пальца или лицу, ваши данные обрабатываются алгоритмами компьютерного зрения.</p>
51
<p><strong>Создавать 3D-модели.</strong>Компьютерное зрение позволяет на основе нескольких фотографий или видео создать 3D-модель объекта или пространства. Это используется для восстановления облика объектов и ландшафта, а в робототехнике - чтобы робот мог ориентироваться в помещениях.</p>
51
<p><strong>Создавать 3D-модели.</strong>Компьютерное зрение позволяет на основе нескольких фотографий или видео создать 3D-модель объекта или пространства. Это используется для восстановления облика объектов и ландшафта, а в робототехнике - чтобы робот мог ориентироваться в помещениях.</p>
52
<p><strong>Развивать сельское хозяйство.</strong>С помощью компьютерного зрения можно считать поголовье скота и следить за посевами: оценивать их состояние, обнаруживать вредителей и болезни до того, как их заметил бы человек.</p>
52
<p><strong>Развивать сельское хозяйство.</strong>С помощью компьютерного зрения можно считать поголовье скота и следить за посевами: оценивать их состояние, обнаруживать вредителей и болезни до того, как их заметил бы человек.</p>
53
<p><strong>Управлять производством.</strong>Вместо того чтобы полагаться в выполнении рутинных задач на людей, компьютерное зрение может анализировать продукцию и процессы самостоятельно. Например, можно установить камеру, которая будет прямо на конвейере выявлять бракованную продукцию. В отличие от человека, такая система не устанет и не отвлечётся.</p>
53
<p><strong>Управлять производством.</strong>Вместо того чтобы полагаться в выполнении рутинных задач на людей, компьютерное зрение может анализировать продукцию и процессы самостоятельно. Например, можно установить камеру, которая будет прямо на конвейере выявлять бракованную продукцию. В отличие от человека, такая система не устанет и не отвлечётся.</p>
54
<p>Для создания систем с компьютерным зрением подходят разные инструменты. Один из самых популярных - OpenCV. Его используют Google, Yahoo, Microsoft, Intel, IBM, Sony, Honda, Toyota и другие технологические компании для решения разнообразных задач.</p>
54
<p>Для создания систем с компьютерным зрением подходят разные инструменты. Один из самых популярных - OpenCV. Его используют Google, Yahoo, Microsoft, Intel, IBM, Sony, Honda, Toyota и другие технологические компании для решения разнообразных задач.</p>
55
<p>Например, с помощью OpenCV в Китае следят за состоянием оборудования в шахтах, а в Японии распознают лица людей. Написать программу, распознающую лица, вы можете и сами. О том, как сделать это,<a>рассказываем ниже</a>.</p>
55
<p>Например, с помощью OpenCV в Китае следят за состоянием оборудования в шахтах, а в Японии распознают лица людей. Написать программу, распознающую лица, вы можете и сами. О том, как сделать это,<a>рассказываем ниже</a>.</p>
56
<p>Библиотека OpenCV бесплатна и доступна для использования в личных, образовательных и коммерческих целях. Рассмотрим её базовые функции на примере Python и в итоге напишем скрипт, распознающий лица людей.</p>
56
<p>Библиотека OpenCV бесплатна и доступна для использования в личных, образовательных и коммерческих целях. Рассмотрим её базовые функции на примере Python и в итоге напишем скрипт, распознающий лица людей.</p>
57
<p>Чтобы запустить OpenCV, у вас должен быть установлен поддерживаемый ею язык программирования. В нашем случае это Python. Если у вас он ещё не установлен, можете воспользоваться<a>нашим руководством</a>.</p>
57
<p>Чтобы запустить OpenCV, у вас должен быть установлен поддерживаемый ею язык программирования. В нашем случае это Python. Если у вас он ещё не установлен, можете воспользоваться<a>нашим руководством</a>.</p>
58
<p>Скачать библиотеку можно с помощью инструментов вашей IDE или с помощью командной строки:</p>
58
<p>Скачать библиотеку можно с помощью инструментов вашей IDE или с помощью командной строки:</p>
59
# Windows pip install opencv-python # macOS brew install opencv3 --with-contrib --with-python3 # Linux sudo apt-get install libopencv-dev python-opencv<p>Теперь можно импортировать модуль и приступать к работе:</p>
59
# Windows pip install opencv-python # macOS brew install opencv3 --with-contrib --with-python3 # Linux sudo apt-get install libopencv-dev python-opencv<p>Теперь можно импортировать модуль и приступать к работе:</p>
60
import cv2<p>Перед тем как переходить к практике, остановимся на том, как OpenCV воспринимает изображения. Библиотека работает с ними как с<a>NumPy-массивами</a>.</p>
60
import cv2<p>Перед тем как переходить к практике, остановимся на том, как OpenCV воспринимает изображения. Библиотека работает с ними как с<a>NumPy-массивами</a>.</p>
61
<p><strong>Если изображение в оттенках серого</strong>, то массив этот двумерный. Каждый пиксель в изображении представлен в виде числа 0 до 255, где 0 - чёрный, 255 - белый, а всё остальное - оттенки серого между ними.</p>
61
<p><strong>Если изображение в оттенках серого</strong>, то массив этот двумерный. Каждый пиксель в изображении представлен в виде числа 0 до 255, где 0 - чёрный, 255 - белый, а всё остальное - оттенки серого между ними.</p>
62
<p>Каждая пиксельная строка объединена в одномерный массив. Например, [255, 255, 77, 77, 77, 255, 255]. Это строка из семи пикселей: двух белых, трёх серых и ещё двух белых.</p>
62
<p>Каждая пиксельная строка объединена в одномерный массив. Например, [255, 255, 77, 77, 77, 255, 255]. Это строка из семи пикселей: двух белых, трёх серых и ещё двух белых.</p>
63
<p>Каждая такая пиксельная строка объединена в массив второго уровня. Например:</p>
63
<p>Каждая такая пиксельная строка объединена в массив второго уровня. Например:</p>
64
[[255, 255, 255, 77, 255, 255, 255], [255, 255, 77, 77, 77, 255, 255], [255, 77, 77, 255, 77, 77, 255], [255, 255, 77, 77, 77, 255, 255] [255, 255, 255, 77, 255, 255, 255]]<p>В итоге получается вот такое изображение, только в 100 раз меньше:</p>
64
[[255, 255, 255, 77, 255, 255, 255], [255, 255, 77, 77, 77, 255, 255], [255, 77, 77, 255, 77, 77, 255], [255, 255, 77, 77, 77, 255, 255] [255, 255, 255, 77, 255, 255, 255]]<p>В итоге получается вот такое изображение, только в 100 раз меньше:</p>
65
<em>Изображение: Skillbox Media</em><p><strong>Если изображение цветное</strong>, то потребуется трёхмерный массив. Цвет каждого пикселя описывает не одно, а сразу три числа от 0 до 255 - в соответствии с <a>моделью RGB</a>. Только красный и синий цвет переставлены местами, так что первое число отвечает за синий цвет, второе - за зелёный, третье - за красный: получается BGR.</p>
65
<em>Изображение: Skillbox Media</em><p><strong>Если изображение цветное</strong>, то потребуется трёхмерный массив. Цвет каждого пикселя описывает не одно, а сразу три числа от 0 до 255 - в соответствии с <a>моделью RGB</a>. Только красный и синий цвет переставлены местами, так что первое число отвечает за синий цвет, второе - за зелёный, третье - за красный: получается BGR.</p>
66
<p>Вот примеры пикселей разного цвета на языке OpenCV:</p>
66
<p>Вот примеры пикселей разного цвета на языке OpenCV:</p>
67
<ul><li>[0, 0, 0] - чёрный.</li>
67
<ul><li>[0, 0, 0] - чёрный.</li>
68
<li>[255, 255, 255] - белый.</li>
68
<li>[255, 255, 255] - белый.</li>
69
<li>[255, 0, 0] - синий.</li>
69
<li>[255, 0, 0] - синий.</li>
70
<li>[0, 255, 0] - зелёный.</li>
70
<li>[0, 255, 0] - зелёный.</li>
71
<li>[0, 0, 255] - красный.</li>
71
<li>[0, 0, 255] - красный.</li>
72
<li>[0, 255, 255] - жёлтый.</li>
72
<li>[0, 255, 255] - жёлтый.</li>
73
<li>[203, 192, 255] - розовый.</li>
73
<li>[203, 192, 255] - розовый.</li>
74
</ul><p>Таблицу распространённых цветов в RGB можно посмотреть<a>здесь</a>. Только помните, что в OpenCV первый и третий цвета переставлены местами.</p>
74
</ul><p>Таблицу распространённых цветов в RGB можно посмотреть<a>здесь</a>. Только помните, что в OpenCV первый и третий цвета переставлены местами.</p>
75
<p>Как и в случае с изображениями в оттенках серого, массив следующего уровня объединяет строки пикселей, а верхнеуровневый массив - всё изображение.</p>
75
<p>Как и в случае с изображениями в оттенках серого, массив следующего уровня объединяет строки пикселей, а верхнеуровневый массив - всё изображение.</p>
76
<p>Вот так в OpenCV будет выглядеть массив для изображения из девяти цветных пикселей:</p>
76
<p>Вот так в OpenCV будет выглядеть массив для изображения из девяти цветных пикселей:</p>
77
[[[0, 0, 255], [0, 255, 255], [0, 255, 0]], [[0, 0, 0], [203, 192, 255], [255, 255, 255]], [[164, 73, 163], [255, 0, 0], [127, 127, 127]]]<p>И само изображение, увеличенное для удобства:</p>
77
[[[0, 0, 255], [0, 255, 255], [0, 255, 0]], [[0, 0, 0], [203, 192, 255], [255, 255, 255]], [[164, 73, 163], [255, 0, 0], [127, 127, 127]]]<p>И само изображение, увеличенное для удобства:</p>
78
<em>Изображение: Skillbox Media</em><p>Скачаем любое изображение (желательно яркое и контрастное) и откроем его в нашем коде.</p>
78
<em>Изображение: Skillbox Media</em><p>Скачаем любое изображение (желательно яркое и контрастное) и откроем его в нашем коде.</p>
79
<p>Например, вот такое изображение:</p>
79
<p>Например, вот такое изображение:</p>
80
<em>Изображение: OpenCV</em><p>Прочитайте изображение и откройте его в отдельном окне:</p>
80
<em>Изображение: OpenCV</em><p>Прочитайте изображение и откройте его в отдельном окне:</p>
81
image = cv2.imread('logo.jpg') cv2.imshow('logo', image) cv2.waitKey(0)<ul><li>cv2.imread - "читает" изображение и возвращает NumPy-массив, с которым библиотека может работать. В качестве аргумента получает полный или относительный путь к изображению.</li>
81
image = cv2.imread('logo.jpg') cv2.imshow('logo', image) cv2.waitKey(0)<ul><li>cv2.imread - "читает" изображение и возвращает NumPy-массив, с которым библиотека может работать. В качестве аргумента получает полный или относительный путь к изображению.</li>
82
<li>cv2.imshow - открывает изображение в отдельном окне операционной системы. Первым аргументом получает название окна, вторым - NumPy-массив, в нашем случае он хранится в переменной image.</li>
82
<li>cv2.imshow - открывает изображение в отдельном окне операционной системы. Первым аргументом получает название окна, вторым - NumPy-массив, в нашем случае он хранится в переменной image.</li>
83
<li>cv2.waitKey - если не указать эту функцию, то открытое окно тут же закроется. В качестве аргумента получает кнопку, которую нужно нажать, чтобы закрыть окно. Если указать 0, то окно закроется при нажатии любой кнопки.</li>
83
<li>cv2.waitKey - если не указать эту функцию, то открытое окно тут же закроется. В качестве аргумента получает кнопку, которую нужно нажать, чтобы закрыть окно. Если указать 0, то окно закроется при нажатии любой кнопки.</li>
84
</ul><p>Можно передать функции cv2.imread необязательный второй аргумент и выбрать режим отображения:</p>
84
</ul><p>Можно передать функции cv2.imread необязательный второй аргумент и выбрать режим отображения:</p>
85
<ul><li>cv2.IMREAD_COLOR (по умолчанию) - цветное отображение в формате RGB.</li>
85
<ul><li>cv2.IMREAD_COLOR (по умолчанию) - цветное отображение в формате RGB.</li>
86
<li>cv2.IMREAD_GRAYSCALE - отображение в оттенках серого.</li>
86
<li>cv2.IMREAD_GRAYSCALE - отображение в оттенках серого.</li>
87
</ul><p>Таким образом, функцию cv2.imread можно использовать, чтобы обесцветить цветное изображение:</p>
87
</ul><p>Таким образом, функцию cv2.imread можно использовать, чтобы обесцветить цветное изображение:</p>
88
gray_image = cv2.imread('logo.jpg', cv2.IMREAD_GRAYSCALE) cv2.imshow('logo', gray_image) cv2.waitKey(0)<p>Вот что получится:</p>
88
gray_image = cv2.imread('logo.jpg', cv2.IMREAD_GRAYSCALE) cv2.imshow('logo', gray_image) cv2.waitKey(0)<p>Вот что получится:</p>
89
<em>Изображение: Skillbox Media</em><p>Чтобы сохранить новое изображение в отдельный файл, используйте функцию cv2.imwrite:</p>
89
<em>Изображение: Skillbox Media</em><p>Чтобы сохранить новое изображение в отдельный файл, используйте функцию cv2.imwrite:</p>
90
cv2.imwrite('gray_logo.jpg', gray_image)<p>Первым аргументом функция принимает название нового файла с картинкой, вторым - NumPy-массив с данными изображения.</p>
90
cv2.imwrite('gray_logo.jpg', gray_image)<p>Первым аргументом функция принимает название нового файла с картинкой, вторым - NumPy-массив с данными изображения.</p>
91
<p>OpenCV позволяет обращаться к пикселям по их записи в NumPy-массиве. Так мы можем менять изображение.</p>
91
<p>OpenCV позволяет обращаться к пикселям по их записи в NumPy-массиве. Так мы можем менять изображение.</p>
92
<p>Для начала<strong>получим доступ к пикселю</strong>. Для этого обратимся к нему по координатам. Сначала указываем координаты ширины, потом - высоты. Например:</p>
92
<p>Для начала<strong>получим доступ к пикселю</strong>. Для этого обратимся к нему по координатам. Сначала указываем координаты ширины, потом - высоты. Например:</p>
93
blue, green, red = image[10, 350] print(f'RGB-код пикселя: {red}, {green}, {blue}') >>> RGB-код пикселя: 249, 7, 6<p>Теперь<strong>изменим цвет пикселя</strong>. Для этого обратитесь к нему по координатам и сделайте его синим. Помните, что синий и красный переставлены местами:</p>
93
blue, green, red = image[10, 350] print(f'RGB-код пикселя: {red}, {green}, {blue}') >>> RGB-код пикселя: 249, 7, 6<p>Теперь<strong>изменим цвет пикселя</strong>. Для этого обратитесь к нему по координатам и сделайте его синим. Помните, что синий и красный переставлены местами:</p>
94
image[0, 0] = [255, 0, 0]<p>Если открыть изменённое изображение, то в правом верхнем углу вы увидите чёрную точку размером с один пиксель.</p>
94
image[0, 0] = [255, 0, 0]<p>Если открыть изменённое изображение, то в правом верхнем углу вы увидите чёрную точку размером с один пиксель.</p>
95
<p>При ручной замене полезно знать размеры изображения. Для этого воспользуйтесь функцией image.shape:</p>
95
<p>При ручной замене полезно знать размеры изображения. Для этого воспользуйтесь функцией image.shape:</p>
96
<ul><li>image.shape[0] - высота изображения в пикселях.</li>
96
<ul><li>image.shape[0] - высота изображения в пикселях.</li>
97
<li>image.shape[1] - ширина изображения в пикселях.</li>
97
<li>image.shape[1] - ширина изображения в пикселях.</li>
98
</ul><p>Используя циклы, можно изменять цвет сразу множества пикселей. Например, нарисовать для картинки чёрную рамку шириной 10 пикселей.</p>
98
</ul><p>Используя циклы, можно изменять цвет сразу множества пикселей. Например, нарисовать для картинки чёрную рамку шириной 10 пикселей.</p>
99
<p>Внешние циклы перебирают каждый пиксель по горизонтали (первый) и вертикали (второй), а внутренние циклы идут от краёв к центру изображения и на каждом витке перекрашивают в чёрный по пикселю.</p>
99
<p>Внешние циклы перебирают каждый пиксель по горизонтали (первый) и вертикали (второй), а внутренние циклы идут от краёв к центру изображения и на каждом витке перекрашивают в чёрный по пикселю.</p>
100
import cv2 image = cv2.imread('logo.jpg') # рисуем верхнюю и нижнюю линии width = image.shape[1] for width_coordinate in range(width): for frame_coordinate in range(0, 10): image[frame_coordinate, width_coordinate] = [0, 0, 0] image[-frame_coordinate, width_coordinate] = [0, 0, 0] # рисуем правую и левую линии height = image.shape[0] for height_coordinate in range(height): for frame_coordinate in range(0, 10): image[height_coordinate, frame_coordinate] = [0, 0, 0] image[height_coordinate, -frame_coordinate] = [0, 0, 0] # создаём новое окно с изменённым изображением cv2.imshow('logo', image) cv2.waitKey(0)<p>В итоге получается такое изображение:</p>
100
import cv2 image = cv2.imread('logo.jpg') # рисуем верхнюю и нижнюю линии width = image.shape[1] for width_coordinate in range(width): for frame_coordinate in range(0, 10): image[frame_coordinate, width_coordinate] = [0, 0, 0] image[-frame_coordinate, width_coordinate] = [0, 0, 0] # рисуем правую и левую линии height = image.shape[0] for height_coordinate in range(height): for frame_coordinate in range(0, 10): image[height_coordinate, frame_coordinate] = [0, 0, 0] image[height_coordinate, -frame_coordinate] = [0, 0, 0] # создаём новое окно с изменённым изображением cv2.imshow('logo', image) cv2.waitKey(0)<p>В итоге получается такое изображение:</p>
101
<em>Изображение: Skillbox Media</em><p>Чтобы изменить размер изображения, используйте функцию cv2.resize. Уменьшим нашу картинку в два раза:</p>
101
<em>Изображение: Skillbox Media</em><p>Чтобы изменить размер изображения, используйте функцию cv2.resize. Уменьшим нашу картинку в два раза:</p>
102
reduced_image = cv2.resize(image, (399, 368), cv2.INTER_AREA)<ul><li>image - NumPy-массив изображения, размер которого мы изменяем.</li>
102
reduced_image = cv2.resize(image, (399, 368), cv2.INTER_AREA)<ul><li>image - NumPy-массив изображения, размер которого мы изменяем.</li>
103
<li>(399, 368) - ширина и высота нового изображения.</li>
103
<li>(399, 368) - ширина и высота нового изображения.</li>
104
<li>cv2.INTER_AREA - метод интерполяции, то есть алгоритм, по которому OpenVC выбирает, в какие цвета красить пиксели.</li>
104
<li>cv2.INTER_AREA - метод интерполяции, то есть алгоритм, по которому OpenVC выбирает, в какие цвета красить пиксели.</li>
105
</ul><p>Есть несколько методов интерполяции, но в большинстве случаев достаточно двух из них:</p>
105
</ul><p>Есть несколько методов интерполяции, но в большинстве случаев достаточно двух из них:</p>
106
<ul><li>cv2.INTER_LINEAR - для увеличения изображения. Используется по умолчанию, если не указано иное.</li>
106
<ul><li>cv2.INTER_LINEAR - для увеличения изображения. Используется по умолчанию, если не указано иное.</li>
107
<li>cv2.INTER_AREA - для уменьшения картинки.</li>
107
<li>cv2.INTER_AREA - для уменьшения картинки.</li>
108
</ul><p>Чтобы сохранять пропорции изображения и каждый раз не высчитывать их вручную, используйте данные, полученные с помощью метода shape:</p>
108
</ul><p>Чтобы сохранять пропорции изображения и каждый раз не высчитывать их вручную, используйте данные, полученные с помощью метода shape:</p>
109
height = image.shape[0] width = image.shape[1] reduced_image = cv2.resize(image, (int(width/2), int(height/2)), cv2.INTER_AREA)<p>В обоих случаях результат одинаковый:</p>
109
height = image.shape[0] width = image.shape[1] reduced_image = cv2.resize(image, (int(width/2), int(height/2)), cv2.INTER_AREA)<p>В обоих случаях результат одинаковый:</p>
110
<em>Изображение: Skillbox Media</em><p>Чтобы обрезать изображение, укажите диапазоны координат, в которых хотите оставить изображение, - сначала высоту, потом ширину. Например:</p>
110
<em>Изображение: Skillbox Media</em><p>Чтобы обрезать изображение, укажите диапазоны координат, в которых хотите оставить изображение, - сначала высоту, потом ширину. Например:</p>
111
cropped_image = image[0:368, 200:600]<em>Изображение: Skillbox Media</em><p>Чтобы повернуть картинку, используйте сразу две функции:</p>
111
cropped_image = image[0:368, 200:600]<em>Изображение: Skillbox Media</em><p>Чтобы повернуть картинку, используйте сразу две функции:</p>
112
matrix = cv2.getRotationMatrix2D((399, 368), 60, 0.8) rotated_image = cv2.warpAffine(image, matrix, (image.shape[1], image.shape[0]))<p>Функция cv2.getRotationMatrix2D задаёт матрицу, по которой будет повёрнуто изображение. Она получает следующие аргументы:</p>
112
matrix = cv2.getRotationMatrix2D((399, 368), 60, 0.8) rotated_image = cv2.warpAffine(image, matrix, (image.shape[1], image.shape[0]))<p>Функция cv2.getRotationMatrix2D задаёт матрицу, по которой будет повёрнуто изображение. Она получает следующие аргументы:</p>
113
<ul><li>(399, 368) - координаты точки, вокруг которой происходит поворот.</li>
113
<ul><li>(399, 368) - координаты точки, вокруг которой происходит поворот.</li>
114
<li>60 - угол поворота в градусах.</li>
114
<li>60 - угол поворота в градусах.</li>
115
<li>0.8 - коэффициент масштабирования. В нашем случае мы уменьшаем изображение, чтобы части логотипа не вышли за край.</li>
115
<li>0.8 - коэффициент масштабирования. В нашем случае мы уменьшаем изображение, чтобы части логотипа не вышли за край.</li>
116
</ul><p>Функция cv2.warpAffine непосредственно поворачивает изображение. Она получает следующие аргументы:</p>
116
</ul><p>Функция cv2.warpAffine непосредственно поворачивает изображение. Она получает следующие аргументы:</p>
117
<ul><li>image - само изображение.</li>
117
<ul><li>image - само изображение.</li>
118
<li>matrix - матрица, созданная функцией cv2.getRotationMatrix2D.</li>
118
<li>matrix - матрица, созданная функцией cv2.getRotationMatrix2D.</li>
119
<li>(image.shape[1], image.shape[0]) - размеры итогового изображения. В нашем случае мы оставляем те же, что были.</li>
119
<li>(image.shape[1], image.shape[0]) - размеры итогового изображения. В нашем случае мы оставляем те же, что были.</li>
120
</ul><em>Изображение: Skillbox Media</em><p>Напишем пару простых скриптов для работы с изображениями, используя библиотеку OpenCV для Python.</p>
120
</ul><em>Изображение: Skillbox Media</em><p>Напишем пару простых скриптов для работы с изображениями, используя библиотеку OpenCV для Python.</p>
121
<p>OpenCV умеет работать с нажатиями на открытое в окне изображение. Сделаем так, чтобы при нажатии на картинку программа выводила в терминал координаты точки и её цветовой код в формате BGR.</p>
121
<p>OpenCV умеет работать с нажатиями на открытое в окне изображение. Сделаем так, чтобы при нажатии на картинку программа выводила в терминал координаты точки и её цветовой код в формате BGR.</p>
122
<p>Дополнительно будем рисовать данные о точке, на которую нажали, прямо на изображении. Если нажали левую кнопку мыши - координаты, если правую - BGR-код.</p>
122
<p>Дополнительно будем рисовать данные о точке, на которую нажали, прямо на изображении. Если нажали левую кнопку мыши - координаты, если правую - BGR-код.</p>
123
<p>Напишите функцию click_event, которая будет реагировать на нажатие на картинку:</p>
123
<p>Напишите функцию click_event, которая будет реагировать на нажатие на картинку:</p>
124
def click_event(event, x, y, flags, params): # если нажата левая кнопка мыши if event == cv2.EVENT_LBUTTONDOWN: pass # заглушка вместо будущего кода # если нажата правая кнопка мыши if event == cv2.EVENT_RBUTTONDOWN: pass # заглушка вместо будущего кода<p>Функция click_event принимает пять аргументов:</p>
124
def click_event(event, x, y, flags, params): # если нажата левая кнопка мыши if event == cv2.EVENT_LBUTTONDOWN: pass # заглушка вместо будущего кода # если нажата правая кнопка мыши if event == cv2.EVENT_RBUTTONDOWN: pass # заглушка вместо будущего кода<p>Функция click_event принимает пять аргументов:</p>
125
<ul><li>event - произошедшее событие (в нашем случае нажатие кнопки мыши).</li>
125
<ul><li>event - произошедшее событие (в нашем случае нажатие кнопки мыши).</li>
126
<li>x и y - координаты точки, на которую нажали.</li>
126
<li>x и y - координаты точки, на которую нажали.</li>
127
<li>flags и params - служебные аргументы, нужные методу, с помощью которого мы будем вызывать эту функцию.</li>
127
<li>flags и params - служебные аргументы, нужные методу, с помощью которого мы будем вызывать эту функцию.</li>
128
</ul><p>При нажатии любой кнопки мыши мы хотим выводить в терминал координаты и BGR-код точки. Пропишите это:</p>
128
</ul><p>При нажатии любой кнопки мыши мы хотим выводить в терминал координаты и BGR-код точки. Пропишите это:</p>
129
def click_event(event, x, y, flags, params): # если нажата левая кнопка мыши if event == cv2.EVENT_LBUTTONDOWN: # узнаём BGR-код точки и сохраняем в переменные b = img[y, x, 0] g = img[y, x, 1] r = img[y, x, 2] # выводим координаты и BGR-код точки в терминал print(f'Координаты точки: {x}, {y}') print(f'BGR-код точки: {b}, {g}, {r}\n') # если нажата правая кнопка мыши if event == cv2.EVENT_RBUTTONDOWN: # узнаём BGR-код точки и сохраняем в переменные b = img[y, x, 0] g = img[y, x, 1] r = img[y, x, 2] # выводим координаты и BGR-код точки в терминал print(f'Координаты точки: {x}, {y}') print(f'BGR-код точки: {b}, {g}, {r}\n')<p>Дополните первое условие кодом, который будет рисовать координаты точки прямо на изображении, если нажата левая кнопка мыши:</p>
129
def click_event(event, x, y, flags, params): # если нажата левая кнопка мыши if event == cv2.EVENT_LBUTTONDOWN: # узнаём BGR-код точки и сохраняем в переменные b = img[y, x, 0] g = img[y, x, 1] r = img[y, x, 2] # выводим координаты и BGR-код точки в терминал print(f'Координаты точки: {x}, {y}') print(f'BGR-код точки: {b}, {g}, {r}\n') # если нажата правая кнопка мыши if event == cv2.EVENT_RBUTTONDOWN: # узнаём BGR-код точки и сохраняем в переменные b = img[y, x, 0] g = img[y, x, 1] r = img[y, x, 2] # выводим координаты и BGR-код точки в терминал print(f'Координаты точки: {x}, {y}') print(f'BGR-код точки: {b}, {g}, {r}\n')<p>Дополните первое условие кодом, который будет рисовать координаты точки прямо на изображении, если нажата левая кнопка мыши:</p>
130
# устанавливаем шрифт, которым будем писать надпись font = cv2.FONT_HERSHEY_SIMPLEX # пишем надпись cv2.putText(img, f'{x}, {y}', (x, y), font, 1, (0, 0, 0), 2) # отображаем изменённое изображение cv2.imshow('image', img)<p>Функция cv2.putText принимает следующие аргументы:</p>
130
# устанавливаем шрифт, которым будем писать надпись font = cv2.FONT_HERSHEY_SIMPLEX # пишем надпись cv2.putText(img, f'{x}, {y}', (x, y), font, 1, (0, 0, 0), 2) # отображаем изменённое изображение cv2.imshow('image', img)<p>Функция cv2.putText принимает следующие аргументы:</p>
131
<ul><li>img - изображение, на которое добавляется надпись.</li>
131
<ul><li>img - изображение, на которое добавляется надпись.</li>
132
<li>f'{x}, {y}' - надпись, которая добавляется на изображение.</li>
132
<li>f'{x}, {y}' - надпись, которая добавляется на изображение.</li>
133
<li>(x, y) - координаты точки, из которой выходит надпись.</li>
133
<li>(x, y) - координаты точки, из которой выходит надпись.</li>
134
<li>font - шрифт надписи.</li>
134
<li>font - шрифт надписи.</li>
135
<li>1 - масштабирование размера текста.</li>
135
<li>1 - масштабирование размера текста.</li>
136
<li>(0, 0, 0) - цвет текста.</li>
136
<li>(0, 0, 0) - цвет текста.</li>
137
<li>2 - толщина линий.</li>
137
<li>2 - толщина линий.</li>
138
</ul><p>По аналогии дополните второе условие кодом, который будет рисовать на изображении BGR-код, если нажата правая кнопка мыши:</p>
138
</ul><p>По аналогии дополните второе условие кодом, который будет рисовать на изображении BGR-код, если нажата правая кнопка мыши:</p>
139
# устанавливаем шрифт, которым будем писать надпись font = cv2.FONT_HERSHEY_SIMPLEX # пишем надпись cv2.putText(img, f'{b}, {g}, {r}', (x, y), font, 1, (0, 0, 0), 2) # отображаем изменённое изображение cv2.imshow('image', img)<p>Наша функция готова. Остаётся только передать изображение и воспользоваться встроенной OpenCV-функцией cv2.setMouseCallback:</p>
139
# устанавливаем шрифт, которым будем писать надпись font = cv2.FONT_HERSHEY_SIMPLEX # пишем надпись cv2.putText(img, f'{b}, {g}, {r}', (x, y), font, 1, (0, 0, 0), 2) # отображаем изменённое изображение cv2.imshow('image', img)<p>Наша функция готова. Остаётся только передать изображение и воспользоваться встроенной OpenCV-функцией cv2.setMouseCallback:</p>
140
if __name__ == "__main__": img = cv2.imread('logo.jpg', 1) cv2.imshow('image', img) # устанавливаем реакцию на действия мыши и вызываем функцию click_event cv2.setMouseCallback('image', click_event) cv2.waitKey(0)<p>Итоговый код:</p>
140
if __name__ == "__main__": img = cv2.imread('logo.jpg', 1) cv2.imshow('image', img) # устанавливаем реакцию на действия мыши и вызываем функцию click_event cv2.setMouseCallback('image', click_event) cv2.waitKey(0)<p>Итоговый код:</p>
141
-
import cv2 # функция реакции на нажатие левой или правой кнопки мыши def click_event(event, x, y, flags, params): # если нажата левая кнопка мыши if event == cv2.EVENT_LBUTTONDOWN: # выводим координаты и BGR-код точки в терминал print(f'Координаты точки: {x}, {y}') b = img[y, x, 0] g = img[y, x, 1] r = img[y, x, 2] print(f'BGR-код точки: {b}, {g}, {r}\n') # рисуем координаты точки на изображении font = cv2.FONT_HERSHEY_SIMPLEX cv2.putText(img, f'{x}, {y}', (x, y), font, 1, (0, 0, 0), 2) cv2.imshow('image', img) # если нажата правая кнопка мыши if event == cv2.EVENT_RBUTTONDOWN: # узнаём BGR-код точки и сохраняем в переменные b = img[y, x, 0] g = img[y, x, 1] r = img[y, x, 2] # выводим координаты и BGR-код точки в терминал print(f'Координаты точки: {x}, {y}') print(f'BGR-код точки: {b}, {g}, {r}\n') # рисуем BGR-код точки на изображении font = cv2.FONT_HERSHEY_SIMPLEX cv2.putText(img, f'{b}, {g}, {r}', (x, y), font, 1, (0, 0, 0), 2) cv2.imshow('image', img) # основной сценарий if __name__ == "__main__": img = cv2.imread('logo.jpg', 1) cv2.imshow('image', img) # устанавливаем реакцию на действия мыши и вызываем функцию click_event cv2.setMouseCallback('image', click_event) cv2.waitKey(0)<p>Опробуйте код. Откройте изображение, нажмите правой кнопкой мыши на каждую из фигур и левой - на пространство между ними. Получится вот такой результа��:</p>
141
+
import cv2 # функция реакции на нажатие левой или правой кнопки мыши def click_event(event, x, y, flags, params): # если нажата левая кнопка мыши if event == cv2.EVENT_LBUTTONDOWN: # выводим координаты и BGR-код точки в терминал print(f'Координаты точки: {x}, {y}') b = img[y, x, 0] g = img[y, x, 1] r = img[y, x, 2] print(f'BGR-код точки: {b}, {g}, {r}\n') # рисуем координаты точки на изображении font = cv2.FONT_HERSHEY_SIMPLEX cv2.putText(img, f'{x}, {y}', (x, y), font, 1, (0, 0, 0), 2) cv2.imshow('image', img) # если нажата правая кнопка мыши if event == cv2.EVENT_RBUTTONDOWN: # узнаём BGR-код точки и сохраняем в переменные b = img[y, x, 0] g = img[y, x, 1] r = img[y, x, 2] # выводим координаты и BGR-код точки в терминал print(f'Координаты точки: {x}, {y}') print(f'BGR-код точки: {b}, {g}, {r}\n') # рисуем BGR-код точки на изображении font = cv2.FONT_HERSHEY_SIMPLEX cv2.putText(img, f'{b}, {g}, {r}', (x, y), font, 1, (0, 0, 0), 2) cv2.imshow('image', img) # основной сценарий if __name__ == "__main__": img = cv2.imread('logo.jpg', 1) cv2.imshow('image', img) # устанавливаем реакцию на действия мыши и вызываем функцию click_event cv2.setMouseCallback('image', click_event) cv2.waitKey(0)<p>Опробуйте код. Откройте изображение, нажмите правой кнопкой мыши на каждую из фигур и левой - на пространство между ними. Получится вот такой результат:</p>
142
<em>Изображение: Skillbox Media</em><p>При этом в терминале выводится следующий текст:</p>
142
<em>Изображение: Skillbox Media</em><p>При этом в терминале выводится следующий текст:</p>
143
>>> Координаты точки: 383, 68 >>> BGR-код точки: 1, 1, 255 >>> Координаты точки: 68, 494 >>> BGR-код точки: 1, 255, 1 >>> Координаты точки: 579, 665 >>> BGR-код точки: 255, 1, 1 >>> Координаты точки: 381, 393 >>> BGR-код точки: 255, 255, 255<p>В OpenCV есть и более "умные" инструменты, использующие машинное обучение. Один из них -<a>модель Haar</a>, которая умеет распознавать лица.</p>
143
>>> Координаты точки: 383, 68 >>> BGR-код точки: 1, 1, 255 >>> Координаты точки: 68, 494 >>> BGR-код точки: 1, 255, 1 >>> Координаты точки: 579, 665 >>> BGR-код точки: 255, 1, 1 >>> Координаты точки: 381, 393 >>> BGR-код точки: 255, 255, 255<p>В OpenCV есть и более "умные" инструменты, использующие машинное обучение. Один из них -<a>модель Haar</a>, которая умеет распознавать лица.</p>
144
<p>Чтобы воспользоваться ей, скачайте<a>файл haarcascade_frontalface_default.xml</a>, выложенный OpenCV на GitHub.</p>
144
<p>Чтобы воспользоваться ей, скачайте<a>файл haarcascade_frontalface_default.xml</a>, выложенный OpenCV на GitHub.</p>
145
<p>Также вам понадобится любое изображение с лицами людей. Мы воспользуемся кадром из "Матрицы", который уже показывали в начале этой статьи.</p>
145
<p>Также вам понадобится любое изображение с лицами людей. Мы воспользуемся кадром из "Матрицы", который уже показывали в начале этой статьи.</p>
146
<em>Кадр: фильм "Матрица" / Warner Bros.</em><p>Сохраните эти файлы в папку с вашим скриптом, и тогда к ним можно будет обращаться по имени.</p>
146
<em>Кадр: фильм "Матрица" / Warner Bros.</em><p>Сохраните эти файлы в папку с вашим скриптом, и тогда к ним можно будет обращаться по имени.</p>
147
<p>Импортируйте OpenCV и создайте по переменной для модели Haar и изображения:</p>
147
<p>Импортируйте OpenCV и создайте по переменной для модели Haar и изображения:</p>
148
import cv2 # создаём переменную с файлом модели face_cascade = cv2.CascadeClassifier('haarcascade_frontalface_default.xml') # читаем изображение image = cv2.imread('matrix.jpg')<p>При работе с распознаванием и сравнением объектов используют обесцвеченные версии изображений. Обесцветим и наше:</p>
148
import cv2 # создаём переменную с файлом модели face_cascade = cv2.CascadeClassifier('haarcascade_frontalface_default.xml') # читаем изображение image = cv2.imread('matrix.jpg')<p>При работе с распознаванием и сравнением объектов используют обесцвеченные версии изображений. Обесцветим и наше:</p>
149
gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)<p>Чтобы обнаружить на картинке лица, используйте метод detectMultiScale, который применим к модели Haar.</p>
149
gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)<p>Чтобы обнаружить на картинке лица, используйте метод detectMultiScale, который применим к модели Haar.</p>
150
faces = face_cascade.detectMultiScale(gray_image, scaleFactor=1.1, minNeighbors=5)<p>Мы передаём методу следующие аргументы:</p>
150
faces = face_cascade.detectMultiScale(gray_image, scaleFactor=1.1, minNeighbors=5)<p>Мы передаём методу следующие аргументы:</p>
151
<ul><li>gray_image - обесцвеченное изображение;</li>
151
<ul><li>gray_image - обесцвеченное изображение;</li>
152
<li>scaleFactor=1.1 - шаг масштабирования изображения. Дело в том, что в модели хранятся данные о лицах определённого размера. Если лица на изображении больше или меньше, то алгоритм не обнаружит их. Поэтому при анализе размер изображения меняется: чтобы лица на нём в какой-то момент стали того же размера, что и в модели. Чем меньше scaleFactor, тем точнее распознавание, но тем медленнее оно работает;</li>
152
<li>scaleFactor=1.1 - шаг масштабирования изображения. Дело в том, что в модели хранятся данные о лицах определённого размера. Если лица на изображении больше или меньше, то алгоритм не обнаружит их. Поэтому при анализе размер изображения меняется: чтобы лица на нём в какой-то момент стали того же размера, что и в модели. Чем меньше scaleFactor, тем точнее распознавание, но тем медленнее оно работает;</li>
153
<li>minNeighbors=5 - какое минимальное число совпадений с моделью должно быть на изображении, чтобы признать объект лицом. Чем больше этот аргумент, тем меньше лиц алгоритм будет обнаруживать, но вместе с тем уменьшается шанс принять за лицо какой-либо другой объект.</li>
153
<li>minNeighbors=5 - какое минимальное число совпадений с моделью должно быть на изображении, чтобы признать объект лицом. Чем больше этот аргумент, тем меньше лиц алгоритм будет обнаруживать, но вместе с тем уменьшается шанс принять за лицо какой-либо другой объект.</li>
154
</ul><p>Метод detectMultiScale возвращает координаты полученных объектов. Используйте эти координаты и функцию cv2.rectangle, чтобы нарисовать вокруг лиц квадраты:</p>
154
</ul><p>Метод detectMultiScale возвращает координаты полученных объектов. Используйте эти координаты и функцию cv2.rectangle, чтобы нарисовать вокруг лиц квадраты:</p>
155
or (x, y, w, h) in faces: cv2.rectangle(image, (x, y), (x + w, y + h), (0, 0, 255), 2)<p>В переменной faces хранится список из четырёх элементов. Каждый из них - список с данными всех найденных объектов:</p>
155
or (x, y, w, h) in faces: cv2.rectangle(image, (x, y), (x + w, y + h), (0, 0, 255), 2)<p>В переменной faces хранится список из четырёх элементов. Каждый из них - список с данными всех найденных объектов:</p>
156
<ul><li>x - координаты верхнего левого угла объекта по горизонтали.</li>
156
<ul><li>x - координаты верхнего левого угла объекта по горизонтали.</li>
157
<li>y - координаты верхнего левого угла объекта по вертикали.</li>
157
<li>y - координаты верхнего левого угла объекта по вертикали.</li>
158
<li>w - ширина объекта.</li>
158
<li>w - ширина объекта.</li>
159
<li>h - высота объекта.</li>
159
<li>h - высота объекта.</li>
160
</ul><p>Функция cv2.rectangle получает следующие аргументы:</p>
160
</ul><p>Функция cv2.rectangle получает следующие аргументы:</p>
161
<ul><li>image - цветное изображение, на котором мы рисуем квадрат.</li>
161
<ul><li>image - цветное изображение, на котором мы рисуем квадрат.</li>
162
<li>(x, y) - координаты верхнего левого угла квадрата.</li>
162
<li>(x, y) - координаты верхнего левого угла квадрата.</li>
163
<li>(x+w, y+h) - координаты нижнего правого угла квадрата.</li>
163
<li>(x+w, y+h) - координаты нижнего правого угла квадрата.</li>
164
<li>(0, 0, 255) - цвет квадрата в формате BGR.</li>
164
<li>(0, 0, 255) - цвет квадрата в формате BGR.</li>
165
<li>2 - толщина линии квадрата в пикселях.</li>
165
<li>2 - толщина линии квадрата в пикселях.</li>
166
</ul><p>Посмотрим на получившееся изображение:</p>
166
</ul><p>Посмотрим на получившееся изображение:</p>
167
cv2.imshow('found_faces', image) cv2.waitKey(0)<p>Итоговый код:</p>
167
cv2.imshow('found_faces', image) cv2.waitKey(0)<p>Итоговый код:</p>
168
import cv2 # создаём переменную с файлом модели face_cascade = cv2.CascadeClassifier('haarcascade_frontalface_default.xml') # читаем изображение image = cv2.imread('matrix.jpg') # обесцвечиваем изображение gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) # находим лица на обесцвеченном изображении faces = face_cascade.detectMultiScale(gray_image, scaleFactor=1.1, minNeighbors=5) # на цветном изображении рисуем квадраты там, где нашли лица на обесцвеченном for (x, y, w, h) in faces: cv2.rectangle(image, (x, y), (x + w, y + h), (0, 0, 255), 2) # открываем изображение в отдельном окне cv2.imshow('found_faces', image) cv2.waitKey(0)<p>Результат:</p>
168
import cv2 # создаём переменную с файлом модели face_cascade = cv2.CascadeClassifier('haarcascade_frontalface_default.xml') # читаем изображение image = cv2.imread('matrix.jpg') # обесцвечиваем изображение gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) # находим лица на обесцвеченном изображении faces = face_cascade.detectMultiScale(gray_image, scaleFactor=1.1, minNeighbors=5) # на цветном изображении рисуем квадраты там, где нашли лица на обесцвеченном for (x, y, w, h) in faces: cv2.rectangle(image, (x, y), (x + w, y + h), (0, 0, 255), 2) # открываем изображение в отдельном окне cv2.imshow('found_faces', image) cv2.waitKey(0)<p>Результат:</p>
169
Тук-тук, Нео<em>Кадр: фильм "Матрица" / Warner Bros.</em><p>Всё получилось - лица в отражении обведены рамками.</p>
169
Тук-тук, Нео<em>Кадр: фильм "Матрица" / Warner Bros.</em><p>Всё получилось - лица в отражении обведены рамками.</p>
170
<a>Курс с трудоустройством: "Профессия Data scientist + ИИ" Узнать о курсе</a>
170
<a>Курс с трудоустройством: "Профессия Data scientist + ИИ" Узнать о курсе</a>