Список работ

Поиск фронтальных лиц и контуров на изображении

Содержание

Введение

Рассматриваются две задачи компьютерного зрения – поиск лиц на изображении и контуров имеющихся на изображении объектов. Обе задачи решаются средствами библиотеки OpenCV. Вдобавок поиск лиц выполняется нейронной сетью mtcnn.
Многие алгоритмы детектирования объектов основаны на предложенном в [1] подходе, предполагающем:

В каскадной модели отдельные классификаторы позволяют последовательно уточнять расположение окон, охватывающих, например, лица.
Повышение качества детектирования лиц может быть достигнуто за счет расширения набора примитивов Хаара [4], использования иных функций для извлечения признаков, а также в результате модификации слабых классификаторов.
Известны различные библиотечные реализации детекторов фронтальных лиц [5].
Ниже приводятся Python-версии программ, выполняющих поиск фронтальных лиц, использующих детекторы библиотек OpenCV (open source computer vision library) и mtcnn (multi-task cascaded convolutional neural network).
Найденные на фотографии лица, обводятся прямоугольной рамкой заданного цвета (рис. 1).

Все лица найдены

Рис. 1. Лица найдены

Вдобавок, работая с mtcnn, можно вывести ключевые точки (рис. 2).

Ключевые точки

Рис. 2. Вывод ключевых точек

Найденные лица могут быть переданы программе, выполняющей их распознавание [6].
Установка библиотек OpenCV и mtcnn:

pip install opencv-python
pip install mtcnn

Информацию о библиотеках предоставят следующие команды:

import cv2
print(cv2.__version__)
pip show mtcnn
import mtcnn
print(mtcnn.__version__)

Поиск лиц

Применение OpenCV

OpenCV использует каскадный классификатор П. Виолы и М. Джонса [1], выделяющий значимые признаки с помощью алгоритма AdaBoost [2, 3].
Для поиска лиц с OpenCV предварительно нужно загрузить ранее обученную модель, сохраненную в файле haarcascade_frontalface_default.xml [7]. После этого выделение лиц обеспечит следующий код:

from cv2 import imread, imshow, waitKey, destroyAllWindows, CascadeClassifier, rectangle
##filename = 'TheBeatles.jpg'
filename = '1_Handshaking_Handshaking_1_801.jpg'
photo = pyplot.imread(filename) # Загрузка изображения из файла
classifier = CascadeClassifier('haarcascade_frontalface_default.xml') # Загрузка классификатора
# Находим лица
# Коэффициент масштабирования scaleFactor = 1.05
# scaleFactor показывает, на сколько размер изображения изменяется при каждом масштабировании
# По умолчанию scaleFactor = 1.1
# minNeighbors = 5; задает число соседей прямоугольника-кандидата, необходимое для его сохранения
# По умолчанию minNeighbors = 3
boxes = classifier.detectMultiScale(photo, 1.05, 5) # photo, scaleFactor, minNeighbors
for box in boxes:
##    print(box)
    # Координаты правого верхнего угла рамки, ее ширина и высота
    x, y, width, height = box
    x2, y2 = x + width, y + height
    # Вывод прямоугольников (рамок), обрамляющих лица;
    # цвет рамки желтый; ширина линии рамки 2 пикселя
    rectangle(photo, (x, y), (x2, y2), (0, 255, 255), 2)
# Показываем изображение с найденными лицами
imshow('Faces', photo)
##waitKey(0) # Окно графического вывода будет закрыто после нажатия на клавишу
##destroyAllWindows() # Закрываем окно

Применение mtcnn

Многозадачная каскадная сверточная нейронная сеть позволяет находить лица и ключевые точки на них (см. рис. 2).
Пример структуры каскадной сверточной нейронной сети приведен на рис. 3 [8].

Каскадная СНС

Рис. 3. Пример структуры каскадной сверточной нейронной сети

На рис. 3:

Сеть обучают на доступных наборах данных, например, AFW [9]. AFW – содержит jpg-файлы с изображениями лиц (пример см. на рис. 4) – обучающая, оценочная и проверочная выборки.

AFW: пример из оценочной выборки

Рис. 4. Пример из оценочной выборки

Для первых двух выборок имеются описания рамок, охватывающих лица. Фрагмент файла с таким описанием для изображения, приведенного на рис. 4:

1--Handshaking/1_Handshaking_Handshaking_1_801.jpg
6
869 27 98 133 0 0 0 0 0 0
645 44 54 70 0 0 0 0 0 0
556 79 49 67 0 0 0 0 0 0
410 23 58 69 0 0 0 0 0 0
243 66 58 68 0 0 0 0 0 0
69 60 62 69 0 0 0 0 0 0

