Python中Opencv的基础应用-人脸识别

一。首先如果想要使用Opencv,需要导入cv2库,这里主要使用的是cv2(有三代)的功能。

import cv2 as cv

二。cv2的文件需要下载,这里下载有两种方式:

    ①:第一种方式是–>当你敲了上述代码时cv2下会有红色波浪线,你只需要将鼠标光标放在上面按下alt+enter键,会弹出import cv2选项,点击即可。但是此方法只适用于您已经设置好了pycharm或者其他编辑器的默认镜像网站或者开了魔法。因为cv2源站在外面。

   ②:于是便有了第二种方式–>在terminal中敲入以下代码

pip install -i https://pypi.tuna.tsinghua.edu.cn/simple opencv-python

里面使用的时清华大学的镜像源,您也可以选择其他镜像源,比如豆瓣等

三。然后我们尝试一个简单的操作:展示一张图片

img=cv.imread('image.jpg')   #读取路径中的图片,路径必须全英文
cv.imshow('read_img',img)    #imshow(‘起一个弹窗名称’,读取的图片对象)
# cv.waitKey(0)              # 等待键盘输入,单位毫秒,传入0则就是无线等待,必须按下按键
cv.waitKey(3000)             # 如果写入时间,则是有两个选择,一个是按下任意键,一个是等待三秒
cv.destroyWindow('read_img') # 释放内存,结束掉时释放被占用的内存,括号内写入需要关闭的窗口名

四。上面的代码可以帮助我们使用opencv打开一个图片,这有助于我们进行图片方面的识别。

        现在我们来尝试第二个功能:将图片转化为灰色。

        为什么要转为灰色,可以理解为图片中色彩太多会对识别产生干扰,需要先解决它。

           

import cv2 as cv

img=cv.imread('image.jpg')
cv.imshow('Myimg',img)
# 将图片灰度转换
gray_img=cv.cvtColor(img,cv.COLOR_BGR2GRAY)#cvtColor('图片对象',‘将BGR图片转为gray灰度图片’)
cv.imshow('gray_img',gray_img)             
cv.imwrite('grey_img.jpg',gray_img)# 保存图片
cv.waitKey(0)
cv.destroyAllWindows()

   最终我们将转化为灰色的图片保存到了同一层级中。

五。接下来尝试调整窗口的大小,并且设置固定的关闭窗口按键

import cv2 as cv

img=cv.imread('image.jpg')
cv.imshow('image',img)
resize_img=cv.resize(img,dsize=(200,240))  #调整图片的大小
cv.imshow('small_mg',resize_img)

while True:                                #此处添加了一个无线循环
    if ord('q')==cv.waitKey(0):            #waitkey会监测键盘输入,当键盘输入等于q时结束循环
        break
cv.destroyAllWindows()                     #结束循环后释放内存

六。然后就开始正式和人脸有关了,我们尝试识别出图片中的人脸并且将人脸用矩形框出来。

首先需要理解举行的坐标是如何运作的–>默认矩形的左上角是(x,y),宽为w,高为h

画矩形代码:reactangle(图片,坐标,颜色,粗度)

重点:既然我们学会了如何绘制矩形,但是我们该如何知道图片中人脸的坐标呢?因为我们需要在人脸上画矩形,这里就用到了opencv最厉害的工具–我们将站在巨人的肩膀上,直接使用他们编写好并开源的人脸识别代码。但在调用之前我们还需要额外安装一下它。

我这里使用的是4.9.0版本,直接去官网下载就可以了,是开源免费的。

安装好了之后我们就需要调用里面的人脸识别组件(其中包含了许多组件)

组件路径是安装目录下的:

opencv/sources/data/haarcascades/haarcascade_frontalface_default.xml

调用组件代码是:cv.CascadeClassifier('路径'),需要使用一个变量接收

face_detector=cv.CascadeClassifier("D:/Opencv/opencv/sources/data/haarcascades/haarcascade_frontalface_default.xml")

于是乎,我们就可以通过调用变量名来使用其功能了。

其中用来监测人脸的代码是:face_detector.detectMultiScale(灰度图片对象)

faces=face_detector.detectMultiScale(gray) #faces中存储的是人脸的坐标

接下来,我们来完整一下这个代码:

