使用OpenCV工具包成功实现人脸检测与人脸识别,包括传统视觉和深度学习方法(附完整代码,吐血整理......)

2023-11-14

OpenCV实现人脸检测

要实现人脸识别功能,首先要进行人脸检测,判断出图片中人脸的位置,才能进行下一步的操作。

参考链接:
1、OpenCV人脸检测
2、【OpenCV-Python】32.OpenCV的人脸检测和识别——人脸检测
3、【youcans 的图像处理学习课】23. 人脸检测:Haar 级联检测器
4、OpenCV实战5:LBP级联分类器实现人脸检测
5、计算机视觉OpenCv学习系列:第十部分、实时人脸检测

OpenCV人脸检测方法

在OpenCV中主要使用了两种特征(即两种方法)进行人脸检测,Haar特征和LBP特征。用的最多的是Haar特征人脸检测,此外OpenCV中还集成了深度学习方法来实现人脸检测。

基于Haar特征的人脸检测

Haar级联检测器预训练模型下载

在OpenCV中,使用已经训练好的XML格式的分类器进行人脸检测。在OpenCV的安装目录下的sources文件夹里的data文件夹里或者在github上下载opencv源代码,在源代码的data文件夹里都可以找到模型文件:
https://github.com/opencv/opencv/tree/4.x/data

haarcascade_eye.xml, 眼睛
haarcascade_eye_tree_eyeglasses.xml, 戴眼镜的眼睛
haarcascade_frontalcatface.xml, 正面猫脸
haarcascade_frontalcatface_extended.xml, 正面猫脸
haarcascade_frontalface_alt.xml, 正面人脸
haarcascade_frontalface_alt2.xml, 正面人脸
haarcascade_frontalface_alt_tree.xml, 正面人脸
haarcascade_frontalface_default.xml, 正面人脸
haarcascade_fullbody.xml, 人体
haarcascade_lefteye_2splits.xml, 左眼
haarcascade_license_plate_rus_16stages.xml,
haarcascade_lowerbody.xml,
haarcascade_profileface.xml,
haarcascade_righteye_2splits.xml, 右眼
haarcascade_russian_plate_number.xml,
haarcascade_smile.xml, 笑脸
haarcascade_upperbody.xml, 上身

Haar 级联分类器

基于 Haar 特征的级联分类器是 Paul Viola 在论文”Rapid Object Detection using a Boosted Cascade of Simple Features”中提出的一种目标检测方法。

Haar 级联分类器在每一级的节点中,使用 AdaBoost 算法学习一个高检测率低拒绝率的多层分类器。其特点是:

  • 使用 Haar-like 输入特征,对矩形图像区域的和或者差进行阈值化。
  • 使用积分图像计算 45°旋转区域的像素和,加速 Haar-like 输入特征的计算。
  • 使用统计 Boosting 来创建二分类(人脸/非人脸)的分类器节点(高通过率,低拒绝率)。
  • 将弱分类器并联组合起来,构成筛选式级联分类器。
    Haar级联分类器

各级的 Boosting 分类器对于有人脸的检测窗口都能通过,同时拒绝一小部分非人脸的检测窗口,并将通过的检测窗口传给下一个分类器。依次类推,最后一个分类器将几乎所有非人脸的检测窗口都拒绝掉,只剩下有人脸的检测窗口。因此,只要检测窗口区域通过了所有各级 Boosting 分类器,则认为检测窗口中有人脸。

在实际应用中输入图片的尺寸较大,需要进行多区域、多尺度的检测。多区域是要遍历图片的不同位置,多尺度是为了检测图片中不同大小的人脸。
在 Haar 级联分类人脸检测器中,主要利用了人脸的结构化特征:
1)与脸颊相比,眼部颜色较深
2)与眼睛相比,鼻梁区域较为明亮
3)眼睛、嘴巴、鼻子的位置较为固定
通过这 5 个矩形区域的明暗关系,就可以形成对人脸的各个部分的判别特征。例如在下图中,第一个特征检测眼部和上脸颊之间的强度差异,第二个特征检测双眼的间距。
在这里插入图片描述
Haar 人脸检测正脸检测识别率很高,但对侧脸的检测性能较差。

OpenCV-Python实现

使用 Haar 级联检测器检测图片中的人脸的步骤:

(1)创建一个 CascadeClassifier 级联分类器对象,从 .xml 文件加载级联分类器模型。
(2)读取待检测的图片。
(3)使用 detectMultiScale() 方法检测图片,返回检测到的面部或眼睛的边界矩形。
(4)将检测到的边界矩形绘制到检测图片上。
OpenCV 中定义了级联分类器类 cv::CascadeClassifier。在 Python 语言中,使用接口函数 cv2.CascadeClassifier() 从文件创建分类器。成员函数 cv.CascadeClassifier.detectMultiScale() 用于执行对图像进行目标检测。

import cv2
cv2.CascadeClassifier.detectMultiScale(image[, scaleFactor=1.1, minNeighbors=3, flags=0, minSize=Size(), maxSize=Size()]) → objects