Первая строка файла – это имя рисунка, вторая – число рамок на рисунке, последующие – описания рамок.
При задании рамок (прямоугольников) используется физическая система координат: ее начало находится в верхнем левом углу окна вывода. Оси X и Y соответственно направлены влево и вниз.
Описание рамки содержит следующие данные: x1, y1, w, h, blur, expression, illumination, invalid, occlusion, pose, где
x1, y1, w, h - соответственно координаты верхнего левого угла рамки, ее ширина и высота;
blur – размытость: 0 – нет; 1 – нормальная; 2 – сильная;
expression – выражение лица: 0 – обычное; 1 – преувеличенное;
illumination – освещение: 0 – номальное; 1 – чрезмерное;
invalid – флаг плохого рисунка: 0 – хороший; 1 – плохой;
occlusion – окклюзия (деформация лица): 0 – нет; 1 – частичная; 2 – высокая;
pose – поза: 0 – обычная; 1 – необычная.
Для вывода рисунка библиотеки AFW и заданных для него рамок (рис. 5) можно применить следующий код:

import numpy as np
from matplotlib import pyplot
from matplotlib.patches import Rectangle
boxes_filename = '801.txt'
# Состав файла 801.txt:
# 1--Handshaking/1_Handshaking_Handshaking_1_801.jpg
# 6
# 869 27 98 133 0 0 0 0 0 0
# 645 44 54 70 0 0 0 0 0 0
# 556 79 49 67 0 0 0 0 0 0
# 410 23 58 69 0 0 0 0 0 0
# 243 66 58 68 0 0 0 0 0 0
# 69 60 62 69 0 0 0 0 0 0
# Используется физическая система координат.
# Ее начало в верхнем левом угду рисунка. Ось Y направлена вниз
# В файле после первых двух строчек следующие данные:
# x1, y1, w, h, blur, expression, illumination, invalid, occlusion, pose
# x1, y1, w, h - соответственно координаты верхнего левого угла рамки, ее ширина и высота
# blur - размытость: 0 - нет; 1 - нормальная; 2 - сильная
# expression - выражение лица: 0 - обычное; 1 - преувеличенное
# illumination - освещение: 0 - номальное; 1 - чрезмерное
# invalid - плохой рисунок: 0 - хороший; 1 - плохой
# occlusion - окклюзия (деформация лица): 0 - нет; 1 - частичная; 2 - высокая
# pose - поза: 0 - обычная; 1 - необычная
f = open(boxes_filename, 'r')
file_list = []
for line in f: file_list.append(line)
f.close()
filename = '1_Handshaking_Handshaking_1_801.jpg'
photo = pyplot.imread(filename)
pyplot.imshow(photo)
clr = 'red'
ax = pyplot.gca() # Контекст для выводы рамок (прямоугольников)
for k in range(2, 8):
    arr_b = np.asarray(file_list[k].split()).astype('int')
    w = arr_b[2]
    h = arr_b[3]
    rect = Rectangle(arr_b[0:2], w, h, fill = False, color = clr, linewidth = 2)
    ax.add_patch(rect)
pyplot.show()

AFW: рамки

Рис. 5. Изображение AFW с заданными для него рамками

Вывод лиц (рис. 6), найденных mtcnn с заданными по умолчанию параметрами, обеспечит следующий код:

from matplotlib import pyplot
from matplotlib.patches import Rectangle
from matplotlib.patches import Circle
from mtcnn.mtcnn import MTCNN
#
# Выводит изображение, обрамляя найденные лица прямоугольниками
def show_image_with_boxes(photo, faces, with_dots):
    clr = 'yellow'
    pyplot.imshow(photo)
    ax = pyplot.gca() # Контекст для выводы прямоугольников
    # Вывод обрамляющих рамок
    for face in faces: # Для каждого найденного прямоугольника
        x, y, width, height = face['box']
        # Обрамляющий прямоугольник и его вывод
        rect = Rectangle((x, y), width, height, fill = False, color = clr, linewidth = 2)
        ax.add_patch(rect)
        # Вывод точек
        if with_dots:
            for key, value in face['keypoints'].items():
                # Создание и вывод точек
                dot = Circle(value, radius = 2, color = clr)
                ax.add_patch(dot)
    pyplot.show()
##filename = 'TheBeatles.jpg'
filename = '1_Handshaking_Handshaking_1_801.jpg'
photo = pyplot.imread(filename) # Загрузка изображения из файла
detector = MTCNN() # Создаем детектор с заданными по умолчанию параметрами
faces = detector.detect_faces(photo) # Находим лица
show_image_with_boxes(photo, faces, False) # Показываем найденные лица (рис. 6)

Найденные лица

Рис. 6. Лица, найденные mtcnn

С заданными по умолчанию параметрами имеем одну ошибку.
Для вывода ключевых точек нужно изменить вызов процедуры show_image_with_boxes:

show_image_with_boxes(photo, faces, True)

Отдельно можно вывести обрамленные области (рис. 7):

# Выводим обрамленные части изображения
from matplotlib import pyplot
from matplotlib.patches import Rectangle
from matplotlib.patches import Circle
from mtcnn.mtcnn import MTCNN
def show_boxes(photo, faces):
    k = 0
    nFaces = len(faces)
    for face in faces:
        k += 1
        x1, y1, w, h = face['box']
        x2, y2 = x1 + w, y1 + h
        pyplot.subplot(1, nFaces, k)
        pyplot.axis('off')
        pyplot.imshow(photo[y1:y2, x1:x2]) # Вывод лица
    pyplot.show()