# 1导入拓展
import cv2 as cv
# 2.读取图片
img=cv.imread('image.jpg')
# 3.转为灰度
gray=cv.cvtColor(img,cv.COLOR_BGR2GRAY)
# 4.导入人脸识别组件
face_detector=cv.CascadeClassifier("D:/Opencv/opencv/sources/data/haarcascades/haarcascade_frontalface_default.xml")
# 5.使用组件
faces=face_detector.detectMultiScale(gray)
# 获取面部坐标
for x,y,w,h in faces:   #每组x,y,w,h是一个人脸的坐标,有几个人脸画几个矩形
    cv.rectangle(img,(x,y),(x+w,y+h),color=(0,255,0),thickness=2)
cv.imshow('img',img)
cv.waitKey(0)
cv.destroyAllWindows()

以上就可以将我们图片中的人脸给框出来了。

七。如果一个图片中有多个人脸,很容易会出现识别出错的情况,我们需要微调。使用邻居数量限制和缩小比例来提高精确度。

使用代码:minNeighbors=数值,scaleFactor=数值。

如何去理解minNeighbors,画好一个矩形之后周围矩形的最小数量

如何去理解缩小比例。监测人脸是一种遍历的过程,会逐渐缩小监测框,缩小比例越小越精确。

我们来完善一下代码:

import cv2 as cv

img=cv.imread('scientist.jpg')
# 在检测人脸前需要将图片转换为灰色
grey=cv.cvtColor(img,cv.COLOR_BGR2GRAY)
# 调用人脸识别库
faceDectector=cv.CascadeClassifier("D:/Opencv/opencv/sources/data/haarcascades/haarcascade_frontalface_default.xml")
# 使用库,放入图片
faces=faceDectector.detectMultiScale(grey,minNeighbors=1,scaleFactor=1.09)
# 获取人脸坐标
for x,y,w,h in faces:
    print(x,y,w,h)
    cv.rectangle(img,(x,y),(x+w,y+h),color=(0,255,0),thickness=2)
cv.imshow('scientists',img)
cv.waitKey(0)
cv.destroyAllWindows()

八。接下来,我们加大难度,来监测视频中的人脸:但其实也不难,只要在之前的代码中添加新功能即可:只是多了两步。

                ①,第一步是将之前的监测人脸代码放到函数里面。

                ②,第二部就是使用cv.VideoCapture(‘视频路径’),获取视频文件并使用for循环遍历其中的帧。也就是将一个视频拆解成了许多的图片,将每个图片中的人脸都框出来再逐一展示再弹窗中。

import cv2 as cv

def face_detect(img):
#     首先将图片转化为灰色
    gray=cv.cvtColor(img,cv.COLOR_BGR2GRAY)
# 调用识别库
    faceDetector=cv.CascadeClassifier('D:/Opencv/opencv/sources/data/haarcascades/haarcascade_frontalface_default.xml')
# 使用库
    faces=faceDetector.detectMultiScale(gray)
#     获得坐标
    for x,y,w,h in faces:
        cv.rectangle(img,(x,y),(x+w,y+h),color=(0,255,0),thickness=2)
    cv.imshow('Video',img)

cap=cv.VideoCapture('guitar.mp4')
while True:
    flag,frame=cap.read()   # flag代表视频播放状态,frame相当于视频每一帧
    if not flag:
        break
    face_detect(frame)
    if ord('q')==cv.waitKey(10):
        break
cv.destroyAllWindows()
# 释放内存
cap.release()

九。在然后,我们来尝试如何来通过摄像头试试监测人脸。这就更简单了,只需要将视频文件设置成摄像头数据就行。将视频路径改为数字0

import cv2 as cv

def face_detect(img):
# 转为灰色
    gray=cv.cvtColor(img,cv.COLOR_BGR2GRAY)
    # 调用人脸识别组件
    face_dectector=cv.CascadeClassifier('D:/Opencv/opencv/sources/data/haarcascades/haarcascade_frontalface_default.xml')
    # 使用组件
    faces=face_dectector.detectMultiScale(gray)
    # 获取坐标
    for x,y,w,h in faces:
        cv.rectangle(img,(x,y),(x+w,y+h),color=(0,255,0),thickness=2)
# 展示图片
    cv.imshow('show',img)
# 读取摄像头
video=cv.VideoCapture(0)
while True:
        flag,frame = video.read()
        face_detect(frame)
        if flag==False:
            break
        if ord(' ')==cv.waitKey(10):
            break
cv.destroyWindow()

十。然后我们在进入下一个境界,那就是训练人脸,从这开始,opencv提高了些难度。