参数说明:

  • filename:加载分类器模型的文件路径和名称,字符串。加载的级联分类器模型文件,扩展名为 .xml。
  • image:待检测的输入图像,CV_8U 格式。
  • scaleFactor:搜索窗口的缩放比例,默认值为1.1。
  • minNeighbors:表示构成检测目标的相邻矩形的最小个数,默认值为 3。
  • flags:版本兼容标志,默认值为 0。
  • minSize:检测目标的最小尺寸,元组 (h,w)。
  • maxSize:检测目标的最大尺寸,元组 (h,w)。

返回值

  • objects:返回值,检测目标的矩形边界框 ,是形如 (N,4) 的Numpy数组。每行有 4个元素 (x, y, width, height) 表示矩形框的左上顶点坐标 (x,y) 和宽度 width、高度 height。

使用Haar 级联检测器检测图片中的人脸:

import numpy as np
import cv2 as cv

if __name__ == '__main__':
    # (6) 使用 Haar 级联分类器 预训练模型 检测人脸
    # 读取待检测的图片
    img = cv.imread("../data/single.jpg")
    print(img.shape)

    # 加载 Haar 级联分类器 预训练模型
    model_path = "../data/haarcascade_frontalface_alt2.xml"
    face_detector = cv.CascadeClassifier(model_path)  # <class 'cv2.CascadeClassifier'>
    # 使用级联分类器检测人脸
    faces = face_detector.detectMultiScale(img, scaleFactor=1.1, minNeighbors=1,
                                           minSize=(30, 30), maxSize=(300, 300))
    print(faces.shape)  # (17, 4)
    print(faces[0])  # (x, y, width, height)

    # 绘制人脸检测框
    for x, y, width, height in faces:
        cv.rectangle(img, (x, y), (x + width, y + height), (0, 0, 255), 2, cv.LINE_8, 0)
    # 显示图片
    cv.imshow("faces", img)
    cv.waitKey(0)
    cv.destroyAllWindows()

单个人脸检测
使用Haar 级联检测器检测图片中的人眼:
人眼检测的方法与人脸检测方法相同,只是使用了不同的预训练模型,例如 haarcascade_eye.xml。
由于眼睛比人脸的尺寸小,因此减小了检测函数 detectMultiScale() 的参数 minSize=(20, 20)。
此外scaleFactor和minNeighbors也会影响到检测出的人眼个数。

import cv2 as cv

if __name__ == '__main__':
    # (7) 使用 Haar 级联分类器 预训练模型 检测人眼
    # 读取待检测的图片
    img = cv.imread("./data/single.jpg")
    print(img.shape)

    # 加载 Haar 级联分类器 预训练模型
    model_path = "./data/haarcascade_eye.xml"
    eye_detector = cv.CascadeClassifier(model_path)  # <class 'cv2.CascadeClassifier'>
    # 使用级联分类器检测人脸
    eyes = eye_detector.detectMultiScale(img, scaleFactor=1.1, minNeighbors=10,
                                           minSize=(10, 10), maxSize=(80, 80))
    # 绘制人脸检测框
    for x, y, width, height in eyes:
        cv.rectangle(img, (x, y), (x + width, y + height), (0, 0, 255), 2, cv.LINE_8, 0)
    # 显示图片
    cv.imshow("Haar_Cascade", img)
    # cv.imwrite("../images/imgSave3.png", img)
    cv.waitKey(0)
    cv.destroyAllWindows()

单个人脸人眼检测
scaleFactor=1.1, minNeighbors=10
单个人脸人眼检测
scaleFactor=1.1, minNeighbors=5

使用 Haar 级联检测器同时检测人脸和人眼
为了提高检测效率,可以先检测人脸,再在人类窗口内检测人眼,不仅可以提高检测效率,而且可以提高检测精度。

import cv2 as cv

if __name__ == '__main__':
    # (8) 使用 Haar 级联分类器 预训练模型 检测人脸和人眼
    # 读取待检测的图片
    img = cv.imread("./data/multiface1.jpeg")
    print(img.shape)

    # 加载 Haar 级联分类器 预训练模型
    face_path = "./data/haarcascade_frontalface_alt2.xml"  # 人脸检测器
    face_detector = cv.CascadeClassifier(face_path)  # <class 'cv2.CascadeClassifier'>
    eye_path = "./data/haarcascade_eye.xml"  # 人眼检测器
    eye_detector = cv.CascadeClassifier(eye_path)  # <class 'cv2.CascadeClassifier'>
    # 使用级联分类器检测人脸
    faces = face_detector.detectMultiScale(img, scaleFactor=1.1, minNeighbors=5,
                                           minSize=(30, 30), maxSize=(300, 300))
    print(faces.shape)  # (15, 4)

    # 绘制人脸检测框
    for x, y, width, height in faces:
        cv.rectangle(img, (x, y), (x + width, y + height), (0, 0, 255), 2, cv.LINE_8, 0)
        # 在人脸区域内检测人眼
        roi = img[y:y + height, x:x + width]  # 提取人脸
        # 检测人眼
        eyes = eye_detector.detectMultiScale(roi, scaleFactor=1.1, minNeighbors=1,
                                             minSize=(2, 2), maxSize=(80, 80))
        # 绘制人眼
        for ex, ey, ew, eh in eyes:
            cv.rectangle(img, (x+ex, y+ey), (x+ex+ew, y+ey+eh), (255, 0, 0), 2)

    # 显示图片
    cv.imshow("Haar_Cascade", img)
    # cv.imwrite("../images/imgSave4.png", img)
    cv.waitKey(0)
    cv.destroyAllWindows()


