[Stove AI] Машинное обучение 055 — Создание распознавателя лиц с использованием гистограммы LBP

машинное обучение искусственный интеллект Python NumPy

[Stove AI] Машинное обучение 055 — Создание распознавателя лиц с использованием гистограммы LBP

(Библиотеки Python и номера версий, используемые в этой статье: Python 3.6, Numpy 1.14, scikit-learn 0.19, matplotlib 2.2)

сообщение в блоге передо мной[Stove AI] Машинное обучение 052-OpenCV создает детектор лиц, носа и глазВ разделе мы говорили о методе и кодовой реализации обнаружения лица, но во многих практических случаях нам нужно сделать распознавание лица, то есть определить, является ли лицо на изображении Чжан Санем или Ли Си, поэтому в этом статью мы рассмотрим Посмотрите, как использовать гистограмму LBP для построения распознавателя лиц.


1. Введение в локальные бинарные паттерны

Local Binary Pattern (LBP) — это оператор, используемый для описания локальных особенностей текстуры изображения. Локальный текстурный анализ имеет много потенциальных применений, таких как проверка промышленных поверхностей, удаленный мониторинг, анализ изображений и т. д.

Основная идея LBP: исходный оператор LBP представляет собой окно 3 * 3 с центральным пикселем в качестве порога и сравнивает значения серого соседних 8 пикселей с центральным пикселем.Это 0, поэтому получается бинаризованное изображение этих 9 пикселей, поэтому название — локальная бинаризация, как показано на следующем рисунке. От левого центрального пикселя бинаризованного изображения в качестве начальной точки направление против часовой стрелки является квадратом, и бинаризованное значение берется для получения двоичного значения шаблона в изображении.Это значение является кодом LBP. время, мы называем значение LBP центрального пикселя 11110001. Если значение LBP вычисляется для всех пикселей изображения, получается карта характеристик LBP изображения.

Относительно инвариантности оттенков серого: очевидно, что если все значения оттенков серого в исходном локальном изображении увеличиваются на одно значение или вычитаются на одно значение одновременно, это эквивалентно увеличению или уменьшению яркости, но в это время полученный код LBP остается неизменным, так называемая инвариантность оттенков серого. Следует отметить, что инвариантность оттенков серого применима только к монотонным изменениям значений оттенков серого. Как показано ниже

Вышеприведенный LBP-оператор имеет недостаток, он покрывает только небольшую область в пределах фиксированного радиуса, что явно не может удовлетворить потребности текстур разного размера и частоты, поэтому некоторые люди улучшают его и расширяют поле 3*3 на любое поле. замените квадратное поле круглым полем.На следующем рисунке показан случай, когда центральный пиксель является центром круга, R является радиусом, а точки P равномерно выбираются в качестве точек выборки на круге.

На приведенном выше рисунке размер R определяет размер круга, отражающий масштаб двумерного пространства, а размер P определяет количество точек выборки, отражающих разрешение углового пространства. Точно так же мы также можем изменить значения R и P для достижения различных масштабных и угловых разрешений (как показано ниже). Это также является теоретической основой «анализа с несколькими разрешениями» в будущем.

Хотя приведенный выше оператор LBP может достигать нескольких разрешений, он не инвариантен к вращению, и вращение изображения будет получать разные значения LBP.Значение LBP начального определения серии принимает минимальное значение в качестве значения LBP для поле.

В приложениях LBP, таких как распознавание лиц и анализ текстуры, мы обычно не используем карту LBP в качестве вектора признаков для классификации и распознавания, а используем статистическую гистограмму карты признаков LBP в качестве вектора признаков.

Шаги использования гистограммы LBP для извлечения признаков обычно следующие:

1) Сначала разделите окно обнаружения на 16×16 небольших областей (ячеек)

2) Для пикселя в каждой ячейке сравниваем с ним значение серого соседних 8 пикселей.Если значение окружающего пикселя больше значения центрального пикселя, позиция пикселя помечается как 1, в противном случае - 0. Таким образом, можно сравнить 8 точек в окрестности 3*3, чтобы сгенерировать 8-битное двоичное число, то есть можно получить значение LBP центрального пикселя окна.

3) Затем вычислить гистограмму каждой ячейки, то есть частоту каждого числа (предполагается, что это десятичное число значение LBP); затем нормализовать гистограмму

4) Наконец, полученная статистическая гистограмма каждой ячейки соединяется в вектор признаков, то есть вектор признаков текстуры LBP всего изображения, после чего для классификации можно использовать SVM или другие алгоритмы машинного обучения.

Для углубленной теории LBP вы можете обратиться к сообщению в блоге:Принцип извлечения признаков LBP (локальный двоичный шаблон)иЛокальные двоичные шаблоны для классификации текстур


2. Подготовьте набор данных

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

