Находим лица в картинке с веб-камеры
medium

Находим лица в картинке с веб-камеры

Первый шаг на пути к крупным проектам

Сегодня сделаем модную штуку в Python — научимся находить лица в веб-камере. Потом научимся делать то же самое на картинах, а затем на основе этого сделаем много разного и интересного. 

Вот что нужно для начала знать о распознавании лиц:

  • Для распознавания лица компьютер должен получить изображение — через камеру или готовый файл.
  • Компьютер использует особый алгоритм, который разбивает изображение на прямоугольники.
  • С помощью этих прямоугольников алгоритм пытается найти на картинке знакомые ему переходы между светлыми и тёмными областями.
  • Если в одном месте программа находит много таких совпадений, то, скорее всего, это лицо человека.
  • Чтобы программистам каждый раз не писать свой код распознавания с нуля, сделали специальную библиотеку компьютерного зрения — cv2. Если в неё загрузить заранее подготовленные параметры лиц, она сможет распознавать их намного точнее.
  • С помощью этой библиотеки можно находить на картинке не только лица, но и другие предметы — для этого нужно использовать дополнительные библиотеки либо обучать систему самому.

Сегодня мы научимся работать с этой библиотекой компьютерного зрения и определим лицо человека в кадре:

Сегодня сделаем модную штуку в Python — научимся находить лица в веб-камере

Логика проекта

Будем делать так:

  1. Установим и подключим библиотеку cv2.
  2. Получим изображение с камеры и выведем его в отдельном окне.
  3. Обучим библиотеку находить лица.
  4. Напишем функцию выделения лиц на изображении.
  5. Объединим всё вместе и получим выделение лица с камеры в режиме реального времени.

Для проекта нам понадобится Python — это идеальный язык для работы с нейросетями и компьютерным зрением.

Если ещё не работали с Python, вот материал: как установить Python на компьютер и начать на нём писать.

Устанавливаем cv2

Для установки библиотеки запустим терминал или VS Code и выполним такую команду:

pip install opencv-python

Теперь убедимся, что это сработало: создаём новый Python-файл и пишем в нём команду:

# подключаем библиотеку компьютерного зрения 
import cv2

Если после запуска скрипта ошибок нет — всё установилось правильно и можно двигаться дальше.

Получаем изображение с камеры

По умолчанию библиотека работает с веб-камерой, которая в системе установлена первой (и часто — единственной). Так как нумерация в программировании почти всегда начинается с нуля, нам нужно обратиться к нулевому устройству видеозахвата.

В современных операционных системах в целях безопасности доступ к камере отключён для внешних скриптов, поэтому при первом запуске у нас могут спросить: разрешить доступ к камере или нет? Выбираем вариант «Да, разрешить»:

Находим лица в картинке с веб-камеры

После этого делаем так: пока не нажата любая клавиша — выводим окошко с изображением. Но может случиться так, что доступ к камере есть, а с самой камерой что-то не так — нет картинки, например. В этом случае нет смысла пытаться определить лица — лучше сразу прекратить работу. Для этого мы проверяем параметр hasFrame — он как раз отвечает за то, есть картинка или нет. 

Добавляем этот код в файл, сохраняем и запускаем скрипт:

# получаем видео с камеры
video=cv2.VideoCapture(0)
# пока не нажата любая клавиша — выполняем цикл
while cv2.waitKey(1)<0:
    # получаем очередной кадр с камеры
    hasFrame,frame=video.read()
    # если кадра нет
    if not hasFrame:
        # останавливаемся и выходим из цикла
        cv2.waitKey()
        break
    # выводим картинку с камеры
    cv2.imshow("Face detection", frame)
Появилась картинка — значит, мы на верном пути
Появилась картинка — значит, мы на верном пути

Запускаем нейросеть для определения лиц

Чтобы библиотека компьютерного зрения могла уметь определять лица, её нужно этому научить. Для этого создадим внутреннюю нейросеть, которая уже натренирована на определение лиц, и используем её для наших задач. 

Обученная нейросеть отличается тем, что в ней уже сформированы все слои виртуальных нейронов и правильно распределены веса каждого нейрона. Мы возьмём уже готовые веса и слои и положим их в ту же папку, что и скрипт. Эти файлы — результат работы программистов, которые уже обучили нейросеть на 25 тысячах фотографий. 