可以看到对于比较正常的人脸检测效果还是不错的(需要手动调整detectMultiScale()方法的参数),但是对于侧脸、歪脸、小脸的检测效果就不太理想了,而且对于眼睛的检测只能画框,不能实现关键点检测,现在在考虑利用这个人眼检测转换成关键点来做人脸对齐,后面再看看效果。

基于深度学习的人脸检测

OpenCV的深度神经网络(Deep Neural Network,DNN)模块提供了基于深度学习的人脸检测器。DNN模块中使用了广受欢迎的深度学习框架,包括Caffe、TensorFlow、Torch和Darknet等。
OpenCV提供了两个预训练的人脸检测模型:Caffe和TensorFlow模型。
Caffe模型需要加载以下两个文件:

  • deploy.prototxt:定义模型结构的配置文件
  • res10_300x300_ssd_iter_140000_fp16.caffemodel:包含实际层权重的训练模型文件

TensorFlow模型需要加载以下两个文件:

  • opencv_face_detector_uint8.pb:定义模型结构的配置文件
  • opencv_face_detector.pbtxt:包含实际层权重的训练模型文件

在OpenCV源代码的“\samples\dnn\face_detector”的文件夹中提供了模型配置文件,但未提供模型训练文件。可运行该文件夹中的download_models.py文件下载上述两个训练模型文件。或直接在官方链接https://github.com/spmallick/learnopencv/find/master(这个链接太难下了)下载,在这个链接下载:OpenCV学堂/OpenCV课程资料https://gitee.com/opencv_ai/opencv_tutorial_data(关键时刻靠Gitee)
(在搜索框中输入Age进行搜索,不然找不到)  在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

使用预训练的模型执行人脸检测时主要包含下列步骤:
(1) 调用cv2.dnn.readNetFromCaffe()或cv2.dnn.readNetFromTensorflow()函数加载模型,创建检测器。
(2) 调用cv2.dnn.blobFromImage()函数将待检测图像转换为图像块数据。
(3) 调用检测器的setInput()方法将图像块数据设置为模型的输入数据。
(4) 调用检测器的forward()方法执行计算,获得预测结果。
(5) 将可信度高于指定值的预测结果作为检测结果,在原图中标注人脸,同时输出可信度作为参考。

单张图片检测

# 基于深度学习的人脸检测(脸-眼_视频)
import cv2
import numpy as np


# dnnnet = cv2.dnn.readNetFromCaffe("deploy.prototxt", "res10_300x300_ssd_iter_140000_fp16.caffemodel")
dnnnet = cv2.dnn.readNetFromTensorflow("./data/opencv_face_detector_uint8.pb", "./data/opencv_face_detector.pbtxt")

img = cv2.imread("./data/multiface1.jpeg")
h, w = img.shape[:2]
blobs = cv2.dnn.blobFromImage(img, 1.0, (300, 300), [104., 117., 123.], False, False)
dnnnet.setInput(blobs)
detections = dnnnet.forward()
faces = 0
for i in range(0, detections.shape[2]):
    confidence = detections[0, 0, i, 2]
    if confidence > 0.6:               
        faces += 1
        box = detections[0, 0, i, 3:7] * np.array([w, h, w, h])
        x1,y1,x2,y2 = box.astype("int")
        y = y1 - 10 if y1 - 10 > 10 else y1 + 10
        text = "%.3f"%(confidence * 100)+'%'
        cv2.rectangle(img, (x1, y1), (x2, y2), (255, 0, 0), 2)
        cv2.putText(img,text, (x1, y), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 255), 1)
cv2.imshow('faces',img)
cv2.waitKey(0)
cv2.destroyAllWindows()

在这里插入图片描述
相比之下,还是深度学习模型的效果更胜一筹。

视频检测

import cv2
import numpy as np


# win7系统在代码中所有的cv2.VideoCapture要加cv2.CAP_DSHOW,不然会报错
capture = cv2.VideoCapture(0, cv2.CAP_DSHOW) 
frame_width = capture.get(cv2.CAP_PROP_FRAME_WIDTH)
frame_height = capture.get(cv2.CAP_PROP_FRAME_HEIGHT)
fps = capture.get(cv2.CAP_PROP_FPS)

dnnnet = cv2.dnn.readNetFromTensorflow("./data/opencv_face_detector_uint8.pb", "./data/opencv_face_detector.pbtxt")

if capture.isOpened() is False:
    print('CAMERA ERROR !')
    exit(0)

