人脸检测、人脸跟踪、人脸识别、OpenCV(特征脸、LBPH、费歇脸)

日萌社

人工智能AI:Keras PyTorch MXNet TensorFlow PaddlePaddle 深度学习实战(不定时更新)


Face_Detection.py

# 导入OpenCV库
import cv2
#使用OpenCV2库提供的正面haar级联初始化面级联。这对于图像中的人脸检测是必需的。
faceCascade = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')
# 所需的输出宽度和高度,可根据需要修改。
OUTPUT_SIZE_WIDTH = 700
OUTPUT_SIZE_HEIGHT = 600

# 打开第一个网络摄像机设备
capture = cv2.VideoCapture(0)

# 创建两个名为windows窗口的opencv,用于显示输入、输出图像。
cv2.namedWindow("base-image", cv2.WINDOW_AUTOSIZE)
cv2.namedWindow("result-image", cv2.WINDOW_AUTOSIZE)

# 把windows窗口靠在一起
cv2.moveWindow("base-image", 20, 200)
cv2.moveWindow("result-image", 640, 200)

# 启动我们正在使用的两个windows窗口的windows窗口线程
cv2.startWindowThread()

#我们在脸周围画的矩形的颜色
rectangleColor = (0, 100, 255)

while(1):
    # 从网络摄像头中检索最新图像
    rc,fullSizeBaseImage = capture.read()
    # 将图像大小调整为520x420
    baseImage= cv2.resize(fullSizeBaseImage, (520, 420))

    # 检查是否按下了某个键,是否为Q或q,然后销毁所有opencv窗口并退出应用程序,停止无限循环。
    pressedKey = cv2.waitKey(2)
    if (pressedKey == ord('Q')) | (pressedKey == ord('q')):
        cv2.destroyAllWindows()
        exit(0)
    #结果图像是我们将向用户显示的图像,它是从网络摄像头捕获的原始图像与检测最大人脸的覆盖矩形的组合
    resultImage = baseImage.copy()

    # 我们将使用灰色图像进行人脸检测。
    # 所以我们需要把摄像头捕捉到的基本图像转换成基于灰度的图像
    gray_image = cv2.cvtColor(baseImage, cv2.COLOR_BGR2GRAY)
    faces = faceCascade.detectMultiScale(gray_image, 1.3, 5)
    # 由于我们只对“最大”面感兴趣,因此需要计算所找到矩形的最大面积。
    # 为此,首先将所需的变量初始化为0。
    maxArea = 0
    x = 0
    y = 0
    w = 0
    h = 0

    # 在图像中找到的所有面上循环,并检查此面的区域是否是迄今为止最大的
    for(_x, _y, _w, _h) in faces:
        if _w * _h > maxArea:
            x = _x
            y = _y
            w = _w
            h = _h
            maxArea = w * h
    # 如果找到任何面,请在图片中最大的面周围画一个矩形
    if maxArea > 0:
        cv2.rectangle(resultImage, (x-10, y-20),(x + w+10, y + h+20), rectangleColor, 2)

    #因为我们想在屏幕上显示比原来的520x420更大的东西,所以我们再次调整图像的大小
    #请注意,也可以保留基本图像的大版本,并使结果图像成为此大基本图像的副本,并使用缩放因子在右坐标处绘制矩形。
    largeResult = cv2.resize(resultImage,(OUTPUT_SIZE_WIDTH, OUTPUT_SIZE_HEIGHT))
    # 最后,我们在屏幕上显示图像
    cv2.imshow("base-image", baseImage)
    cv2.imshow("result-image", largeResult)
Face_Recognition.py

import os
import re
import warnings
import scipy.misc
import cv2
import face_recognition
from PIL import Image
import argparse
import csv
import os

parser = argparse.ArgumentParser()
parser.add_argument("-i", "--images_dir",help="image dir")
parser.add_argument("-v", "--video", help="video to recognize faces on")
parser.add_argument("-o", "--output_csv", help="Ouput csv file [Optional]")
parser.add_argument("-u", "--upsample-rate", help="How many times to upsample the image looking for faces. Higher numbers find smaller faces. [Optional]")
args = vars(parser.parse_args())

# 检查参数值是否有效
if args.get("images_dir", None) is None and os.path.exists(str(args.get("images_dir", ""))):
    print("Please check the path to images folder")
    exit()
if args.get("video", None) is None and os.path.isfile(str(args.get("video", None))):
    print("Please check the path to video")
    exit()
if str(args.get("output_csv", None)) is None:
    print("You haven't specified an output csv file. Nothing will be written.")
# 默认情况下,upsample rate(上采样率)=1
upsample_rate = args.get("upsample_rate", None)
if upsample_rate is None:
    upsample_rate = 1

