当前位置:   article > 正文

pycharm+opencv实现简单人脸识别_pycharm人脸识别

pycharm人脸识别

一.配置环境

  1. 官网下载python对应版本,配置好环境变量【下载后选择直接添加到路径即可】
  2. jetbrain官网下载pycharm(社区版就行),可在设置里添加汉语包或者其他插件
  3. 下载opencv,如果使用cmd命令的pip下载不成功,就去官网下载python对应版本的opencv。并去项目设置里安装好相应的解释器和软件包

二.一些铺垫

实现一个简单功能:找到图片中的人脸:

  1. #下载opencv-python4.6软件包,导入cv模块
  2. import cv2 as cv
  1. def face_detect_demo():
  2. gray_img = cv.cvtColor(img, cv.COLOR_BGR2GRAY) # 调用cvtcolor(待修改图片名字,修改颜色)
  3. # face_detect=cv.CascadeClassifier('D:/PCgames/GTA5/opencv/sources/data/haarcascades/haarcascade_frontalface_alt2.xml') #调用分类器
  4. face_detect=cv.CascadeClassifier('D:/PCgames/GTA5/opencv/sources/data/haarcascades/haarcascade_frontalface_default.xml')
  5. face=face_detect.detectMultiScale(gray_img)
  6. for x,y,w,h in face:
  7. cv.rectangle(img,(x,y),(x+w,y+h),color=(255,255,0),thickness=2) #调用rectangle(name,(左上角坐标,右下角坐标),颜色,厚度
  8. # cv.circle(resize_img,center=(x+w,y+h),radius=100,color=(255,0,0),thickness=1)) #调用circle(name,(圆心坐标,半径),颜色,厚度)
  9. cv.imshow('result',img) #调用imshow,显示图片

        这是一个检测函数,思路是先给读取的图片进行灰度化,cv.cvtColor()opencv中转换色彩空间的函数,img是待改变的图片像素矩阵,cv.COLOR_BGR2GRAYopencv3以上中的转换灰度格式,结束后把灰度矩阵存入gray_img

        gray_img = cv.cvtColor(img, cv.COLOR_BGR2GRAY)


        cv.CascadeClassifier()是调用分类器,里面的地址是opencv安装文件中的人脸分类器路径,该分类是基于haarlbp的图形识别,调用该分类器并命名为face_detect


        face_detect=cv.CascadeClassifier('D:/PCgames/GTA5/opencv/sources/data/haarcascades/haarcascade_frontalface_default.xml')


        接下来从整图的灰度矩阵里获取人脸部分的灰度矩阵,调用分类器中的detectMultiScale(),这个函数里有诸多参数可以调节识别的精度和次数等等,此处默认值,此函数返回的值是图片中人脸的起点坐标和长宽(x,y,w,h),存入face

            face=face_detect.detectMultiScale(gray_img)


        遍历face里的(x,y,w,h), 然后调用cv.rectangle()绘制矩形


            for x,y,w,h in face:
                cv.rectangle(img,(x,y),(x+w,y+h),color=(255,255,0),thickness=2)
            cv.imshow('result',img)

思路总结:先转换图片色彩空间,然后调用分类器中的人脸识别函数获取人脸范围坐标,然后按照图片的这个范围上绘制矩形,并imshow图片

  1. img=cv.imread('pic4.jpg') #读取一张图片命名为img
  2. while True: #循环
  3. # flag,frame=cap.read() #读取视频赋值给frame,用flag判断视频是否为空
  4. # if not flag:
  5. # break
  6. face_detect_demo()
  7. if ord('Q')==cv.waitKey(0):
  8. break

        这里的思路是,先读取图片'pic4.jpg'存入img,此时如果print(img)则会在控制台输出像素矩阵,即每个点的rgb三元组构成的矩阵,注意图片路径,此处是和py项目在同一文件夹下的情况
然后进行图片检测,之所以用
while true是为了给一个break条件。

        img=cv.imread('pic4.jpg'),
        while True: 
                face_detect_demo()
                if ord('Q')==cv.waitKey(0):
                        break

        只有face_detect_demo()和cv.waitKey(0)也可以
        face_detect_demo()
        cv.waitKey(0)

        其中face_detect_demo()即是检测函数,需要另外定义。GUIimshow()不能单独使用,需要用cv.waitKey(0)控制图片显示时间:括号里为0表示静止当前帧,其他数字是需要等待的毫秒【此处的imshow()位于函数中的最后一步】。cv.waitKey()会返回等待期间键盘输入的字符的asc码,ord('Q')会返回Q的asc码。if两者值相等就break按Q结束检测

