Детальное распознавание лиц OpenCV (всего 2 строки кода, чтобы научиться распознавать лица)

искусственный интеллект Идентификация изображения
Детальное распознавание лиц OpenCV (всего 2 строки кода, чтобы научиться распознавать лица)

«Это 30-й день моего участия в ноябрьском испытании обновлений. Подробную информацию об этом событии см.:Вызов последнего обновления 2021 г."

Введение в распознавание лиц

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

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

Распознавание лиц с помощью OpenCV

OpenCVПредусмотрено два метода обнаружения лиц, в том числе:

  • Детектор лиц на основе каскада Хаара
  • Детектор лиц на основе глубокого обучения

Детектор лиц на основе каскада Хаара

OpenCVна основеViolaиJonesПредложен алгоритм обнаружения лиц, основанный на системе обнаружения объектов. Кроме того, фреймворк обнаружения объектов может также использоваться для обнаружения других объектов, таких как: номерные знаки или кошачьи морды и т. д. В этом разделе мы будем использовать эту структуру для обнаружения лиц.

OpenCVДля распознавания лиц предусмотрены 4 каскадных классификатора, которые можноОфициальный OpenCVЗагрузите эти файлы каскадного классификатора:

  • haarcascade_frontalface_alt.xml (FA1)
  • haarcascade_frontalface_alt2.xml (FA2)
  • haarcascade_frontalface_alt_tree.xml (FAT)
  • haarcascade_frontalface_default.xml (FD)

Производительность этих каскадных классификаторов можно оценить с использованием разных наборов данных, и в целом эти классификаторы имеют одинаковую точность, поэтому в дальнейшем для упрощения процедуры мы используем только два из них (точнее, только Загрузить каскадный классификатор).FA2иFD), вы также можете выбрать другие интересующие вас классификаторы, чтобы проверить их эффективность.OpenCVпри условииcv2.CascadeClassifier()Функция используется для загрузки классификатора из файла:

# 加载级联分类器
# 第一行代码
cas_alt2 = cv2.CascadeClassifier("haarcascade_frontalface_alt2.xml")
cas_default = cv2.CascadeClassifier("haarcascade_frontalface_default.xml")

Далее вы можете использоватьcv2.CascadeClassifier.detectMultiScale()Проверяется выполнение функции:

# 第二行代码,人脸检测就这么简单
faces_alt2 = cas_alt2.detectMultiScale(gray)
faces_default = cas_default.detectMultiScale(gray)

cv2.CascadeClassifier.detectMultiScale()Функция обнаруживает объекты и возвращает их в виде списка прямоугольников. Для визуализации, наконец, напишитеshow_detection()функция визуализации:

def show_detection(image, faces):
    """在每个检测到的人脸上绘制一个矩形进行标示"""
    for (x, y, w, h) in faces:
        cv2.rectangle(image, (x, y), (x + w, y + h), (255, 0, 0), 5)
    return image
# 调用 show_detection() 函数标示检测到的人脸
img_faces_alt2 = show_detection(img.copy(), faces_alt2)
img_faces_default = show_detection(img.copy(), faces_default)

Что, две строки кода все еще кажутся громоздкими, тогда пора вызывать детектор и определять лица одной строкой, этоOpenCVкоторый предоставилcv2.face.getFacesHAAR()функция:

# 一行代码实现基于 Haar 级联的人脸检测器,学一送一
retval, faces_haar_alt2 = cv2.face.getFacesHAAR(img, "haarcascade_frontalface_alt2.xml")
retval, faces_haar_default = cv2.face.getFacesHAAR(img, "haarcascade_frontalface_default.xml")

cv2.CascadeClassifier.detectMultiScale()требует изображения в градациях серого в качестве входных данных, в то время какcv2.face.getFacesHAAR()необходимостьBGRизображение в качестве входных данных. также,cv2.CascadeClassifier.detectMultiScale()Выведите обнаруженные лица в виде списка прямоугольников, например, если обнаружено два лица, вывод будет иметь вид:

[[809 494 152 152] [168 503 188 188]]

иcv2.face.getFacesHAAR()Функция возвращает обнаруженное лицо в следующем формате:

[[[ 809  493  151  151]] [[ 167  503  189  189]]]

Поэтому, если вы используетеcv2.face.getFacesHAAR()Функция обнаружения, вызываемая при отрисовке рамки обнаруженияnp.squeeze()Функция удаляет лишние размеры:

faces_haar_alt2 = np.squeeze(faces_haar_alt2)
faces_haar_default = np.squeeze(faces_haar_default)

Полный код от загрузки изображения до обнаружения и рисования лица выглядит следующим образом:

# 可视化函数
def show_img_with_matplotlib(color_img, title, pos):
    img_RGB = color_img[:, :, ::-1]
    ax = plt.subplot(2, 2, pos)
    plt.imshow(img_RGB)
    plt.title(title, fontsize=8)
    plt.axis('off')
    
