人脸识别项目从0开始

人脸识别项目从0开始



环境搭建

说实话,这个是真的太费精力了,我们采用python和opencv来实现,这个python的版本, opencv的版本下载,在pycharm编译器中真的找了一大堆看着头大。

这里只介绍我觉得比较方便并且操作起来容易好理解的。

首先,python的下载,我们需要下载一个python的版本,而这个版本最好是3.6,因为大部分教程中的版本都是3.6。在我尝试3.11,3.9各种报错之后,我乖乖的选择了3.6.7。


找到官网下载安装到一个你知道的路径即可,建议将下载连接放到迅雷等下载软件中下载可以秒下载。


其次,pycharm准备好即可,没有特别的要求。在建立新项目的时候在选择python解释器的时候,选择你之前准备好的python版本,在选择项目路径的时候提前建好文件夹。

最后,是安装包的通用流程。可以用pip,可以直接把包给复制到你的vene下的site-package中。但是最保险的是直接用pycharm去安装。在pycharm下面有一行里有一个Python Package点击之后,可以看到你安装的包,这个时候点齿轮设置按钮,这个是可以来加下载的源,我们可以添加国内的镜像网站,来保证下载的更快。在插件库URL中加上https://pypi.tuna.tsinghua.edu.cn/simple/ 。清华的源,也可以加别的。之后应用 确定。

然后关掉,进入设置,项目,Python解释器。点进去之后看到软件包,点击加号搜索open-python点击下载即可,这里要保证你的版本是和python版本匹配。3.6.7是和opencv4.5.5.62。如果前面都正确,下载速度非常快,几秒。就把新的opencv的包加入到了环境里。

还需要安装opencv的源码来最终调用后面提到的训练好的分类器。opencv.org 官网下载,得到地址后使用迅雷。安装到自定的一个路径下。



基础版本实现及原理

基础版本对指定的照片进行识别。

opencv+python

判断的几个流程是:导入分类器文件,读入图片,转为灰阶图,调用detectMultiScale,绘制矩形框标记人脸,输出图像。

级联分类器:CascadeClassifier就是opencv下objdetect模块中用来做目标检测的级联分类器的一个类,它可以帮助我们检测例如车牌、眼睛、人脸等物体。

而实现的这个模型就在最后安装的opencv源码中,sources/data/haarcascades.里面 haarcascade_frontalface_alt2.xml 和 haarcascade_frontalface_default.xml 都可以使用。

import cv2 as cv

# 读入图像
img = cv.imread('3.jpg')
# 把图像转化成灰度
gary = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
# 导入分类器文件
face_detect = cv.CascadeClassifier('D:/soft/opencv/opencv/sources/data/haarcascades/haarcascade_frontalface_alt2.xml')
# 调用detectMultiScale函数检测
face = face_detect.detectMultiScale(gary)

num = 0
# 绘制矩形框标记人脸
for x, y, w, h in face:
    cv.rectangle(img, (x, y), (x+w, y+h), color=(0, 0, 255), thickness=1)
    num = num+1
# 输出图像
cv.imshow('result', img)

print("照片里有", num, "个人")
cv.waitKey(0)



对视频进行识别

VideoCapture

我理解是从视频中抓取图片,cv.VideoCapture(0)是从本地的摄像头抓取,括号内部’1.mp4’,就是从视频中抓取。

cap.read():是从抓取到的图片中得到数据,如果有图像返会第一个值为true,否则为false。第二个是图片格式。

我们不断检测是否从图像中抓取到了图像,如果有图像就检测是否有人脸,循环,并且每次抓取等待时间为1/24s,就是24帧,可以达到动起来的效果。直到按下q退出。

cap = cv.VideoCapture(0)
# cap = cv.VideoCapture('1.mp4')

