Долгая дорога начинается с первых шагов, а первый шаг в дополненную реальность и сложные алгоритмы компьютерного зрения это умение загрузить изображение, изменить его размер, цвет и просто вырезать интересный нам фрагмент. Вы удивитесь, как много можно всего достичь, используя самые простые средства.
Весь код, представленный в статье, написан на последней версии Python 3.6 и версии OpenCV 3.3.0. Инструкции по установке OpenCV 3.3.0 вы можете найти у меня на сайте: установка OpenCV 3 на Raspberry Pi 3 Jessie. Весь представленный код может быть запущен как на системах Windows, так и на OSX, и Unix, таких как Raspberry Pi, Banana Pi.
Если вы устанавливали OpenCV 3 в виртуальное окружение, не забудьте перед началом работы войти в него следующими командами:
source ~/.profile workon cv_python3
Открываем локальный файл в OpenCV 3 Python
Начнем мы с главного – открытия файла. Для примера я использовал кадр из замечательного фильма “Matrix”, или “Матрица”.
Скачивайте его на свой компьютер, он понадобиться для дальнейших шагов по изучению OpenCV и Python. Готовы? Поехали дальше!
Загрузим кадр в программу и отобразим его встроенными средствами OpenCV 3 командами:
# добавим необходимый пакет с opencv import cv2 # загружаем изображение и отображаем его image = cv2.imread("matrix-sunglasses-768x320.jpg") cv2.imshow("Original image", image) cv2.waitKey(0)
Выполнение данного кода в Python 3.6 на моем компьютере выводит следующее окно:
Разберем подробно приведенный код:
- Строка 2: В первой значимой строке мы говорим интерпретатору Python загрузить библиотеку OpenCV
- Строка 5: Тут мы открываем и читаем файл с жесткого диска. Команда cv2.imread возвращает NumPy массив, который содержит представление данных из изображения.
- Строки 6-7: Отображение файла встроенными средствами OpenCV. Тут стоит остановиться подробнее: метод для отображения cv2.imshow() принимает в себя два аргумента, первый это название окна, в котором будет отрисовано изображение, второй – имя переменной, которая хранит данное изображение. Однако выполнение только данной команды отрисует изображение и сразу же закроет программу. Для того, чтобы мы смогли увидеть и работать с изображением, добавим команду cv2.waitKey(0). Данная команда останавливает выполнение скрипта до нажатия клавиши на клавиатуре. Параметр 0 означает что нажатие любой клавиши будет засчитано.
Изменяем размер изображения
Мы загрузили изображение как есть – хорошее начало, но хочется что то сделать с изображением. Сделаем его меньше, чтобы мы могли его использовать как иконку. Мы можем увидеть разрешение оригинального изображения через атрибут изображения shape, который покажет размерность NumPy массива и, таким образом, разрешение снимка:
print(image.shape)
Когда вы выполним код, мы можем увидеть что на терминал выведется (320, 768, 3). Это означает изображение содержит 320 строк, 768 столбцов и 3 канала цвета. Данный формат может показаться знакомым, если вы имели дело в школе или институте с матрицами – там так же сначала писалось количество строк, потом количество столбцов, далее количество матриц.
Но когда мы работаем с изображениями, мы пишем их размеры в нотации – ширина x высоту. Первоначально такой разный подход будет приводить к ошибкам, я сам много раз замечал, что по привычке пишу ширину изображения первой когда обращаюсь к массиву NumPy. Однако вам стоит попрактиковаться, попробовать различные методы, и вы потом сможете с легкостью понимать где ширина а где количество строк.
Изображение у шириной целых 768 пикселей, давайте сожмем его до ширины в 200 пикселей:
# Нам надо сохранить соотношение сторон # чтобы изображение не исказилось при уменьшении # для этого считаем коэф. уменьшения стороны final_wide = 200 r = float(final_wide) / image.shape[1] dim = (final_wide, int(image.shape[0] * r)) # уменьшаем изображение до подготовленных размеров resized = cv2.resize(image, dim, interpolation = cv2.INTER_AREA) cv2.imshow("Resize image", resized) cv2.waitKey(0)
Выполнение кода выведет следующее изображение:
Разберем код:
- Строки 4-6: Мы задаем итоговую ширину изображения, равную 200px. Далее мы хотим сохранить исходные пропорции изображения, чтобы уменьшить его не искажая. Для этого есть два пути: через коэффициент уменьшения и через коэффициент отношения сторон. В данном случае мы используем отношение новой ширины 200px и исходной 768px = r. Умножение данного числа на исходную высоту даст нам новую высоту изображения. Что мы и используем для создания кортежа с новым разрешением.
- Строки 9-11: Уменьшаем изображение методом cv2.resize. Данный метод принимает три параметра и возвращает новое изображение. Первый параметр – исходное изображение, второй – кортеж с требуемым разрешением для нового изображения, третий – алгоритм, который будет использоваться для масштабирования.
Вырезаем нужный фрагмент изображения
Мы открыли изображение, уменьшили, мы уже можем многое ? Для практического применения почти всегда нам не требуется целиком все изображение, нужен только интересующий нас участок. Для получения такого участка воспользуемся методом по получению кропа изображения:
# вырежем участок изображения используя срезы # мы же используем NumPy cropped = image[30:130, 150:300] cv2.imshow("Cropped image", cropped) cv2.waitKey(0)
Что же мы получили? Ответ:
Данный код показывает преимущества работы с изображениями в стиле NumPy: мы просто используем срезы. В такой нотации мы вырезаем изображение с 30 по 130 пиксель по высоте и со 150 по 300 пиксель по ширине. Заметьте что высота идет первая – как мы говорили выше, первой идет строки, вторыми идут столбцы.
Поворот изображения на OpenCV 3 Python
Теперь перейдем к сложным вещам – афинным преобразованиям. Начнем с простого поворота на 180 градусов, без смещения. Следующий код поставит Нео с ног на голову:
# получим размеры изображения для поворота # и вычислим центр изображения (h, w) = image.shape[:2] center = (w / 2, h / 2) # повернем изображение на 180 градусов M = cv2.getRotationMatrix2D(center, 180, 1.0) rotated = cv2.warpAffine(image, M, (w, h)) cv2.imshow("Rotated image", rotated) cv2.waitKey(0)
Выполнив код мы получим Нео и Морфеуса вниз ногами – что мы и хотели:
Разберем код подробнее:
- Строки 3-4: Мы получаем размеры изображения через атрибут shape и среза по первым двум показателям – высоте и ширине. Далее мы вычисляем середину картинки для передачи ее в матрицу вращения, мы же хотим чтобы изображение осталось в центре. Для этого просто делим числа на 2.
- Строка 7: Считаем матрицу для преобразования. В данном случае мы воспользовались методом cv2.getRotationMatrix2D, который может использоваться как для поворота изображения, так и для изменения его размеров. Данный метод принимает три аргумента – первый это кортеж с точкой, относительно которой будет осуществлен поворот изображения и изменение размера. Второй аргумент – угол поворота, в градусах. И третий аргумент – коэффициент увеличения, который может быть и меньше 1. Метод возвращает матрицу поворота, которая может использоваться в необходимых случаях.
- Строка 8: Поворачиваем изображение. Используем метод cv2.warpAffine, который принимает три параметра – исходное изображения, матрицу преобразования, в данном случае матрицу поворота, и кортеж с размерами выходного изображения. Данный метод возвращает преобразованную картинку.
- Строки 9-10: Показываем полученное изображение.
Отражаем изображение по осям
Рассмотрим такую частую операцию как отражение изображения. Для некоторых вычислений вам потребуется иметь не исходную картинку, а ее зеркальную копию, чего вы не сможете получить операцией поворота или срезом массива. В таком случае мы воспользуемся следующим кодом:
#отразим изображение по горизонтали flip_image = cv2.flip(image,1) cv2.imshow("Flip image", flip_image) cv2.waitKey(0)
Выполнив данный код мы получим Морфеуса в зеркале:
В данном коде мы воспользовались методом cv2.flip, данный метод принимает два параметра – исходное изображение и ось для отражения. В качестве осей может быть следующие числа: 0 – по вертикали, 1 – по горизонтали, (-1) – по вертикали и по горизонтали.
Сохраняем изображение на локальный диск с OpenCV и Python
После всего что мы сделали с исходным изображением, мы захотим сохранить полученные результаты. Для этого мы воспользуемся командой:
# запишем изображение на диск в формате png cv2.imwrite("flip.png", flip_image)
Как мы видим, исполнение этого кода создает файл:
Как мы можем видеть, мы сохранили файл в формат PNG, при том что исходный файл был в формате JPG. Мы сделали это командой cv2.imwrite, которая принимает два аргумента, первый – путь файла, который будет создан, второй – изображение. Все операции по преобразованию формата OpenCV заботливо взял на себя.
Итог
В данной статье вы научились самым основным и нужным вещам, таким как загрузка и простые операции с изображениями. Весь приведенный код вы можете найти на GitHub. Если вы будете дальше изучать компьютерное зрение, вы очень много раз будете использовать эти приемы. Для закрепления материала выберите интересное вам изображение и разбейте его на интересные участки с сохранением всех фрагментов на диск.
В следующем уроке я расскажу, как иметь дело с видео, и дальше мы начнем веселый урок по созданию приложения для рисования. Мы даже распишемся на полученном проекте с помощью технологий компьютерного зрения ?
7 Comments
вапрапр · 21/08/2020 at 23:01
где должна лежать эта картинка, чтобы она считалась, я уже сейчас застрелюсь
Аноним · 14/09/2020 at 07:37
Чтобы было проще, укажите явную ссылку на файл например: “C:\Users\UserName\Desktop\Works\image.jpg”
Это один из способов. Не самый лучший, но рабочий.
max · 15/05/2020 at 11:33
Спасибо! С этого и начнем!
Anonymous · 26/11/2019 at 09:38
cropped = image[30:230, 320:620]
Ms.M · 25/04/2019 at 08:38
cropped = image[30:130, 150:300]
Вырезается черный фон из исходной картинки.
Elena · 23/04/2019 at 07:32
Неверно вырезается картинка с Нео.
Nikolay · 16/01/2019 at 20:01
Ссылка, на упомянутую в начале статьи, инструкцию “установка OpenCV 3 на Raspberry Pi 3 Jessie” не рабочая. Не могли бы Вы её поправить?