Opencv (Open Source Computer Vision Library или библиотека компьютерного зрения с открытым исходным кодом) – это модуль Python, используемый для решения задач с помощью компьютерного зрения. Это огромный модуль с исключительными возможностями. Используя компьютерное зрение, мы можем решать самые разные задачи. Примером таких задач может быть распознавание лиц и движения.
Сегодня мы с вами научимся писать код для обнаружения лиц на изображениях, видео и для распознавания движения.
Чтобы избежать всевозможных ошибок и проблем, мы загрузили файл opencv с GitHub по адресу https://github.com/opencv/opencv. Мы будем использовать некоторые содержащиеся в нем файлы для завершения кода.
Распознавание лиц на изображениях
В файле GitHub OpenCV есть подкаталог (opencv-master\samples\data) с именем data
, в котором доступны образцы изображений и видео для работы. Мы будем использовать фотографии и видео из этого каталога. В частности, давайте возьмем файл lena.jpg
. Скопируем и вставим его в свой рабочий каталог в PyCharm (или в любом другом редакторе). Теперь приступим к распознаванию лиц на этом изображении.
Для начала загрузим необходимые нам модули:
import numpy as np import cv2
Файл, который мы будем использовать, находится по адресу opencv-master\data\haarcascades\haarcascade_frontalface_default.xml в файле, загруженном с GitHub. Разместим ссылку на файл haarcascade
следующим образом:
face_cascade= cv2.CascadeClassifier('C:\\Users\\never\\Downloads\\opencv-master\\data\\haarcascades\\haarcascade_frontalface_default.xml')
Загрузим фотографию, чтобы выполнить распознавание лица с помощью метода imread()
библиотеки cv2.
image = cv2.imread('lena.jpg')
Наша следующая цель – превратить фотографию в оттенки серого. Сделаем это с помощью метода cv2.cvtColor()
.
Этот метод принимает два аргумента. Первый – имя файла, который нужно преобразовать, а второй – формат, в который нужно преобразовать этот файл. В данном случае мы будем использовать формат cv2.COLOR_BGR2GRAY
.
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
Затем воспользуемся функцией detectMultiScale()
для обнаружения объектов (в нашем случае — лиц). Здесь мы напишем face_cascade.detectMultiScale()
, который будет обнаруживать лица (это указано параметром face_cascade
).
Функция detectMultiScale()
принимает несколько аргументов: изображение, коэффициент масштабирования, минимальное количество соседей, флаги, минимальный и максимальный размер. Мы укажем только первые 3 аргумента.
faces = face_cascade.detectMultiScale(gray, 1.5, 5)
Чтобы разместить прямоугольную рамку вокруг лица, нам нужно использовать метод cv2.rectangle()
. Он принимает несколько аргументов. Первый – это наше изображение, второй – начальная точка прямоугольника, третий – конечная точка прямоугольника, четвертый – цвет прямоугольника, а пятый – его толщина. В данном случае w – ширина, h – высота, x и y – координаты начальной точки.
for (x,y,w,h) in faces: cv2.rectangle(image, (x,y), (x+w,y+h), (0,255,0), 3)
Наконец, мы выводим изображение на экран с помощью метода cv2.imshow()
. Мы также используем cv2.waitKey(0)
, чтобы установить бесконечное время ожидания, и cv2.destroyAllWindows()
, чтобы закрыть окно.
cv2.imshow('image',image) cv2.waitKey(0) cv2.destroyAllWindows()
Распознавание лиц с помощью видео или веб-камеры
Теперь давайте попробуем обнаружить лица в реальном времени с помощью веб-камеры или видео. Как и в прошлый раз, сначала мы импортируем необходимые модули.
import numpy as np import cv2
Далее нам нужно указать расположение файлов haarcascade
. Делаем это следующим образом:
face_cascade = cv2.CascadeClassifier('C:\\Users\\never\\Downloads\\opencv-master\\data\\haarcascades\\haarcascade_frontalface_default.xml')
Теперь нам нужно указать видео, с которым мы будем работать. Для этого воспользуемся методом cv2.VideoCapture()
. Сейчас мы будем использовать уже готовое видео. Если вам нужно работать с веб-камерой, поставьте 0 вместо имени видеофайла.
video = cv2.VideoCapture ("video.mp4")
Далее мы запускаем бесконечный цикл: мы просим программу определять лица, пока мы сами не остановим её. Видеофайл читаем с помощью функции read()
.
while True: ret, image = video.read()
Как и в предыдущем примере, для облегчения обнаружения лиц нам нужно преобразовать изображения или кадры в оттенки серого. Чтобы изменить цвет фреймов на серый, мы используем метод cv2.cvtColor()
.
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
Воспользуемся функцией detectMultiScale()
для обнаружения лиц. Функция принимает те же параметры, что и в предыдущем примере.
faces = face_cascade.detectMultiScale(gray, 1.1, 4)
Чтобы разместить прямоугольники вокруг граней, мы используем метод cv2.rectangle()
. Это мы уже тоже делали ?
for (x, y, w, h) in faces: cv2.rectangle(image, (x, y), (x+w, y+h), (255, 0, 0), 2)
Затем мы показываем кадры с помощью метода cv2.imshow()
. Этот метод принимает два аргумента: первый – имя фрейма, а второй – фрейм для отображения.
cv2.imshow('image', image)
Затем мы прописываем что, если пользователь нажимает клавишу ESC (или 27), тогда цикл завершится, и программа остановится.
if cv2.waitKey(0) & 0xff == 27: break
И наконец, мы выпускаем видео с помощью функции release()
.
video.release()
Распознавание движения
А теперь давайте попробуем с помощью Python и хорошей веб-камеры создать нашу собственную камеру безопасности! Итак, приступим. Для начала импортируем библиотеки (те же, что и в прошлых примерах).
Возьмем видео из примеров (opencv-master\samples\data) файла с GitHub.
video = cv2.VideoCapture("vtest.avi")
Чтобы обнаружить движение, мы в основном полагаемся на разницу в значениях пикселей двух изображений. Поэтому создадим два изображения, frame1
и frame2
.
ret, frame1 = video.read() ret, frame2 = video.read()
Пока открыто видео или используется функция isOpened()
, мы начинаем цикл.
while video.isOpened():
Основная часть программы
Для начала давайте вычислим абсолютную разницу между frame1
и frame2
с помощью метода cv2.absdiff()
.
difference = cv2.absdiff(frame1, frame2)
Поскольку в черно-белых цветах работать проще, давайте превратим полученную разницу в оттенки серого с помощью метода cv2.cvtColor()
, его мы уже использовали для распознавания лиц на изображениях в первом примере.
gray = cv2.cvtColor(difference, cv2.COLOR_BGR2GRAY)
Когда изображение преобразовано в оттенки серого, нам нужно его размыть, чтобы удалить шум. Для этого используется метод cv2.GaussianBlur()
. Он принимает несколько аргументов: исходное изображение для размытия, выходное изображение, размер ядра Гаусса, стандартное отклонение ядра по оси x, стандартное отклонение ядра по оси y и тип границы.
blur = cv2.GaussianBlur(gray, (5,5), 0)
Затем мы устанавливаем пороговое значение с помощью метода cv2.threshold()
. Эта техника изолирует движение, сегментируя фон и передний план (или движение). Метод cv2.threshold()
принимает четыре аргумента: изображение, пороговое значение, максимальное значение, используемое с THRESH_BINARY
и THRESH_BINARY_INV
, и тип порогового значения.
_, threshold = cv2.threshold(blur, 20, 255, cv2.THRESH_BINARY)
Затем мы используем метод cv2.dilate()
, который принимает максимум 6 аргументов: изображение, ядро, привязку, итерации, тип границы и значение границы.
dilate = cv2.dilate(threshold, None, iterations=3)
Метод cv2.findContours()
находит контуры, что логично следует из названия. Он принимает три аргумента: исходное изображение, режим поиска и метод аппроксимации контура.
contour, _ = cv2.findContours(dilate, cv2.RETR_TREE, v2.CHAIN_APPROX_SIMPLE)
Метод cv2.drawContours()
используется для рисования контуров. Он также принимает несколько аргументов: изображение, контуры, contourIdx
(это значение отрицательно, если нарисованы все контуры), цвет, толщина, тип линии, иерархия, максимальный уровень и смещение.
cv2.drawContours(frame1, contour, -1, (0, 0, 255), 2)
Наконец, мы показываем изображение с помощью метода cv2.imshow()
.
cv2.imshow("image", frame1)
Теперь мы устанавливаем frame2
в качестве первого кадра и считываем видео для нового кадра, который помещаем в параметр frame2
.
frame1 = frame2 ret, frame2 = video.read()
Если клавиша «q» нажата, произойдет выход из цикла:
if cv2.waitKey(40) == ord('q'): break video.release()
В целом код для обнаружения движения будет выглядеть примерно так:
import numpy as np import cv2 video = cv2.VideoCapture("vtest.avi") ret, frame1 = video.read() ret, frame2 = video.read() while video.isOpened(): difference = cv2.absdiff(frame1, frame2) gray = cv2.cvtColor(difference, cv2.COLOR_BGR2GRAY) blur = cv2.GaussianBlur(gray, (5,5), 0) _, threshold = cv2.threshold(blur, 20, 255, cv2.THRESH_BINARY) dilate = cv2.dilate(threshold, None, iterations=3) contour, _ = cv2.findContours(dilate, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) cv2.drawContours(frame1, contour, -1, (0, 0, 255), 2) cv2.imshow("image", frame1) frame1 = frame2 ret, frame2 = video.read() if cv2.waitKey(40) == ord('q'): break video.release()
Просто, не правда ли? Несколько строк кода, и мы можем создавать собственные программы распознавания лиц и движения. Несколько дополнительных строк, и мы даже можем заставить их говорить (скажем, используя pttsx3) и в итоге создать собственные камеры безопасности!