import os  # 用于处理文件路径和文件操作
import cv2 as cv  # OpenCV库,用于图像处理和计算机视觉任务
from PIL import Image  # Pillow库,用于图像处理
import numpy as np  # 用于数组操作


def getImageAndLabels(path):
    """
    获取指定路径下的图像和对应的标签(ID)。
    遍历路径中的每个图像文件,提取其中的人脸并记录对应的ID。

    参数:
    path (str): 存储人脸图像的文件夹路径。

    返回:
    facesSample (list): 包含所有人脸区域的列表。
    ids (list): 对应人脸的ID列表。
    """
    facesSample = []  # 用于存储人脸区域的列表
    ids = []  # 用于存储每张人脸对应的ID
    imagePaths = [os.path.join(path, f) for f in os.listdir(path)]  # 获取路径中所有图像文件的完整路径

    # 使用预训练的人脸分类器进行人脸检测,CascadeClassifier是一种级联分类器
    face_detector = cv.CascadeClassifier(cv.data.haarcascades + 'haarcascade_frontalface_default.xml')

    for imagePath in imagePaths:
        try:
            # 打开图像并将其转换为灰度图,因为人脸检测通常在灰度图像上效果更好
            PIL_image = Image.open(imagePath).convert('L')
        except Exception as e:
            print(f"Error opening image {imagePath}: {e}")  # 如果图像打开失败,打印错误信息
            continue

        img_numpy = np.array(PIL_image, 'uint8')  # 将图像转换为NumPy数组,用于后续处理
        # 使用分类器检测图像中的人脸,返回的是人脸区域的坐标列表
        faces = face_detector.detectMultiScale(img_numpy, scaleFactor=1.2, minNeighbors=5)

        # 从文件名中提取ID,假设文件名的格式为 "ID.其他扩展名"
        id = int(os.path.split(imagePath)[1].split('.')[0])

        # 遍历检测到的人脸区域
        for (x, y, w, h) in faces:
            # 确保人脸的坐标在图像边界内
            if x + w <= img_numpy.shape[1] and y + h <= img_numpy.shape[0]:
                # 截取人脸区域,并添加到人脸样本列表中
                facesSample.append(img_numpy[y:y + h, x:x + w])
                # 添加对应的ID到列表
                ids.append(id)
    return facesSample, ids


if __name__ == '__main__':
    # 设置人脸图像所在的文件夹路径
    path = './jm'

    # 调用函数获取图像中的人脸和对应的ID
    faces, ids = getImageAndLabels(path)

    # OpenCV的新版本不再支持face模块,但这里是使用旧版的face识别器
    recognizer = cv.face.LBPHFaceRecognizer_create()  # 创建LBPH人脸识别器
    recognizer.train(faces, np.array(ids))  # 使用获取到的人脸和ID列表训练识别器

    # 如果存储模型的文件夹不存在,则创建一个新的
    if not os.path.exists('trainer'):
        os.makedirs('trainer')

    # 将训练好的模型保存到指定文件
    recognizer.write('trainer/trainer.yml')

十一。最后我们来尝试识别出人脸并作出反馈

import os
import numpy as np
import time
import cv2 as cv
video=cv.VideoCapture(0)
# 加载训练数据集文件
recognizer=cv.face.LBPHFaceRecognizer_create()
recognizer.read('trainer/trainer.yml')
while True:
    flag, frame = video.read()
    # 准备识别图片
    gray=cv.cvtColor(frame,cv.COLOR_BGRA2GRAY)
    face_dectector=cv.CascadeClassifier('D:/Opencv/opencv/sources/data/haarcascades/haarcascade_frontalface_default.xml')
        # 使用组件
    faces=face_dectector.detectMultiScale(gray)
    for x,y,w,h in faces:
        cv.rectangle(frame,(x,y),(x+w,y+h),(0,255,0),2)
    #     人脸识别
        id,confindence=recognizer.predict(gray[y:y+h,x:x+w])
        print('标签id',id,'置信评分:',confindence)

        if confindence <60 and id<5:
            print(f'完成识别,身份为主人')
        elif confindence < 60 and id >= 65:
            print(f'完成识别,身份为二当家')
        elif confindence < 60 and id >= 78:
            print(f'完成识别,身份为三当家')
        
    cv.imshow('show',frame)
    if flag==False:
                break
    if ord(' ')==cv.waitKey(10):
                break
cv.destroyWindow()

作者:木易往

物联沃分享整理
物联沃-IOTWORD物联网 » Python中Opencv的基础应用-人脸识别

发表回复