# 加载图像
img = cv2.imread("test_face_detection.jpg")
# 将 BGR 图像转换为灰度图像
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 加载分类器
cas_alt2 = cv2.CascadeClassifier("haarcascade_frontalface_alt2.xml")
cas_default = cv2.CascadeClassifier("haarcascade_frontalface_default.xml")
# 检测人脸
faces_alt2 = cas_alt2.detectMultiScale(gray)
faces_default = cas_default.detectMultiScale(gray)
retval, faces_haar_alt2 = cv2.face.getFacesHAAR(img, "haarcascade_frontalface_alt2.xml")
faces_haar_alt2 = np.squeeze(faces_haar_alt2)
retval, faces_haar_default = cv2.face.getFacesHAAR(img, "haarcascade_frontalface_default.xml")
faces_haar_default = np.squeeze(faces_haar_default)
# 绘制人脸检测框
img_faces_alt2 = show_detection(img.copy(), faces_alt2)
img_faces_default = show_detection(img.copy(), faces_default)
img_faces_haar_alt2 = show_detection(img.copy(), faces_haar_alt2)
img_faces_haar_default = show_detection(img.copy(), faces_haar_default)
# 可视化
show_img_with_matplotlib(img_faces_alt2, "detectMultiScale(frontalface_alt2): " + str(len(faces_alt2)), 1)
show_img_with_matplotlib(img_faces_default, "detectMultiScale(frontalface_default): " + str(len(faces_default)), 2)
show_img_with_matplotlib(img_faces_haar_alt2, "getFacesHAAR(frontalface_alt2): " + str(len(faces_haar_alt2)), 3)
show_img_with_matplotlib(img_faces_haar_default, "getFacesHAAR(frontalface_default): " + str(len(faces_haar_default)), 4)
plt.show()

Вывод программы показан ниже:

基于 Haar 级联的人脸检测器

Как показано на рисунке выше, с помощьюhaarРазличные каскадные классификаторы признаков обнаруживают разные лица. Наконец, следует отметить, что,cv2.CascadeClassifier.detectMultiScale()функция имеетminSizeиmaxSizeпараметр для установки минимального размера (менееminSizeобъекты не будут обнаружены) и максимальный размер (больше чемmaxSizeобъекты не будут обнаружены), аcv2.face.getFacesHAAR()Функция не предоставляет этот параметр.

Детектор лиц на основе глубокого обучения

За исключением основанного наHaarВ дополнение к каскадным детекторам лиц OpenCV предоставляетДетектор лиц на основе глубокого обучения,OpenCVглубокая нейронная сеть (Deep Neural Networks, DNN) детектор лица на основе использованияResNet-10Сетевой однокадровый детектор MultiBox (SSD) Рамка.

OpenCVсерединаDNNмодулей с использованием популярных фреймворков глубокого обучения (например,Caffe,TensorFlow,TorchиDarknet) через предварительно обученную глубокую сеть для прямого вычисления (т. е. этап логического вывода). Это означает, что мы можем использовать предварительно обученную сеть для выполнения полного прямого вычисления и использовать выходные данные для прогнозирования в нашем приложении, не тратя часы на обучение сети.

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

  • Детектор лиц (FP16): версия реализации Caffe с плавающей запятой 16, чтобы использовать этот детектор, сначала загрузите файл модели (deploy.prototxt) и файлы конфигурации (res10_300x300_ssd_iter_140000_fp16.caffemodel);
  • Детектор лиц (UINT8): 8-битная квантованная версия реализации TensorFlow, чтобы использовать этот детектор, сначала загрузите файл модели (opencv_face_detector.pbtxt) и файлы конфигурации (opencv_face_detector_uint8.pb).

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

# 加载预训练的模型, Caffe 实现的版本
net = cv2.dnn.readNetFromCaffe("deploy.prototxt", "res10_300x300_ssd_iter_140000_fp16.caffemodel")
# 加载预训练的模型, Tensorflow 实现的版本
# net = cv2.dnn.readNetFromTensorflow("opencv_face_detector_uint8.pb", "opencv_face_detector.pbtxt")

Для большей точности синий, зеленый и красный каналы должны выполняться отдельно.(104, 177, 123)Канал означает вычитание и изменение размера изображения до изображения BGR 300 x 300, вOpenCVможно использовать с помощьюcv2.dnn.blobFromImage()функция для выполнения этой предварительной обработки:

blob = cv2.dnn.blobFromImage(image, 1.0, (300, 300), [104., 117., 123.], False, False)

Следующим шагом являетсяblobУстановите в качестве входных данных, чтобы получить результат, выполните прямые вычисления для всей сети, чтобы вычислить выходные данные:

# 将 blob 设置为输入并获取检测结果
net.setInput(blob)
detections = net.forward()

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

# 迭代所有检测结果
for i in range(0, detections.shape[2]):
    # 获取当前检测结果的置信度
    confidence = detections[0, 0, i, 2]
    # 如果置信大于最小置信度,则将其可视化
    if confidence > 0.7:
        detected_faces += 1
        # 获取当前检测结果的坐标
        box = detections[0, 0, i, 3:7] * np.array([w, h, w, h])
        (startX, startY, endX, endY) = box.astype('int')
        # 绘制检测结果和置信度
        text = "{:.3f}%".format(confidence * 100)
        y = startY -10 if startY - 10 > 10 else startY + 10
        cv2.rectangle(image, (startX, startY), (endX, endY), (255, 0, 0), 3)
        cv2.putText(image, text, (startX, y), cv2.FONT_HERSHEY_SIMPLEX, 0.9, (0, 0, 255), 2)

# 可视化
show_img_with_matplotlib(image, "DNN face detector: " + str(detected_faces), 1)
plt.show()

Результаты обнаружения детектора лиц на основе глубокого обучения следующие:

基于深度学习的人脸检测器

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