while True :
    flag,frame = cap.read()
    if not flag :
        break
    face_detect_demo(frame)
    if ord('q') == cv.waitKey(1000//24):
        break

cv.destroyAllWindows()

cap.release()


在视频中对照片进行保存

还是使用VideoCapture采集视频中的图像

read()得到信息,展示出图像,并且当按下s时候保存图片

保存图片:使用的是cv.imwrite(“路径”+str(num)+“.name”+“.jpg”,frame)

waitKey:括号内,1表示间隔时间是1ms,如果是0则是一直暂停。



训练数据

总体流程是:先获取路径下所有照片的脸部信息和id。然后加载识别器。把刚刚的信息用识别器训练,然后把识别器储存在指定路径下。

    # 获得路径下的信息
	faces, ids = getImageAndLabels(path)
    # 加载识别器
    recognizer = cv2.face.LBPHFaceRecognizer_create()
    # 训练
    recognizer.train(faces, np.array(ids))
    # 保存文件
    recognizer.write('trainer/trainer.yml')
如何获得图片的信息和标签。

1.取出路径下所有照片的路径。

# 存储图片信息,也就是图片的路径,os.listdir(path)是把path路径下的所有文件都遍历一遍,存储到f中,然后用os.path.join拼接起来。
# 存给imagePaths,也就存下了图片的路径。
imagePaths=[os.path.join(path,f) for f in os.listdir(path)]

2.遍历所有该路径下的图片,加载为灰度图片,再将灰度图片变成矩阵,使用这个矩阵来调取面部的分类器 得到面部数据,再用每张图片前的信息来储存id,使用os.path.split来存下序号

note:os.path.split(path) 会把这个路径分为两个部分一个是前面的位置,一个是文件本身的名字。

例如:./data/jm/1.beauty.jpg 。那么os.path.split(path)[0] = /data/jm 。而os.path.split(path)[1] = 1.beauty.jpg 。

note:再使用split函数本身,xxx.split(‘以什么为分割’)[分割后排序第几]。

​ 例子:path:1.beauty.jpg 。path.split(‘.’)[0] = 1 。表示的就是以‘.'为分割,有三个部分第0个是1.

PLUS:多一个步骤,把所有脸部信息存到faces之后,为了防止没有脸的情况,还需要遍历一遍faces,把所有的脸部信息的正方形所在区域的矩形传给另外一个储存的facesSamples,这个里面存储的就是面部的信息

def getImageAndLabels(path):
    #储存人脸数据
    facesSamples=[]
    #存储姓名数据
    ids=[]

    # 存储图片信息,也就是图片的路径,os.listdir(path)是把path路径下的所有文件都遍历一遍,存储到f中,然后用os.path.join拼接起来。
    # 存给imagePaths,也就存下了图片的路径。
    imagePaths=[os.path.join(path,f) for f in os.listdir(path)]

    # 加载分类器
    face_detector = cv2.CascadeClassifier('D:/soft/opencv/opencv/sources/data/haarcascades/haarcascade_frontalface_alt2.xml')

    # 遍历列表中的图片
    for imagePath in imagePaths:
        # 可能路径下有多张图片
        # 打开图片(PIL有9种不同的模式)L是灰度图片,以灰度图片加载。
        PIL_img = Image.open(imagePath).convert('L')
        # 将图片转化成数组,以黑白深浅
        img_numpy = np.array(PIL_img, 'uint8')
        # 用数组以及分类器,获取图片人脸的特征
        faces = face_detector.detectMultiScale(img_numpy)
        # 获取每张图片的id和名字,分解imagePath中的,总之就是取到这个图片的1.之前的1
        id = int(os.path.split(imagePath)[1].split('.')[0])


        # 预防没有面容的图片

        # 将有脸的图片id都存下来了。
        for x,y,w,h in faces:
            ids.append(id)  # 如果一张图片中有多张脸,都是同一个id放入ids中
            facesSamples.append(img_numpy[y:y+h, x:x+w])
        # 打印脸部特征和id
    print('id:', id)
    print('fs:', facesSamples)

    return facesSamples, ids


从已有训练库中检测视频中的人是否认识。

首先,把图片转为灰度,并且用面部分类器,把面部数据传到face。检查face的数据,画出框和圆。

用recogizer.predict(灰度图的面部),返回的是标签编号(按照图片命名格式的第一位)和置信度。

​ 如果置信度大于80,就说明不太一致。warningtime++,直到warning的值大于1000,会打印warning,并且在标签上输出unknow。

​ 如果小于80,说明相似度还是很高的,按照id来找到图片命名格式中的第1个元素(也就是名字),显示到图片上。

def face_detect_demo(img):
    gray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)#转换为灰度
    face_detector=cv2.CascadeClassifier('D:/soft/opencv/opencv/sources/data/haarcascades/haarcascade_frontalface_alt2.xml')

    face=face_detector.detectMultiScale(gray,1.1,5,cv2.CASCADE_SCALE_IMAGE,(100,100),(300,300))
    # face=face_detector.detectMultiScale(gray)
    for x,y,w,h in face:
        cv2.rectangle(img,(x,y),(x+w,y+h),color=(0,0,255),thickness=2)
        cv2.circle(img,center=(x+w//2,y+h//2),radius=w//2,color=(0,255,0),thickness=1)
        # 人脸识别
        ids, confidence = recogizer.predict(gray[y:y + h, x:x + w])
        print('标签id:',ids)
        # 由于我们得到的ids是在照片上标记的,如果命名格式中断了,就会在后面names中ids-1,找不到这个names,会报错,例如我给我的照片标记为3.但是目前没有2.
        # 得到的ids就是3,那么找这个names的时候ids-1=2,没有2,就会报错。如果正常情况,那么ids是3 ,names从0开始计数所以是3-1=2。
        print('标签id:',ids,'置信评分:', confidence)
        if confidence > 80:
            global warningtime
            warningtime += 1
            if warningtime > 100:
               # warning()
               print("warning")
               warningtime = 0
            cv2.putText(img, 'unknow', (x + 10, y - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.75, (0, 255, 0), 1)
        else:
            cv2.putText(img,str(names[ids-1]), (x + 10, y - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.75, (0, 255, 0), 1)
    cv2.imshow('result',img)
    #print('bug:',ids)

name()模块负责给names数组赋值,按照顺序存放文件下的名字。

def name():
    path = './data/jm/'
    #names = []
    imagePaths=[os.path.join(path,f) for f in os.listdir(path)]
    for imagePath in imagePaths:
       name = str(os.path.split(imagePath)[1].split('.')[1])
       names.append(name)

参考:一天搞定人脸识别项目!学不会up直接下跪!(python+opencv)_哔哩哔哩_bilibili

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值