while capture.isOpened():

    ret, frame = capture.read()

    if ret is True:

        # cv2.imshow('FRAME', frame)  # 显示捕获的帧

        h, w = frame.shape[:2]
        blobs = cv2.dnn.blobFromImage(frame, 1.0, (300, 300), [104., 117., 123.], False, False)
        dnnnet.setInput(blobs)
        detections = dnnnet.forward()
        faces = 0
        for i in range(0, detections.shape[2]):
            confidence = detections[0, 0, i, 2]
            if confidence > 0.6:
                faces += 1
                box = detections[0, 0, i, 3:7] * np.array([w, h, w, h])
                x1, y1, x2, y2 = box.astype("int")
                y = y1 - 10 if y1 - 10 > 10 else y1 + 10
                text = "%.3f" % (confidence * 100) + '%'
                cv2.rectangle(frame, (x1, y1), (x2, y2), (255, 0, 0), 2)
                cv2.putText(frame, text, (x1, y), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 255), 1)

        cv2.imshow('faces', frame)
        k = cv2.waitKey(1)
        if k == ord('q'):
            break
    else:
        break
capture.release()
cv2.destroyAllWindows()


把手机放在摄像头前进行检测,可以看到有些人脸还是检测不出来,后面可以考虑加入活体检测。

传统视觉方法与深度学习方法对比

针对同一段视频文件,速度与检测总数统计比较
在这里插入图片描述

OpenCV实现人脸识别

参考链接:
1、opencv的人脸面部识别(主要代码参考)
2、【OpenCV-Python】33.OpenCV的人脸检测和识别——人脸识别
自己根据博主的代码做了适当的修改,符合自己项目的要求

OpenCV 有三种人脸识别的算法:

特征脸(Eigenfaces)人脸识别 是通过 PCA(主成分分析)实现的,它识别人脸数据集的主成分,并计算出待识别图像区域相对于数据集的发散程度(0-20k),该值越小,表示差别越小,0值代表完全匹配。低于4k-5k都是相当可靠的识别。
EigenFaces人脸识别的基本步骤如下:
(1) 调用cv2.face.EigenFaceRecognizer_create()方法创建EigenFace识别器。
(2) 调用识别器的train()方法以便使用已知图像训练模型。
(3) 调用识别器的predict()方法以便使用未知图像进行识别,确认其身份。
cv2.face.EigenFaceRecognizer_create()函数的基本格式如下:

recognizer = cv2.face.EigenFaceRecognizer_create([num_components[, threshold]])

# recognizer为返回的EigenFaces识别器对象
# num_components为分析时的分量数量, 默认为0, 表示根据实际输入决定
# threshold为人脸识别时采用的阈值

EigenFaces识别器的train()方法的基本格式如下:

recognizer.train(src, label)

# src为用于训练的已知图像数组, 所有图像必须为灰度图且大小要相同
# label为标签数组, 与已知图像数组中的人脸一一对应, 同一个人的人脸标签应设置为相同值

EigenFaces识别器的predict()方法的基本格式如下:

label, confidence = recoginer.predict(testimg)

# label为返回的标签值
# confidence为返回的可信度, 表示未知人脸和模型中已知人脸之间的距离, 0表示完全匹配, 低于5000可认为是可靠的匹配结果
# test_img为未知人脸图像, 图像必须为灰度图且大小要与训练图像相同

人鱼脸(FisherFaces)人脸识别 是从 PCA发展而来,使用线性判别分析(Linear Discriminant Analysis,LDA)方法实现人脸识别,采用更复杂的计算,容易得到更准确的结果。低于4k~5k都是相当可靠的识别。
FisherFaces人脸识别的基本步骤如下:
(1) 调用cv2.face.FisherFaceRecognizer_create()方法创建FisherFaces识别器。
(2) 调用识别器的train()方法以便使用已知图像训练模型。
(3) 调用识别器的predict()方法以便使用未知图像进行识别,确认其身份。
在OpenCV中,cv2.face.EigenFaceRecognizer类和cv2.face.FisherFaceRecognizer类同属于cv2.face.BasicFaceRecognizer类、cv2.face.FaceRecognizer类和cv2.Algorithm类的子类,对应的xxx_create()、train()和predict()等方法的基本格式与用法相同。

局部二进制编码直方图(Local Binary Patterns Histograms,LBPH)人脸识别 将人脸分成小单元,并将其与模型中的对应单元进行比较,对每个区域的匹配值产生一个直方图。它允许待检测人脸区域可以和数据集中图像的形状、大小不同,更方便灵活。参考值低于50则算是好的识别,高于80则认为比较差。
LBPH算法处理图像的基本原理如下:
(1) 取像素x周围(领域)的8个像素与其比较,像素值比像素x大的取0,否则取1。将8个像素对应的0、1连接得到一个8位二进制数,将其转换为十进制,作为像素x的LBP值。
(2) 对像素的所有像素按相同的方法进行处理,得到整个图像的LBP值,该图像的直方图就是图像的LBPH。
LBPH人脸识别的基本步骤如下;
(1) 调用cv2.face.LBPHFaceRecognizer_create()方法创建LBPH识别器。
(2) 调用识别器的train()方法以便使用已知图像训练模型。
(3) 调用识别器的predict()方法以便使用未知图像进行识别,确认其身份。