思路总结:先读取图片,然后定义face_detect_demo()函数在人脸范围上添加矩形,最按Q结束检测

实现一个简单功能:找到视频/摄像头中的人脸,并能截图保存到本地:

思路设计:与图片检测类似,先读取视频或者摄像头画面中的视频帧,将帧图片传入face_detect_demo()后绘制范围矩形,然后最按s把当前帧保存到指定文件夹并命名,按t结束程序

  1. def face_detect_demo(img):
  2. gray_img = cv.cvtColor(img, cv.COLOR_BGR2GRAY) # 调用cvtcolor(待修改图片名字,修改颜色)
  3. # face_detect=cv.CascadeClassifier('D:/PCgames/GTA5/opencv/sources/data/haarcascades/haarcascade_frontalface_alt2.xml') #调用分类器
  4. face_detect=cv.CascadeClassifier('D:/PCgames/GTA5/opencv/sources/data/haarcascades/haarcascade_frontalface_default.xml')
  5. face=face_detect.detectMultiScale(gray_img) #重复检测5次 每次缩放倍数为1.1
  6. for x,y,w,h in face:
  7. cv.rectangle(img,(x,y),(x+w,y+h),color=(0,255,0),thickness=3) #调用rectangle(name,(左上角坐标,右下角坐标),颜色,厚度
  8. # cv.circle(resize_img,center=(x+w,y+h),radius=100,color=(255,0,0),thickness=1)) #调用circle(name,(圆心坐标,半径),颜色,厚度)
  9. cv.imshow('result',img) #调用imshow,显示图片

        这是 face_detect_demo()函数,注意此时需要给它传入参数,因为视频帧的获取要在其他函数里进行,不可以是全局变量,而图片读取可以在最外层也即是可以定义为全局变量。

  1. cap=cv.VideoCapture(0) #调用摄像头
  2. #cap=cv.VideoCapture('video1.mp4') #这是读取对应视频
  3. flag=1
  4. num=1
  5. #判断摄像头是否为空
  6. while(cap.isOpened()):
  7. #读取当前帧frame,并传入函数中
  8. ret_flag,frame=cap.read()
  9. face_detect_demo(frame)
  10. #按s截取视频帧
  11. if ord('s')==cv.waitKey(2):
  12. #把视频帧写入指定地点并命名
  13. cv.imwrite("C:/Users/KXing/Desktop/facedetecet2/opencv/data/framepic/fpic2/"+str(num)+".name"+".jpg",frame)
  14. print("成功保存截图"+str(num)+".jpg")
  15. print("------------------")
  16. num+=1
  17. elif ord('t')==cv.waitKey(2):
  18. break
  19. #结束后释放内存
  20. cap.release()
  21. cv.destroyAllWindows()

        这里是先调用摄像头截取视频帧,然后把当前帧传入face_detect_demo()函数进行人脸识别和标记,并按照指定名字写入指定文件夹。此时cv.waitKey(2)中不能为0,因为0为静止当前帧。

三.实现人脸识别

