Распознавание лиц и движения с помощью компьютерного зрения

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) и в итоге создать собственные камеры безопасности!