# 定义一个函数来加载图片数据集
def load_train_set(imgs_folder,face_cascade):
    '''
    从imgs_folder中加载图片数据和标记,注意imgs_folder中包含有多个子文件夹,每个子文件夹的名称就是label
    '''
    folders=glob(os.path.join(imgs_folder,'*'))
    imgs_paths=[]
    [imgs_paths.extend(glob(os.path.join(folder, '*.*'))) for folder in folders]
    
    face_imgs=[]
    labels=[]
    # 对每一张图片都检测画面上的人脸
    for img_path in imgs_paths:
        image = cv2.imread(img_path, 0) 
        label=os.path.split(img_path)[0]
        img_folder=os.path.split(img_path)[0]
        faces = face_cascade.detectMultiScale(image, 1.1, 2, minSize=(100,100))
        for (x, y, w, h) in faces:
            face_imgs.append(image[y:y+h, x:x+w])
            
            labels.append(os.path.split(img_folder)[1])
            # 此处有点不合理,本数据集中每张图片只有一个人脸,故而可以用这个方式,
            # 如果有多个不同人的脸,则不能用折冲方式。
    # 将labels转换为数字
    label_encoder=LabelEncoder()
    encode_labels=label_encoder.fit_transform(labels)
    return face_imgs, encode_labels, label_encoder,labels

Проверьте, работает ли вышеуказанная функция, и отобразите загруженную фотографию лица.

# 测试上面函数是否正常
face_cascade=cv2.CascadeClassifier('E:\PyProjects\DataSet\FireAI\cascade_files/haarcascade_frontalface_alt.xml')
face_imgs, labels, label_encoder,labels=load_train_set('E:\PyProjects\/DataSet\FireAI\/faces_dataset/train',face_cascade)
print(len(face_imgs)) # 有53张脸,但是检测得到56个结果,显然有几张图片中检测了多张脸
# 显示任一张人脸
# 由于cv2读取的是BGR,而plt是RGB,故而需要转化一下
plt.imshow(face_imgs[3],cmap='gray')

Из распечатанного результата видно, что есть еще три картинки, а значит есть три картинки, которые не являются фотографиями лица вперемешку, поэтому ее нужно найти и удалить. Определите функцию для поиска неправильного изображения

def find_false_faces(face_imgs):
    '''
    将所有脸部照片显示出来,如果发现有错误的,按d键,记录下错误的脸部照片
    '''
    need_del_ids=[]
    for idx,face in enumerate(face_imgs):
        cv2.namedWindow('check', cv2.WINDOW_NORMAL)
        cv2.resizeWindow('check', 500, 500)
        cv2.imshow('check', face)
        key = cv2.waitKey(0)

        if key==27: # 如果输入时Esc,则退出循环
            print('esc to exit')
            break
        elif key==100: # 如果输入d键,则记录该脸对应的id
            need_del_ids.append(idx)
    cv2.destroyAllWindows()
    print('finished...')
    return need_del_ids

Следовательно, необходимо удалить эти три изображения и соответствующую информацию о метках из исходного набора данных.

# 从数据集中删除这三张照片对应的信息
face_imgs=np.delete(np.array(face_imgs), need_del_ids, axis=0)
encode_labels=np.delete(np.array(encode_labels), need_del_ids, axis=0)
labels=np.delete(np.array(labels), need_del_ids,axis=0)
print(face_imgs.shape) # 53张图没错,元素已经变成了np.ndarray,故而只有行

3. Создание распознавателя гистограмм LBP

Распознаватель гистограммы LBP здесь эквивалентен модели классификации, cv2 уже упаковал для нас эту модель классификации, и нам нужно только вызвать ее.

# 构建createLBPHFaceRecognizer分类模型
from cv2.face import LBPHFaceRecognizer_create
recognizer=LBPHFaceRecognizer_create()
recognizer.train(face_imgs, encode_labels) # 模型训练

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

# 用训练好的模型预测新照片
def predict_imgs(new_imgs_folder, face_cascade,recognizer,label_encoder):
    '''
    用训练好的人脸识别器来识别人脸'''
    img_paths=glob(new_imgs_folder+'/*.*')
    predicted_imgs=[]
    for img_path in img_paths:
        image=cv2.imread(img_path)
        gray=cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
        faces=face_cascade.detectMultiScale(gray,1.1, 2, minSize=(100,100))
        for (x, y, w, h) in faces:
            cv2.rectangle(image,(x,y),(x+w,y+h),(0,0,255),3)
            predicted_index, conf = recognizer.predict(gray[y:y+h, x:x+w])
            predicted_label=label_encoder.inverse_transform([predicted_index])[0]
            cv2.putText(image, predicted_label,(x,y-20), cv2.FONT_HERSHEY_SIMPLEX, 2, (0,0,255), 3)
        predicted_imgs.append(image)
    return predicted_imgs

Получены следующие результаты:

Конечно, этот распознаватель может распознавать только те лица, которые уже есть в обучающем изображении, и будет неточно предсказывать лица, которых нет в обучающем наборе. Например, попробуйте сфотографировать сестру Фэн, чтобы сделать предсказание.

Подсчитано, что эта фотография сестры Фэн похожа на Person3, поэтому эта модель предсказывает ее как Person3.

########################резюме########################## ######

1. Модель гистограммы LBP может быть быстро обучена и быстро распознана, и имеет широкий спектр приложений в области распознавания лиц.

#################################################################


Примечание. Эта часть кода была загружена в (мой гитхаб), добро пожаловать на скачивание.

Использованная литература:

1. Классические примеры машинного обучения Python, Пратик Джоши, перевод Тао Цзюньцзе и Чена Сяоли.