实现训练模型的创造训练和保存:

  1. import hashlib
  2. import os
  3. import tkinter.messagebox
  4. import urllib
  5. import urllib.request
  6. from datetime import datetime
  7. import cv2 as cv # 下载opencv-python4.6软件包,导入cv模块
  8. import numpy as np
  9. from PIL import Image

        定义一个获取图片人脸信息的函数getImageAndLabels(path),imagePaths = [os.path.join(path, listname) for listname in os.listdir(path)]是将文件中图片的完整格式保存到信息数组里。然后再里面即可遍历每一张图片,把灰度矩阵保存在img_numpy 数组中【要是用numpyconvert('L')方法打开则要import numpy】。然后把img_numpy传入人脸识别模块返回图片人脸的坐标【xywh】。最后把该坐标对应的灰度矩阵和id返回

  1. def getImageAndLabels(path):
  2. facesSamples = [] # 定义一个数组存放脸部样本
  3. ids = [] # 这个数组用来存放脸部样本的id
  4. imagePaths = [os.path.join(path, listname) for listname in
  5. os.listdir(path)] # 这个数组用来存放图片信息,os.listdir(path)返回path中的文件名按照字母排序
  6. # os.path.join(path, f),将多个路径组合返回,这一步是把图片名和存放图片的路径组合成图片的路径
  7. # 调用opencv库的分类器检测人脸
  8. face_detector = cv.CascadeClassifier(
  9. 'D:/PCgames/GTA5/opencv/sources/data/haarcascades/haarcascade_frontalface_alt2.xml')
  10. # 打印数组imagePaths
  11. print('数据信息:', imagePaths)
  12. # 遍历列表中的图片
  13. for imagpath in imagePaths: # 这是在图片信息数组中遍历每一张图片
  14. # 用l法打开图片,此时每个像素点可表示为一个(0-255)的值,将得到的图片存入PIL_img
  15. PIL_img = Image.open(imagpath).convert('L')
  16. img_image = cv.imread(imagpath) # 如果用opencv打开则显示每个像素rgb数值组成的矩阵
  17. gray_img = cv.cvtColor(img_image, cv.COLOR_BGR2GRAY) # 用opencv调成灰色图,此时得到矩阵和img_numpy相同
  18. print(PIL_img)
  19. print('这是impath', imagpath)
  20. print('这是整图灰度矩阵opencv', gray_img)
  21. # PIL_img = cv2.resize(PIL_img, dsize=(400, 400))
  22. img_numpy = np.array(PIL_img, 'uint8') # np.array是一种创建数组的方法,前面是创建对象,后面是元素的类型,将PIL_img创建成为矩阵,存入img_numpy
  23. # 其中img_numpy即使所选图像的灰度值矩阵
  24. print('这是整图的灰度矩阵numpy和PIL', img_numpy)
  25. # 接下来从整图的灰度矩阵里获取图片人脸特征, face_detector.detectMultiScale是opencv的一个函数
  26. # image–待检测图片,一般为灰度图像加快检测速度;objects–被检测物体的矩形框向量组;scaleFactor–表示在前后两次相继的扫描中,搜索窗口的比例系数。默认为1.1即每次搜索窗口依次扩大10%
  27. # minNeighbors–表示构成检测目标的相邻矩形的最小个数(默认为3个),flags–要么使用默认值,要么使用CV_HAAR_DO_CANNY_PRUNING,如果设置为
  28. # CV_HAAR_DO_CANNY_PRUNING,那么函数将会使用Canny边缘检测来排除边缘过多或过少的区域,minSize和maxSize用来限制得到的目标区域的范围。
  29. faces = face_detector.detectMultiScale(img_numpy)
  30. print('这是faces', faces) # 返回的faces为人脸的起点以及人脸矩形的长宽(x,y,w,h)
  31. # 获取每张图片的id和姓名,os.path.split是分离路径和和文件名函数,
  32. id = int(os.path.split(imagpath)[1].split('.')[
  33. 0]) # os.path.split(imagePath)[0],整个路径链表的表头,os.path.split(imagePath)[1]
  34. # os.path.split(imagePath)[1]split('.')[1],后面是指以’‘内划分链表,0为头,1为表尾
  35. h = []
  36. h = os.path.split(imagpath)[0].split('a')[1]
  37. print('this is path', imagpath)
  38. print('this is os.path', h)
  39. # 预防无面容照片
  40. # 在faces中遍历(x,y,w,h),把id加入数组,把人脸灰度矩阵加入数组
  41. for x, y, w, h in faces:
  42. ids.append(id)
  43. facesSamples.append(img_numpy[y:y + h, x:x + w])
  44. # 打印脸部特征和id
  45. print('fs:', facesSamples)
  46. print('id:', id)
  47. # print('fs:', facesSamples[id])
  48. # print('fs:', facesSamples)
  49. # print('脸部例子:',facesSamples[0])
  50. # print('身份信息:',ids[0])
  51. return facesSamples, ids

        定义一个train()函数 ,if __name__ == '__main__':内的内容不会被其他py文件importlen(os.listdir(path))即是获取路径内文件名字的长度,若存在图片就调用getImageAndLabels()函数返回文件夹中图片的面部灰度矩阵和id。然后调用cv.face.LBPHFaceRecognizer_create(内有若干参数可选) 生成LBPH识别器实例模型recognizer,然后调用recognizer.train ( )函数训练,并将训练结果存入指定文件的yml文件里。再识别时会读取该文件数据。

  1. def train():
  2. #这个if可以让内部内容不被其他文件import
  3. if __name__ == '__main__':
  4. path = 'C:/Users/KXing/Desktop/facedetecet2/opencv/data/framepic/fpic/'
  5. if len(os.listdir(path)) > 0:
  6. # 调用函数,获取面部灰度矩阵和对应的id,存入faces和ids
  7. faces, ids = getImageAndLabels(path)
  8. # 调用cv.face.LBPHFaceRecognizer_create(),这是opencv中基于lbph算法的函数
  9. recognizer = cv.face.LBPHFaceRecognizer_create()
  10. print('this is rec', recognizer)
  11. # # recognizer.train(faces,names)#np.array(ids)
  12. # # 训练函数,传入面部矩阵数组和id数组
  13. recognizer.train(faces, np.array(ids))
  14. # 注意此处的faces是函数里的结果之一
  15. # # 保存文件,写入trainer.yml,此文件用来进行面部对比
  16. recognizer.write('C:/Users/KXing/Desktop/facedetecet2/opencv/data/trainer.yml')