Вот эти файлы нужно скачать и положить в ту же папку, что наш скрипт:

веса для нейросети

модель для определения лиц

Теперь всё готово для создания нейросети по определению лица на изображении:

# загружаем веса для распознавания лиц
faceProto="opencv_face_detector.pbtxt"
# и конфигурацию самой нейросети — слои и связи нейронов
faceModel="opencv_face_detector_uint8.pb"

# запускаем нейросеть по распознаванию лиц
faceNet=cv2.dnn.readNet(faceModel,faceProto)

Пишем функцию определения лиц

Компьютеру неважно, сколько лиц определять — одно или несколько, — поэтому мы сделаем универсальную функцию. Она возьмёт картинку, найдёт на ней все лица и обведёт их зелёной рамкой.

У функции на входе будет три параметра:

  • модель определения лиц;
  • кадр, в котором нужно найти все лица;
  • порог срабатывания распознавания.

Кадр — это условный скриншот того, что видит камера. В секунду камера может обрабатывать от 15 до 60 кадров — это зависит от самой камеры и настроек операционной системы. 

Порог определяет точность распознавания: если вероятность того, что перед нами лицо, больше порога, то это считается лицом. Поставим порог меньше — это поможет с картинкой плохого качества, но зато компьютер может начать видеть лица там, где их нет. Поставим порог повыше — мы будем уверены, что перед нами лицо, но стоит повернуть голову как-то не так или поменять свет, то алгоритм уже его не определит. 

Модель определения — это алгоритм, по которому компьютер поймёт, что перед нами именно лицо. Его мы как раз сделали на предыдущем этапе.

Выполним предварительную работу внутри функции:

  • получим размеры кадра;
  • превратим кадр в бинарный объект с помощью специального алгоритма;
  • прогоним объект через модель распознавания; 
  • создадим массив для рамок — там будут храниться координаты рамок для всех найденных лиц.

# функция определения лиц
def highlightFace(net, frame, conf_threshold=0.7):
    # делаем копию текущего кадра
    frameOpencvDnn=frame.copy()
    # высота и ширина кадра
    frameHeight=frameOpencvDnn.shape[0]
    frameWidth=frameOpencvDnn.shape[1]
    # преобразуем картинку в двоичный пиксельный объект
    blob=cv2.dnn.blobFromImage(frameOpencvDnn, 1.0, (300, 300), [104, 117, 123], True, False)
    # устанавливаем этот объект как входной параметр для нейросети
    net.setInput(blob)
    # выполняем прямой проход для распознавания лиц
    detections=net.forward()
    # переменная для рамок вокруг лица
    faceBoxes=[]

К этому моменту наша модель уже определила все лица в кадре, сохранила их у себя и готова работать дальше. Теперь мы можем проверить, насколько каждое определение превышает установленный порог — если значение выше порога, то это точно лицо.

Ещё мы сразу записываем координаты найденного блока с лицом в отдельный массив — он нам пригодится для отрисовки рамок вокруг лиц на картинке.

Результат работы функции — это сам кадр и массив с координатами рамок вокруг лиц.

 # перебираем все блоки после распознавания
    for i in range(detections.shape[2]):
        # получаем результат вычислений для очередного элемента
        confidence=detections[0,0,i,2]
        # если результат превышает порог срабатывания — это лицо
        if confidence>conf_threshold:
            # формируем координаты рамки
            x1=int(detections[0,0,i,3]*frameWidth)
            y1=int(detections[0,0,i,4]*frameHeight)
            x2=int(detections[0,0,i,5]*frameWidth)
            y2=int(detections[0,0,i,6]*frameHeight)
            # добавляем их в общую переменную
            faceBoxes.append([x1,y1,x2,y2])
            # рисуем рамку на кадре
            cv2.rectangle(frameOpencvDnn, (x1,y1), (x2,y2), (0,255,0), int(round(frameHeight/150)), 8)
    # возвращаем кадр с рамками
    return frameOpencvDnn,faceBoxes

Собираем всё вместе и запускаем скрипт

Единственное, что осталось сделать, — добавить в основной цикл вызов функции для определения лица и сделать проверку, когда определённых лиц нет:

