OpenCV в Python: Часть 1 — Работа с изображениями и видео
Перевод материала подготовлен в рамках курса "Python Developer. Basic".
Добро пожаловать! Перед вами первая статья из серии OpenCV в Python, которая, как вы уже догадались по названию, посвящена тому, как научиться комфортно работать в OpenCV.
Я понимаю, что у каждого свой стиль обучения, но я настоятельно рекомендую вам вместе со мной следовать за мыслью и писать код по мере прохождения уроков. Все файлы кода и данных будут доступны в конце каждой статьи. Если у вас будут появляться вопросы, не стесняйтесь их задавать.
Не будем терять времени, начнем!
Начало работы с OpenCV
Поскольку мы начинаем с самого начала, в этом разделе мы поговорим об основах обработки изображений. Чтобы начать работать с OpenCV, надо сначала ее установить. Для этого введите команду в терминале (на Windows):
pip install opencv-python
Как только установка будет завершена, можно начинать писать код.
Для начала давайте импортируем необходимые библиотеки.
import cv2
import argparse
Модуль cv2 – это и есть OpenCV. Его мы будем использовать для анализа изображений и видео. Модуль argparse будет полезен при работе с аргументами, передаваемыми через терминал. Если вам неудобно работать с командой строкой, можете почитать это руководство (https://www.pyimagesearch.com/2018/03/12/python-argparse-command-line-arguments/), в котором все очень хорошо объясняется.
Работать мы будем с этим изображением.
Разместите это изображение (или любое другое на выбор) в директорию, где находится ваш файл с программой.
В терминале мы передадим это изображение в качестве аргумента, поэтому в файле с исходным кодом нужно сделать парсер аргументов.
ap = argparse.ArgumentParser()
ap.add_argument("-i", "--image", required=True, help="path to input image")
args = vars(ap.parse_args())
После создания экземпляра argparse
, добавим аргумент, который, по сути, сообщает, что изображение передается, как аргумент, и его нужно распарсить. Затем обработанный аргумент передается функции vars()
, которая возвращает атрибут dict
указанного объекта.
С помощью метода imread
из cv2, мы положим изображение в переменную image
.
image = cv2.imread(args["image"], cv2.IMREAD_GRAYSCALE)
Первый аргумент, передаваемый функции – это args[“image”]
, обработанный аргумент, содержащий путь к изображению. Поскольку мы сохранили изображение в той же папке, просто передадим имя файла изображения.
Второй аргумент конвертирует изображение в оттенки серого. Этот шаг мы будем часто выполнять при работе с изображениями и видео, потому что обработка цветных изображений намного сложнее и занимает много времени, тогда как зачастую изображений в оттенках серого вполне достаточно для многих задач. Следовательно, нам нет необходимости использовать более сложные и трудные в обработке цветные изображения.
Для отображения изображений используется метод imshow. Первый аргумент – заголовок отображаемого изображения, а второй – сама переменная изображения.
cv2.imshow("Image", image)
cv2.waitKey(0)
cv2.waitKey(0)
будет ждать, пока пользователь не нажмет любую клавишу, после чего окно с изображением закроется.
Помимо вывода самого изображения, эту переменную image
можно использовать для отображения некоторой базовой информации, такой как высота и ширина изображения.
(h, w) = image.shape[:2]
# display image properties
print("width: {} pixels".format(w))
print("height: {} pixels".format(h))
OpenCV позволяет сохранить этот файл и записать его на диск. Что интересно, OpenCV также под капотом обрабатывает преобразование типов, то есть вы можете сохранить изначально .jpeg файл в формате .png.
Метод imwrite
принимает путь к выходному изображению, которое будет сохранено в качестве первого аргумента, и переменную с изображением в качестве второго. Если вы хотите изменить тип файла, просто измените его в имени пути, а OpenCV позаботится об остальном.
cv2.imwrite("folder/newimage.png", image)
А вот и полный код:
import cv2
import argparse
ap = argparse.ArgumentParser()
ap.add_argument("-i", "--image", required=True, help="path to input image")
args = vars(ap.parse_args())
image = cv2.imread(args["image"], cv2.IMREAD_GRAYSCALE)
cv2.imshow("Image", image)
cv2.waitKey(0)
(h, w) = image.shape[:2]
# display image properties
print("width: {} pixels".format(w))
print("height: {} pixels".format(h))
cv2.imwrite("photos/newimage.png", image)
Команда для выполнения файла:
python app.py --image photo_one.jpeg
Примечание: Я назвал файл с программой app.py, а файл с изображением photo_one.jpeg, не забудьте вставить свои названия.
После выполнения этого файла, вы получите исходное изображение в оттенках серого:
В вашем основном каталоге создастся папка с изображениями, в которой вы увидите то же изображение, что и в файле newimage.png.
Работа с видео в OpenCV
Теперь, когда мы закончили с изображениями, пришло время познакомиться с основами взаимодействия с веб-камерой или видеофайлами в OpenCV. Работа с видео мало чем отличается от работы с изображениями, поскольку видео состоит из кадров, которые по сути являются изображениями.
Для начала импортируем библиотеки.
import cv2
import numpy as np
Теперь создадим объект VideoCapture
, чтобы, как следует из названия, «захватывать» видео.
cap = cv2.VideoCapture(0)
Число, которое мы передаем, означает источник. 0 – первая веб-камера в вашей системе, 1 – вторая и т.д.
Если вы хотите загрузить уже существующий видеофайл вместо захвата прямой трансляции, просто на место номера вставьте путь к нему.
Затем создадим цикл while
, чтобы получать из источника кадр за кадром.
while True:
ret, frame = cap.read()
cv2.imshow('video feed', frame)
Функция cap.read()
возвращает логическое значение (True/False) и кадр. Если кадр был считан верно, то возвращается True.
cv2.imshow()
используется для отображения видео. Название видео будет первым аргументом.
Поскольку мы сделали бесконечный цикл, нам нужно что-то, что его прервет.
if cv2.waitKey(1) & 0xFF == ord('q'):
break
Поначалу этот фрагмент кода может показаться странным, но как только вы разберетесь в деталях, станет легче.
Функция waitKey(0)
возвращает -1, когда ввод вообще не производится. Как только происходит событие, то есть нажимается кнопка, она возвращает 32-разрядное целое число.
В этом сценарии 0xFF
– это 8-битный двоичный код 11111111, поскольку для представления символа «q». В результате вы получите целое число меньшее 255.
Следовательно, сравнивая целое число со значением ord(char)
, мы можем проверить событие нажатия клавиши и прервать цикл[1].
После того, как мы закончим использовать камеру, ее нужно «освободить». Если мы этого не сделаем, то в следующий раз при попытке ее использовать, вы получите ошибку.
cap.release()
cv2.destroyAllWindows()
Теперь пришло время запустить файл. На всякий случай, если вы не проследили, приведу весь код этого раздела:
import cv2
import numpy as np
cap = cv2.VideoCapture(0)
while True:
ret, frame = cap.read()
cv2.imshow('video feed', frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cap.release()
cv2.destroyAllWindows()
После выполнения файла, вы увидите изображение с веб-камеры в окне под названием «video feed». Чтобы закрыть окно, нажмите «q».
Помните, как мы преобразовали наше цветное изображение в оттенки серого и сохранили его на диске? То же самое можно сделать и с видео. Нужно просто внести несколько незначительных изменений.
В цикл while добавьте следующие инструкции:
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
cv2.imshow('gray feed', gray)
После сохранения и выполнения файла вы получите два окна:
Исходную версию.
Версию в оттенках серого.
Теперь мы можем выводить два или более окон, когда хотим сравнить наши изменения с исходным файлом/потоком. Так проще обнаруживать изменения, которые мы внесли.
Также мы можем сохранить файл с помощью объекта VideoWriter
. Перед этим нужно указать переменную fourcc (https://en.wikipedia.org/wiki/FourCC). FourCC – это 4-байтовый код, который используется для указания видеокодека. Полный список кодов можно посмотреть в кодеках FourCC (http://www.fourcc.org/codecs.php).
fourcc = cv2.VideoWriter_fourcc(*'XVID')
out = cv2.VideoWriter('output.avi', fourcc, 20.0, (640, 480))
Имя выходного файла будет первым аргументом. Затем нужно передать количество кадров в секунду (fps) и размер кадра.
Чтобы сохранить видео, нужно записать каждый кадр в цикле while.
out.write(frame)
out.release()
cv2.destroyAllWindows()
Не забудьте в конце освободить экземпляр VideoWriter
.
Полный код:
import cv2
import numpy as np
cap = cv2.VideoCapture(0)
fourcc = cv2.VideoWriter_fourcc(*'XVID')
out = cv2.VideoWriter('output.avi', fourcc, 20.0, (640, 480))
while True:
ret, frame = cap.read()
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
out.write(frame)
cv2.imshow('video feed', frame)
cv2.imshow('gray feed', gray)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cap.release()
out.release()
cv2.destroyAllWindows()
После выполнения этого кода вы заметите, что видео с именем «output.avi» будет присутствовать в вашем главном каталоге. Вот видео, которое мы только что записали и сохранили на диск.
Итоги
В этой статье мы поговорили о самом простейшем – загрузке и записи мультимедийного контента. OpenCV – очень мощный инструмент, который можно использовать для гораздо более высокоуровневых работ.
На данный момент, я надеюсь, что вам стало гораздо удобнее работать с OpenCV. На самом деле, я бы посоветовал вам почитать официальную документацию и повозиться с кодом, пока я пишу следующую статью этой серии, которую посвящу более сложному контенту.
Ссылки на следующие статьи будут появляться здесь же, так что следите.
Код на GitHub
Код – Часть 1 (https://github.com/sthitaprajna-mishra/opencv_in_python/tree/main/Part%201)
Сноски
Getting Started with Videos — OpenCV-Python Tutorials 1 documentation (opencv-python-tutroals.readthedocs.io)
Узнать подробнее о курсе