cv2.face.LBPHFaceRecognizer_create()函数的基本格式如下:

recognizer = cv2.face.LBPHFaceRecognizer_create([radius[, neighbors[, grid_x[, grid_y[, threshold]]]]])

# recognizer为返回的LBPH识别器对象
# radius为邻域的半径大小
# neighbors为邻域内像素点的数量, 默认为8
# grid_x为将LBP图像划分为多个单元格时, 水平方向上的单元格数量, 默认为8
# grid_y为将LBP图像划分为多个单元格时, 垂直方向上的单元格数量, 默认为8
# threshold为人脸识别时采用的阈值

LBPH识别器的train()方法的基本格式如下:

recognizer.train(src, label)

# src为用于训练的已知图像数组, 所有图像必须为灰度图且大小要相同
# label为标签数组, 与已知图像数组中的人脸一一对应, 同一个人的人脸标签应设置为相同值

LBPH识别器的predict()方法的基本格式如下:

label, confidence = recoginer.predict(testimg)

# label为返回的标签值
# confidence为返回的可信度, 表示未知人脸和模型中已知人脸之间的距离, 0表示完全匹配, 低于50可认为是非常可靠的匹配结果
# test_img为未知人脸图像, 图像必须为灰度图且大小要与训练图像相同

制作数据集

不管使用哪种算法都需要有训练集。从视频或者动图创建训练集的效率比较高。可以从网上下载或者自己写一个摄像头捕获程序进行采集。本次实验直接从网上下载了一些明星的动图,然后将动图按帧分解,使用OpenCV中的Haar级联器检测人脸区域,然后将人脸区域全部存为200X200的灰度图,存入对应的文件夹中,创建训练集。

from PIL import Image
import os
import cv2
import numpy as np

# GIF动图转图片
def gifSplit2Array(gif_path):
    import numpy as np
    img = Image.open(os.path.join(path, gif_path))
    for i in range(img.n_frames):
        img.seek(i)
        new = Image.new("RGBA", img.size)
        new.paste(img)
        arr = np.array(new).astype(np.uint8)  # image: img (PIL Image):
        yield arr[:, :, 2::-1]  # 逆序(RGB 转BGR), 舍弃alpha通道, 输出数组供openCV使用


# 人脸检测
def face_generate(img):
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

    front_face_cascade = cv2.CascadeClassifier('./data/haarcascade_frontalface_alt2.xml')  # 检测正脸
    faces0 = front_face_cascade.detectMultiScale(gray, 1.02, 5)
    eye_cascade = cv2.CascadeClassifier('./data/haarcascade_eye_tree_eyeglasses.xml')  # 检测眼睛
    if faces0 is not None:
        for (x, y, w, h) in faces0:
            face_area = gray[y: y + h, x: x + w]  # (疑似)人脸区域
            quasi_eyes = eye_cascade.detectMultiScale(face_area, 1.03, 5, 0)  # 在人脸区域检测眼睛
            if len(quasi_eyes) == 0: continue
            quasi_eyes = tuple(
                filter(lambda x: x[2] / w > 0.18 and x[1] < 0.5 * h, quasi_eyes))  # ex,ey,ew,eh; ew/w>0.18,尺寸过滤 ,且眼睛在脸的上半部
            if len(quasi_eyes) <= 1: continue
            yield cv2.resize(face_area, (200, 200))


# 制作数据集
def get_dataset(path, gif_list):
    i = 0
    all_items = os.listdir(path)
    print(all_items)
    for item in all_items:
        name = item.split('-')[0]
        name_path = os.path.join(path, name)
        if not os.path.exists(name_path):
            os.mkdir(name_path)

    for gif in gif_list:
        print(gif)
        for img in gifSplit2Array(gif):
            for face in face_generate(img):
                cv2.imwrite("./dataset/%s/%s.pgm" % (gif.split('-')[0], i), face)
                # print(i)
                i += 1



if __name__ == '__main__':
    path = './dataset'
    gif_list = ["Yangmi-1.gif", "Yangmi-2.gif", "Yangmi-3.gif", "Liushishi-1.gif", "Liushishi-2.gif", "Liushishi-3.gif"]
    get_dataset(path, gif_list)

处理结果

加载数据集

将所有数据放在一个ndarray数组中

def load_dataset(datasetPath):
    names = []
    X = []
    y = []
    ID = 0
    for name in os.listdir(datasetPath):
        subpath = os.path.join(datasetPath, name)
        if os.path.isdir(subpath):
            names.append(name)
            for file in os.listdir(subpath):
                im = cv2.imread(os.path.join(subpath, file), cv2.IMREAD_GRAYSCALE)
                X.append(np.asarray(im, dtype=np.uint8))
                y.append(ID)
            ID += 1
    X = np.asarray(X)
    y = np.asarray(y, dtype=np.int32)
    return X, y, names

训练数据集