# 辅助函数
def image_files_in_folder(folder):
    return [os.path.join(folder, f) for f in os.listdir(folder) if re.match(r'.*\.(pgm|jpg|png)', f, flags=re.I)]


def test_image(image_to_check, known_names, known_face_encodings, number_of_times_to_upsample=1):
    """
    通过检查已知图像来检测未知图像中是否有人脸被识别
    :param image_to_check: 图像的Numpy数组
    :param known_names: 包含已知标签的列表
    :param known_face_encodings: 包含训练图像标签的列表
    :param number_of_times_to_upsample: 多少次对图像进行重新采样以查找面。数字越高,脸越小。
    :return: 已知名称的标签列表
    """
    # 未知图像unknown_image = face_recognition.load_image_file(image_to_check)
    unknown_image = image_to_check
    # 缩小图像以使其运行更快
    if unknown_image.shape[1] > 1600:
        scale_factor = 1600 / unknown_image.shape[1]
        with warnings.catch_warnings():
            warnings.simplefilter("ignore")
        unknown_image = scipy.misc.imresize(unknown_image, scale_factor)
    face_locations = face_recognition.face_locations(unknown_image,  number_of_times_to_upsample)
    unknown_encodings = face_recognition.face_encodings(unknown_image, face_locations)

    result = []
    for unknown_encoding in unknown_encodings:
        result = face_recognition.compare_faces(known_face_encodings, unknown_encoding)

    result_encoding = []
    for nameIndex, is_match in enumerate(result):
        if is_match:
            result_encoding.append(known_names[nameIndex])

    return result_encoding

def map_file_pattern_to_label(labels_with_pattern, labels_list): #result
    """
    将文件名模式映射到完整标签
    :param labels_with_pattern: dict : { "file_name_pattern": "full_label" }
    :param labels_list: list : 从test_image()获取的文件名标签列表
    :return: 完整标签列表
    """
    result_list = []
    for key, label in labels_with_pattern.items():
        for img_labels in labels_list:
            if str(key).lower() in str(img_labels).lower():
                if str(label) not in result_list:
                    result_list.append(str(label))
                # continue
    # result_list = [label for key, label in labels_with_pattern if str(key).lower() in labels_list]
    return result_list

cap = cv2.VideoCapture(args["video"])

# 获取训练图像
training_encodings = []
training_labels = []
for file in image_files_in_folder(str(args['images_dir'])):
    basename = os.path.splitext(os.path.basename(file))[0]
    img = face_recognition.load_image_file(file)
    encodings = face_recognition.face_encodings(img)

    if len(encodings) > 1:
        print("WARNING: More than one face found in {}. Only considering the first face.".format(file))

    if len(encodings) == 0:
        print("WARNING: No faces found in {}. Ignoring file.".format(file))
    if len(encodings):
        training_labels.append(basename)
        training_encodings.append(encodings[0])


csvfile = None
csvwriter = None
if args.get("output_csv", None) is not None:
    csvfile = open(args.get("output_csv"), 'w')
    csvwriter = csv.writer(csvfile, delimiter=',', quotechar='|', quoting=csv.QUOTE_MINIMAL)

ret, firstFrame = cap.read()
frameRate = cap.get(cv2.CAP_PROP_FPS)

# 带有文件模式的标签,编辑此处
label_pattern = {
    "pooja": "Shahrukh Khan","j": "Ameer Khan"
            }

# 将视频中的每一帧与我们训练过的一组标记图像相匹配
while ret:
    curr_frame = cap.get(1)
    ret, frame = cap.read()
    result = test_image(frame, training_labels, training_encodings, upsample_rate)
    print(result)
    labels = map_file_pattern_to_label(label_pattern, result)
    print(labels)
    curr_time = curr_frame / frameRate
    print("Time: {} faces: {}".format(curr_time, labels))
    if csvwriter:
        csvwriter.writerow([curr_time, labels])
    cv2.imshow('frame', frame)

    key = cv2.waitKey(1) & 0xFF
    if key == ord('q'):
        break
if csvfile:
    csvfile.close()
cap.release()
cv2.destroyAllWindows()

Face_Tracking.py

import cv2
import dlib

# 使用OpenCV库提供的正面haar级联初始化面级联
faceCascade = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')

# 设备输出宽度和高度
OUTPUT_SIZE_WIDTH = 775
OUTPUT_SIZE_HEIGHT = 600