# распознаём лица в кадре
resultImg,faceBoxes=highlightFace(faceNet,frame)
# если лиц нет
if not faceBoxes:
    # выводим в консоли, что лицо не найдено
    print("Лица не распознаны")

Теперь скрипт можно запускать и проверять — на каком расстоянии перестанет работать компьютерное зрение и сколько человек одновременно система сможет распознать.

Находим лица в картинке с веб-камеры

# подключаем библиотеку компьютерного зрения 
import cv2

# функция определения лиц
def highlightFace(net, frame, conf_threshold=0.7):
    # делаем копию текущего кадра
    frameOpencvDnn=frame.copy()
    # высота и ширина кадра
    frameHeight=frameOpencvDnn.shape[0]
    frameWidth=frameOpencvDnn.shape[1]
    # преобразуем картинку в двоичный пиксельный объект
    blob=cv2.dnn.blobFromImage(frameOpencvDnn, 1.0, (300, 300), [104, 117, 123], True, False)
    # устанавливаем этот объект как входной параметр для нейросети
    net.setInput(blob)
    # выполняем прямой проход для распознавания лиц
    detections=net.forward()
    # переменная для рамок вокруг лица
    faceBoxes=[]
    # перебираем все блоки после распознавания
    for i in range(detections.shape[2]):
        # получаем результат вычислений для очередного элемента
        confidence=detections[0,0,i,2]
        # если результат превышает порог срабатывания — это лицо
        if confidence>conf_threshold:
            # формируем координаты рамки
            x1=int(detections[0,0,i,3]*frameWidth)
            y1=int(detections[0,0,i,4]*frameHeight)
            x2=int(detections[0,0,i,5]*frameWidth)
            y2=int(detections[0,0,i,6]*frameHeight)
            # добавляем их в общую переменную
            faceBoxes.append([x1,y1,x2,y2])
            # рисуем рамку на кадре
            cv2.rectangle(frameOpencvDnn, (x1,y1), (x2,y2), (0,255,0), int(round(frameHeight/150)), 8)
    # возвращаем кадр с рамками
    return frameOpencvDnn,faceBoxes

# загружаем веса для распознавания лиц
faceProto="opencv_face_detector.pbtxt"
# и конфигурацию самой нейросети — слои и связи нейронов
faceModel="opencv_face_detector_uint8.pb"

# запускаем нейросеть по распознаванию лиц
faceNet=cv2.dnn.readNet(faceModel,faceProto)

# получаем видео с камеры
video=cv2.VideoCapture(0)
# пока не нажата любая клавиша — выполняем цикл
while cv2.waitKey(1)<0:
    # получаем очередной кадр с камеры
    hasFrame,frame=video.read()
    # если кадра нет
    if not hasFrame:
        # останавливаемся и выходим из цикла
        cv2.waitKey()
        break
    # распознаём лица в кадре
    resultImg,faceBoxes=highlightFace(faceNet,frame)
    # если лиц нет
    if not faceBoxes:
        # выводим в консоли, что лицо не найдено
        print("Лица не распознаны")
    # выводим картинку с камеры
    cv2.imshow("Face detection", resultImg)

Что дальше

В следующей части мы научим программу работать с файлами и познакомимся с параметрами запуска скрипта. Это нам пригодится и в других проектах.

Нейросети победили. Победите нейросети
Проходите подготовку на продвинутых курсах, чтобы не нейросети заменили вас, а вы создали нейросети. «Практикум» подобрал для вас фундаментальные и навыковые курсы, чтобы это сделать. Начните здесь, это бесплатно:
Начать бесплатно
Нейросети победили. Победите нейросети Нейросети победили. Победите нейросети Нейросети победили. Победите нейросети Нейросети победили. Победите нейросети
Получите ИТ-профессию
В «Яндекс Практикуме» можно стать разработчиком, тестировщиком, аналитиком и менеджером цифровых продуктов. Первая часть обучения всегда бесплатная, чтобы попробовать и найти то, что вам по душе. Дальше — программы трудоустройства.
Начать карьеру в ИТ
Получите ИТ-профессию Получите ИТ-профессию Получите ИТ-профессию Получите ИТ-профессию
Еще по теме
medium