X, y, names = load_dataset(path)
# 报错找不到face模块是因为只安装了主模块
# pip uninstall opencv-python,   pip install opencv0-contrib-python
# 创建人脸识别模型(三种识别模式)
# model = cv2.face.EigenFaceRecognizer_create() #createEigenFaceRecognizer()函数已被舍弃
# model = cv2.face.FisherFaceRecognizer_create()
model = cv2.face.LBPHFaceRecognizer_create()
model.train(X, y)

单张图片测试

注意:将face_generate()函数最后一行改为

yield cv2.resize(face_area, (200, 200)), x, y, w, h

开始进行测试

    path = './dataset'
    infer_path = './data/Yangmi.jpeg'
    # gif_list = ["Yangmi-1.gif", "Yangmi-2.gif", "Yangmi-3.gif", "Liushishi-1.gif", "Liushishi-2.gif", "Liushishi-3.gif"]
    # get_dataset(path, gif_list)
    X, y, names = load_dataset(path)
    # 报错找不到face模块是因为只安装了主模块
    # pip uninstall opencv-python,   pip install opencv0-contrib-python
    # 创建人脸识别模型(三种识别模式)
    # model = cv2.face.EigenFaceRecognizer_create() #createEigenFaceRecognizer()函数已被舍弃
    # model = cv2.face.FisherFaceRecognizer_create()
    model = cv2.face.LBPHFaceRecognizer_create()
    model.train(X, y)
    img = cv2.imread(infer_path)
    for roi, x, y, w, h in face_generate(img):
        cv2.rectangle(img, (x, y), (x + w, y + h), (0, 0, 255), 2)  # 画红色矩形框标记正脸
        ID_predict, confidence = model.predict(roi)  # 预测!!!
        name = names[ID_predict]
        print("name:%s, confidence:%.2f" % (name, confidence))
        text = name if confidence < 70 else "unknow"  # 10000 for EigenFaces #70 for LBPH
        cv2.putText(img, text, (x, y - 20), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2)  # 绘制绿色文字

    cv2.imshow('', img)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

测试效果:
杨幂人脸检测与识别效果