##filename = 'TheBeatles.jpg'
filename = '1_Handshaking_Handshaking_1_801.jpg'
photo = pyplot.imread(filename)
detector = MTCNN()
faces = detector.detect_faces(photo)
show_boxes(photo, faces)

Обрамленные области

Рис. 7. Обрамленные части изображения

Заметим, что детектор OpenCV с заданными по умолчанию параметрами не найдет 2 лица и ошибется в одном случае (рис. 8).

OpenCV: результат работы детектора

Рис. 8. Результат работы детектора OpenCV с заданными по умолчанию параметрами

Поиск контуров

Выполняется следующей программой:

only_contours = True # True False
import numpy as np, cv2
fn = '3d.jpg' # Путь к файлу с изображением
img = cv2.imread(fn)
# Параметры цветового фильтра. Подбираются для каждого изображения
hsv_min = np.array((12, 16, 120), np.uint8)
hsv_max = np.array((120, 120, 255), np.uint8)
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV) # Меняем цветовую модель с BGR на HSV
thresh = cv2.inRange(hsv, hsv_min, hsv_max) # Применяем цветовой фильтр
# Ищем контуры; они хранятся переменной contours
_, contours, hierarchy = cv2.findContours(thresh.copy(), cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
n_contours = len(contours)
### Отображаем контуры
##cv2.drawContours(img, contours, -1, (255, 0, 0), 2, cv2.LINE_AA, hierarchy, 1)
##cv2.imshow('contours', img) # Показываем изображение с найденными контурами
#
index = 0
def update():
        if only_contours:
                dst = np.zeros(img.shape, np.uint8) + 255
        else:
                dst = img.copy()
        cv2.drawContours(dst, contours, index, (0, 0, 0), 2)
        cv2.imshow('contours', dst)
def update_index(v):
        global index
        index = v - 1
        update()
update_index(0)
cv2.createTrackbar('contour', 'contours', 0, n_contours, update_index)

Если only_contours = True, то будут отображены только найденные контуры, в противном случае – объекты с контурами (рис. 9).

Найдены контуры

Рис. 9. Исходное изображения и два варианта вывода найденных контуров

Теорию вопроса можно посмотреть на станичке Фортран-реализация поиска контуров изображения

Заключение

Задача поиска лиц на изображении является частным случаем более общей задачи поиска (детектирования) объектов, заключающейся в обнаружении всех объектов указанных классов и определении охватывающей рамки для каждого из них. Родственными задачами являются следующие [10]:

Сегментация

Рис. 10. Сегментация: а – семантическая; б – по объектам

Список источников

  1. Viola P, Jones MJ. Rapid object detection using a boosted cascade of simple features. IEEE Conference on Computer Vision and Pattern Recognition; 2001. [Электронный ресурс] URL: https://www.cs.cmu.edu/~srini/15-829/readings/ViJo01.pdf (дата обращения: 01.06.2019).
  2. Freund Y, Schapire R. E. A decision-theoretic generalization of on-line learning and an application to boosting. In Computational Learning Theory: Eurocolt ’95, pages 23–37. Springer-Verlag, 1995.
  3. Поиск лица в растровом образе. [Электронный ресурс] URL: http://100byte.ru/stdntswrks/dbst/dbst.html#p9 (дата обращения: 01.06.2019).
  4. Lienhart R, Maydt J. An extended set of Haar-like features for rapid object detection. IEEE International Conference on Image Processing; 2002: 1: 900–903.
  5. Калиновский И. А. Обзор и тестирование детекторов фронтальных лиц. / Калиновский И. А., Спицын В. Г. // Компьютерная оптика. – 2016. – Т. 40, № 1, - С. 99-111. – DOI: 10.18287/2412-6179-2016-40-1-99-111. [Электронный ресурс] URL: https://cyberleninka.ru/article/v/obzor-i-testirovanie-detektorov-frontalnyh-lits (дата обращения: 01.06.2019).
  6. Распознавание лиц. [Электронный ресурс] URL: http://100byte.ru/python/lfw/lfw.html (дата обращения: 01.06.2019).
  7. Модель OpenCV для поиска лиц. [Электронный ресурс] URL: https://raw.githubusercontent.com/opencv/opencv/master/data/haarcascades/haarcascade_frontalface_default.xml (дата обращения: 01.06.2019).
  8. Haoxiang Li et al. A convolutional neural network cascade for face detection. [Электронный ресурс] URL: http://users.eecs.northwestern.edu/~xsh835/assets/cvpr2015_cascnn.pdf (дата обращения: 01.06.2019).
  9. WIDER FACE: A Face Detection Benchmark. Multimedia Laboratory, Department of Information Engineering, The Chinese University of Hong Kong. [Электронный ресурс] URL: http://shuoyang1213.me/WIDERFACE/ (дата обращения: 01.06.2019).
  10. Mask R-CNN: архитектура современной нейронной сети для сегментации объектов на изображениях. [Электронный ресурс] URL: https://habr.com/ru/post/421299/ (дата обращения: 01.06.2019).

Список работ

Рейтинг@Mail.ru