def detectAndTrackLargestFace():
    # 打开第一个网络摄像机设备
    capture = cv2.VideoCapture(0)

    # 创建两个名为windows窗口的opencv
    cv2.namedWindow("base-image", cv2.WINDOW_AUTOSIZE)
    cv2.namedWindow("result-image", cv2.WINDOW_AUTOSIZE)

    # 把windows窗口靠在一起
    cv2.moveWindow("base-image",0,100)
    cv2.moveWindow("result-image",400,100)

    # 启动我们正在使用的两个windows窗口的windows窗口线程
    cv2.startWindowThread()

    # 创建我们将使用的dlib的跟踪器
    tracker = dlib.correlation_tracker()

    # 我们用来跟踪当前是否使用dlib跟踪器的变量
    trackingFace = 0

    # 我们在脸周围画的矩形的颜色
    rectangleColor = (0,165,255)

    try:
        while True:
            # 从网络摄像头中检索最新图像
            rc, fullSizeBaseImage = capture.read()

            # 将图像大小调整为320x240
            baseImage = cv2.resize( fullSizeBaseImage, ( 320, 240))

            #检查是否按下了某个键,如果是Q,则销毁所有opencv窗口并退出应用程序
            pressedKey = cv2.waitKey(2)
            if pressedKey == ord('Q'):
                cv2.destroyAllWindows()
                exit(0)

            # 结果图像是我们将向用户显示的图像,它是来自网络摄像头的原始图像和最大人脸的叠加矩形的组合
            resultImage = baseImage.copy()

            # 如果我们没有跟踪一张脸,那就试着检测一张
            if not trackingFace:

                # 对于人脸检测,我们需要利用一个灰色的图像,这样我们就可以将基础图像转换为基于灰色的图像
                gray = cv2.cvtColor(baseImage, cv2.COLOR_BGR2GRAY)
                # 现在使用haar级联检测器查找图像中的所有面
                faces = faceCascade.detectMultiScale(gray, 1.3, 5)

                #在控制台中,我们可以显示,只有现在我们才使用面部探测器
                print("Using the cascade detector to detect face")

                #目前,我们只对“最大的”面感兴趣,我们根据找到的矩形的最大面积来确定。首先将所需变量初始化为0
                maxArea = 0
                x = 0
                y = 0
                w = 0
                h = 0

                # 在所有面上循环,并检查此面的面积是否是迄今为止最大的。
                # 由于dlib跟踪器的要求,我们需要在这里把它转换成int。
                # 如果我们在这里省略对int的强制转换,您将得到强制转换错误,因为检测器返回numpy.int32,而跟踪器需要一个int
                for (_x,_y,_w,_h) in faces:
                    if _w*_h > maxArea:
                        x = int(_x)
                        y = int(_y)
                        w = int(_w)
                        h = int(_h)
                        maxArea = w*h

                # 如果找到一个或多个面,请在图片中最大的面上初始化跟踪器
                if maxArea > 0 :
                    # 初始化跟踪器
                    tracker.start_track(baseImage,
                                        dlib.rectangle( x-10,
                                                        y-20,
                                                        x+w+10,
                                                        y+h+20))
                    # 设置指示器变量,以便我们知道跟踪器正在跟踪图像中的某个区域
                    trackingFace = 1

            # 检查跟踪器是否正在主动跟踪图像中的某个区域
            if trackingFace:
                # 更新跟踪程序并请求有关跟踪更新质量的信息
                trackingQuality = tracker.update(baseImage)
                # 如果跟踪质量足够好,确定跟踪区域的更新位置并绘制矩形
                if trackingQuality >= 8.75:
                    tracked_position =  tracker.get_position()
                    t_x = int(tracked_position.left())
                    t_y = int(tracked_position.top())
                    t_w = int(tracked_position.width())
                    t_h = int(tracked_position.height())
                    cv2.rectangle(resultImage, (t_x, t_y), (t_x + t_w , t_y + t_h), rectangleColor ,2)

                else:
                    # 如果跟踪更新的质量不够(例如,被跟踪区域移出屏幕),我们将停止对人脸的跟踪,
                    # 在下一个循环中,我们将再次在图像中找到最大的人脸
                    trackingFace = 0

            # 因为我们想在屏幕上显示比原来的320x240更大的东西,所以我们再次调整图像的大小
            # 请注意,也可以保留大版本的基本图像,并使结果图像成为此大基本图像的副本,并使用缩放因子在右坐标处绘制矩形。
            largeResult = cv2.resize(resultImage, (OUTPUT_SIZE_WIDTH,OUTPUT_SIZE_HEIGHT))
            # 最后,我们想在屏幕上显示图像
            cv2.imshow("base-image", baseImage)
            cv2.imshow("result-image", largeResult)

    # 为了确保我们也可以处理用户在控制台中按Ctrl-C
    # 我们必须检查键盘中断异常并销毁所有opencv窗口并退出应用程序
    except KeyboardInterrupt as e:
        cv2.destroyAllWindows()
        exit(0)

if __name__ == '__main__':
    detectAndTrackLargestFace()

发布了352 篇原创文章 · 获赞 116 · 访问量 19万+

猜你喜欢

转载自blog.csdn.net/zimiao552147572/article/details/104723317