补充: 这个实现方法完全使用opencv中的自带方法,目前只是进行了单张图片的识别,并且数据集比较小,在实际的环境中识别效果有待验证,并且没有加入自己写的人脸对齐程序,后面希望能结合进去,提高识别效果

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用OpenCV工具包成功实现人脸检测与人脸识别,包括传统视觉和深度学习方法(附完整代码,吐血整理......) 的相关文章

  • OpenCV 错误:使用 COLOR_BGR2GRAY 函数时断言失败

    我在使用 opencv 时遇到了一个奇怪的问题 我在 jupyter 笔记本中工作时没有任何问题 但在尝试运行此 Sublime 时却出现问题 错误是 OpenCV错误 cvtColor中断言失败 深度 CV 8U 深度 CV 16U 深度
  • 来自连接到远程机器的相机的 Opencv 流

    我正在用 python 开发一个 wx 应用程序 用于流式传输和显示来自两个不同网络摄像头的视频 这工作正常 但现在我需要在不同的场景中执行此操作 其中两个摄像头连接在通过网络连接的 Windows 上运行的单独计算机中 我的应用程序将在机
  • OpenCV Visual Studio ntdll.dll

    我尝试在 Visual Studio 2013 上使用 OpenCV 2 4 10 创建一个项目 但由于以下异常 到目前为止我运气不佳 请建议帮助 TIA letstryitonemoretime exe Win32 Loaded C Us
  • 为什么我无法在 Mac 12.0.1 (Monterey) 上使用 pip 安装 OpenCV? [复制]

    这个问题在这里已经有答案了 当我尝试使用 python pip 安装 OpenCV 时 它显示了以下内容 Remainder of file ignored Requirement already satisfied pip in Libr
  • OpenCV 2.4.3 中的阴影去除

    我正在使用 OpenCV 2 4 3 最新版本 使用内置的视频流检测前景GMG http docs opencv org modules gpu doc video html highlight gmg gpu 3a 3aGMG GPU算法
  • 使用 OpenCV 和/或 Numpy 对两个图像进行 Alpha 混合 [重复]

    这个问题在这里已经有答案了 我想将一个填充纯色的半透明矩形添加到已加载的半透明 PNG 中 这是我正在使用的输入图像示例 该图像加载了标准cv2 IMREAD UNCHANGED标志 以便完美保留 alpha 通道 该输入图像存储在imag
  • iOS 上的 OpenCV - VideoCapture 属性始终返回 1

    我一直在尝试构建一个简单的 OpenCV iOS 应用程序 该应用程序从捆绑包中加载视频并查询其帧数 持续时间等 然后它将尝试从中获取各个帧 不幸的是 当我使用VideoCapture类中 所有属性返回值 1 然后我尝试导航到frame 1
  • 同时从多个流中捕获、最佳方法以及如何减少 CPU 使用率

    我目前正在编写一个应用程序 该应用程序将捕获大量 RTSP 流 在我的例子中为 12 个 并将其显示在 QT 小部件上 当我超过大约 6 7 个流时 问题就会出现 CPU 使用率激增并且出现明显的卡顿 我认为它不是 QT 绘制函数的原因是因
  • OpenCV Mat 和 Leptonica Pix 之间的转换

    我需要在 C 中在 OpenCV Mat 图像和 Leptonica Pix 图像格式之间进行转换 这用于 8 位灰度图像的二值化 我发现发现了 ikaliga的回答 https stackoverflow com a 25929320 2
  • 是否可以在 PyScript 中使用 OpenCV 模块?

    我想使用 opencv 模块 但无法导入 OpenCV 那么我该如何解决这个问题呢 顺便说一句 Pyodide 支持 OpenCV 示例代码 https i stack imgur com ahwex jpg 尚不支持 OpenCV 此时O
  • OpenCV:如何从网络摄像头获取原始 YUY2 图像?

    你知道如何获得吗raw YUY2来自网络摄像头的图像 使用 OpenCV DirectShow 无 VFW http opencv willowgarage com wiki CameraCapture http opencv willow
  • VideoCapture.read() 返回过去的图像

    我在跑python3 6 with openCV on the Raspberry pi OS is Raspbian 代码的大致结构如下 The image以时间间隔 3 5 分钟 捕获 被捕获image在函数中处理并返回度量 精度的种类
  • 图像梯度角计算

    我实际上是按照论文的说明进行操作的 输入应该是二进制 边缘 图像 输出应该是一个新图像 并根据论文中的说明进行了修改 我对指令的理解是 获取边缘图像的梯度图像并对其进行修改 并使用修改后的梯度创建一个新图像 因此 在 MATLAB Open
  • iphone opencv - 模板匹配

    我已经在我的 iphone 项目中实现了这个 OpenCV 构建 http aptogo co uk 2011 09 opencv framework for ios http aptogo co uk 2011 09 opencv fra
  • opencv水印周围的轮廓

    我想在图像中的水印周围画一个框 我已经提取了水印并找到了轮廓 但是 不会在水印周围绘制轮廓 轮廓是在我的整个图像上绘制的 请帮我提供正确的代码 轮廓坐标的输出为 array 0 0 0 634 450 634 450 0 dtype int
  • 从扫描文档中提取行表 opencv python

    我想从扫描的表中提取信息并将其存储为 csv 现在我的表提取算法执行以下步骤 应用倾斜校正 应用高斯滤波器进行去噪 使用 Otsu 阈值进行二值化 进行形态学开局 Canny 边缘检测 进行霍夫变换以获得表格行 去除重复行 10像素范围内相
  • 查找具有不同强度/亮度的相似图像

    假设我有如下图像 我可以选择什么来比较两个图像之间的相似度 显然它们是相同的图像 只是亮度不同 我找不到任何可行的方法 目前我最好的选择是训练 cnn 或自动编码器并比较输出的特征向量 但这似乎有点矫枉过正 任何提示将不胜感激 相当强大的工
  • 在骨架图像中查找线 OpenCV python

    我有以下图片 我想找到一些线来进行一些计算 平均长度等 我尝试使用HoughLinesP 但它找不到线 我能怎么做 这是我的代码 sk skeleton mask rows cols sk shape imgOut np zeros row
  • Opencv 2.4.2 代码讲解-人脸识别

    我参考OpenCV提供的文档制作了一个人脸识别程序 可以识别多个人脸 并且工作正常 在文档中 他们制作了省略号来突出显示脸部 我不明白的是他们如何计算椭圆的中心 他们的计算如下 for int i 0 i lt faces size i P
  • 使用 OpenCV 进行相机校准 - 如何调整棋盘方块大小?

    我正在使用 OpenCV Python 示例开发相机校准程序 来自 OpenCV 教程 http opencv python tutroals readthedocs io en latest py tutorials py calib3d