​​​​​​​开始识别:

  1. def name():
  2. path = 'C:/Users/KXing/Desktop/facedetecet2/opencv/data/framepic/fpic/'
  3. imagePaths = [os.path.join(path, f) for f in os.listdir(path)]
  4. for imagePath in imagePaths:
  5. name = str(os.path.split(imagePath)[1].split('.', 2)[1])
  6. # print("aSDF", name)
  7. inames.append(name)
  1. def face_detect(img):
  2. # recogizer = cv.face.LBPHFaceRecognizer_create()
  3. gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY) # 转换为灰度
  4. face_detector = cv.CascadeClassifier(
  5. 'D:/PCgames/GTA5/opencv/sources/data/haarcascades/haarcascade_frontalface_default.xml')
  6. face = face_detector.detectMultiScale(gray, 1.1, 5, cv.CASCADE_SCALE_IMAGE, (100, 100), (300, 300))
  7. # face=face_detector.detectMultiScale(gray)
  8. for x, y, w, h in face:
  9. cv.rectangle(img, (x, y), (x + w, y + h), color=(0, 0, 255), thickness=2)
  10. cv.circle(img, center=(x + w // 2, y + h // 2), radius=w // 2, color=(0, 255, 0), thickness=1)
  11. # 人脸识别
  12. ids, confidence = recognizer.predict(gray[y:y + h, x:x + w])
  13. # recognizer.predict()进行对比,返回id和confidence值,这个值用来衡量相似度
  14. # print('标签id:',ids,'置信评分:', confidence)
  15. if confidence > 80:
  16. global warningtime
  17. warningtime += 1
  18. if warningtime > 100:
  19. warning()
  20. warningtime = 0
  21. #这里是给画面矩形框添加识别结果的文本
  22. cv.putText(img, 'unkonw', (x + 10, y - 10), cv.FONT_HERSHEY_SIMPLEX, 0.75, (0, 255, 0), 1)
  23. else:
  24. cv.putText(img, str(inames[ids-2]) , (x + 10, y - 10), cv.FONT_HERSHEY_SIMPLEX, 0.75, (0, 255, 0), 1)
  25. cv.imshow('detectresult', img)
  1. def train():
  2. if __name__ == '__main__':
  3. path = 'C:/Users/KXing/Desktop/facedetecet2/opencv/data/framepic/fpic/'
  4. if len(os.listdir(path)) > 0:
  5. # 调用函数,获取面部灰度矩阵和对应的id,存入faces和ids
  6. faces, ids = getImageAndLabels(path)
  7. # 调用cv.face.LBPHFaceRecognizer_create(),这是opencv中基于lbph算法的函数
  8. recognizer = cv.face.LBPHFaceRecognizer_create()
  9. print('this is rec', recognizer)
  10. # # recognizer.train(faces,names)#np.array(ids)
  11. # # 训练函数,传入面部矩阵数组和id数组
  12. recognizer.train(faces, np.array(ids))
  13. print('what is it ?', recognizer.train(faces, np.array(ids))) # 注意此处的faces是函数里的结果之一
  14. # # 保存文件,写入trainer.yml,此文件用来进行面部对比
  15. recognizer.write('C:/Users/KXing/Desktop/facedetecet2/opencv/data/trainer.yml')
  1. def detectfin():
  2. # pathyml = ('C:/Users/KXing/Desktop/facedetecet2/opencv/data/')
  3. # if len(os.listdir(pathyml)) > 0:
  4. flag = 1
  5. cap = cv.VideoCapture(0)
  6. name()
  7. while (cap.isOpened()):
  8. ret_flag, frame = cap.read()
  9. face_detect(frame)
  10. if ord(' ') == cv.waitKey(10):
  11. # flaglo = 0
  12. break
  13. cv.destroyAllWindows()
  14. cap.release()
  1. train()
  2. detectfin()

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小丑西瓜9/article/detail/100994
推荐阅读
相关标签
  

闽ICP备14008679号