随机推荐

  • 搭建J2EE开发平台-Eclipse+MySql+tomcat

    开完J2EE视频之后自己从网上把需要用到的东西下载了下来 分享之 首先是Eclipse开发环境 我记得在马士兵的一个教程里讲的是用lomboz Eclipse 不过那个视频讲的是06年的事了 并且lomboz官网上最新的也只有2007年出的
  • 'str' object has no attribute 'name'

    imgName E AndroidWork Bird Identification App master Bird Identification Server mask rcnn master images cars jpg 出错版 arg
  • UME - 丰富的Flutter调试工具

    背景 目前西瓜视频作者侧 Flutter 业务场景已经覆盖了 40多个页面 包括视频播放场景 用户侧核心场景包括我的 Tab 也已经是 Flutter 在开发过程中 暴露了一些问题 debug 调试难 离开了 IDE 后犹如抓瞎 PM 设计
  • 十六、K8s安全管理与资源限制

    实验环境 按照图示部署好了K8s集群 一个Master 两个worker nodes 访问控制概述 apiserver作为k8s集群系统的网关 是访问及管理资源对象的唯一入口 余下所有需要访问集群资源的组件 包括kube controlle
  • C语言【求最大公约数、最小公倍数】详解

    题目 从键盘输入两个数字 并求出他们的最大公约数 解题思路 一 当我们看到题目时 首先思考求什么是最大公约数 什么 是最小公倍数 最大公约数 指两个或两个以上共有的约数中最大的那个 最小公倍数 指两个或两个以上共有的倍数中最小的那个 接下来
  • Firewalld防火墙转换成Iptables

    关闭及停止使用 firewalld systemctl mask firewalld systemctl stop firewalld 安装iptables yum install y iptables services 生效及iptabl
  • Java海龟画图turtle多彩螺旋线

    利用turtle画多彩螺旋线 思路 在画正多边形的基础上 步长不是一直相同 而是越来越长 并且角度比画正多边形需要的角度多一些 每次拐弯变换颜色 Size是螺旋的大小 Step的每一步的长度 每走一步拐弯一次 Densi是密度 角度越小 螺
  • 【C++11】 列表初始化 auto 范围for 新增关键字 新增容器

    文章目录 1 列表初始化 2 auto 范围for 3 新增关键字 3 1 decltype 3 2 default 3 3 delete 3 4 final与override 4 总结 1 列表初始化 由c语言的规则我们知道 一般只有数组
  • 【Linux】基础:线程的概念

    Linux 基础 线程的概念 摘要 本文介绍Linux下的线程概念 首先将会线程在系列教材中的定义进行抛出 从常规的操作系统进行理解线程的概念 在具体说明Linux下的进线程的管理与组织方式 以及由于该组织方式的差异 导致的接口和资源的特殊
  • C语言实现仿射密码体制

    算法思想 1 通过用户输入的加密函数的斜率和截距 a与b 可以利用a计算出a的逆源 在输入a之后 要判断a与26是否互素 即a值与26的最大公约数为1 代码中采用辗转相除法 如果不符合要求 请提示重新输入 求解a的逆源 例如7的逆源是15
  • Unity连接服务器实现用户登录注册

    仅个人记录 方便以后忘掉回来看看 服务器买的是腾讯云的 系统是 CentOS 管理工具用的是万胜云面板 好像也叫宝塔 数据库都是在这里面整的 用到的表提前在里面创建好了 using MySql Data MySqlClient using
  • 阿里云ECS服务器1核2G能跑centos8.2系统吗?

    可以的 LInux系统的优点就在这些方面的 他不会随着系统的升级 导致服务器的配置过低从而不够用等情况 简单说就是不会太费系统资源的 阿里云ecs服务器centos系统还是算比较轻量级的了 本身对系统资源的占用并不高的 但是如果你使用win
  • C++中public、protected、private的区别

    1 访问范围 private public protected的访问范围 private 只能由该类中的函数 其友元函数访问 不能被任何其他访问 该类的对象也不能访问 protected 可以被该类中的函数 子类的函数 以及其友元函数访问
  • js作用域链

    简单的理解什么是作用域链 一级一级向上查询所以父级对象的变量的这个过程就是作用域链 下面我们来详细了解一下 变量作用域 在js中 变量分为全局变量和局部变量 全局变量的作用域是全局的 在任意地方都是被定义的 而局部变量可以是函数的参数 函数
  • 【Flutter 2-5】Flutter手把手教程UI布局和Widget——TextField使用、搭配InputDecoration和FocusedNode使用

    作者 弗拉德 来源 弗拉德 公众号 fulade me TextField TextField是一个常用的控件 同时它也是一个组合控件 由多个控件组合而成 这是来自Material官方网站的的图片 TextField是由7个控件组成 其中有
  • el-table排序

    排序有三种状态 默认不排序 升序 降序 如果要改变设置默认状态 用 default sort prop controlStatus order ascending 设置排序字段 sort by sortControlStatusArr 可以
  • 第四章 KubeSphere3.3.0 + Redis7.0.4 + Redis-Cluster 集群部署

    第四章 KubeSphere3 3 0 Redis7 0 4 Redis Cluster 集群部署 文章目录 第四章 KubeSphere3 3 0 Redis7 0 4 Redis Cluster 集群部署 前言 一 创建redis存储卷
  • java使用Ucloud对象存储

    最近研究了Ucloud的对象存储 使用起来很简单 总结一下 1 配置UFile 官网上下载下来的SDK jar包和测试类都包含在其中 结合到项目中 有重复的jar包 要选一留下 不要都留 配置文档的配置 UCloudPublicKey HL
  • 【Android】Exam8 多线程

    文章目录 实验目的 题目 Code 实验目的 掌握采用Handler Thread编写多线程序 掌握AsyncTask编写多线程序的方法 题目 采用Handler Thread多线程方式编写程序一个模拟从网络下载文件的程序 点击 点击加载
  • 使用OpenCV工具包成功实现人脸检测与人脸识别,包括传统视觉和深度学习方法(附完整代码,吐血整理......)

    使用OpenCV工具包实现人脸检测与人脸识别 吐血整理 OpenCV实现人脸检测 OpenCV人脸检测方法 基于Haar特征的人脸检测 Haar级联检测器预训练模型下载 Haar 级联分类器 OpenCV Python实现 基于深度学习的人