当前位置:   article > 正文

OpenCv做一个简单的人脸识别_人脸识别-局部二值模式直方图创建一个人脸识别器

人脸识别-局部二值模式直方图创建一个人脸识别器

#人脸识别# #opencv#

最近想做一个人脸识别,正好手上面有一块树莓派4B,借这个机会正好把树莓派玩一下。

一.准备阶段

1.软硬件搭配

  树莓派(树莓派最好还是搞个风扇,不然又烫又卡)

  摄像头(随便找的一块,不是很好,但是够用)

 pycharm:

如果需要下载可以直接去官网下载,分为社区版和专业版,其中社区版免费但是被阉割过了,缺少部分功能,专业版功能强大,但是需付费,专业版许可证和账号可以去淘宝买,不会超过十块钱。

2.环境安装

(1)资料查找

OpenCV是一个基于Apache2.0许可(开源)发行的跨平台计算机视觉和机器学习软件库,可以运行在LinuxWindowsAndroidMac OS操作系统上。 它轻量级而且高效——由一系列 C 函数和少量 C++ 类构成,同时提供了Python、RubyMATLAB等语言的接口,实现了图像处理和计算机视觉方面的很多通用算法。

(2)库文件安装:下载opencv和扩展包。

这里的opencv的两个包区别:

1.opencv-python 只包含了主要模块的包

2.opencv-contrib-python 包含了主要模块以及扩展模块

pycharm终端命令行输入pip指令,但是注意自己的opencv版本和python环境版本对应。

  1. pip install opencv-python
  2. pip install opencv-contrib-python

输入 python -V  或者 python --version

  1. python -V
  2. python --version

如果下载缓慢或者异常中断,可以加入国内镜像源去安装,例如

  1. ​pip install <安装包> -i https://pypi.tuna.tsinghua.edu.cn/simple/

下面是常用的几个源推荐:

  1. //清华源:
  2. https://pypi.tuna.tsinghua.edu.cn/simple/
  3. //中科大学:
  4. https://pypi.mirrors.ustc.edu.cn/simple/
  5. //华科大:
  6. http://pypi.hustunique.com/simple/
  7. //上海交大:
  8. https://mirror.sjtu.edu.cn/pypi/web/simple/
  9. //豆瓣:
  10. http://pypi.douban.com/simple/
  11. //山东理工:
  12. http://pypi.sdutlinux.org/
  13. //阿里云
  14. https://mirrors.aliyun.com/pypi/simple/

这里的源参考来源:国内常见pip使用镜像源地址_清华镜像源-CSDN博客

 下载好了之后在解释器查看

3.过程设计

二.代码部分

代码使用的别人的,但是根据我的使用情况做了一些调整,原始代码出处:

opencv+python+pycharm实现人脸识别_pycharm怎么关闭摄像头-CSDN博客

1.代码分析

导入库文件:

  1. import cv2 as cv#引入OpenCV库,并使用cv作为库的别名
  2. import imutils#图像处理工具库,可以简化常见的图像操作
  3. cv.ocl.setUseOpenCL(False)#禁止利用GPU等设备来加速图像处理和计算任务。
这里cv.ocl.setUseOpenCL(False)是因为不用GPU,而且报错,就删掉了openCL的库,也禁用它,如果你的电脑有GPU就把这句删掉就可以了。

打开摄像头读取每一帧,并转为灰度图片

  1. while (camera.isOpened()): # 从摄像头读取图片
  2. success, img = camera.read()#读取图像帧
  3. if not success:
  4. break
  5. gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY) # 转为灰度图片

初始化人脸检测分类器,这里要找到你的这个工程目录下的site-packages里面的.xml文件。

  1. # 加载OpenCV人脸检测分类器
  2. face_cascade = cv.CascadeClassifier(
  3. "D:\python23\Facetext\.venv\Lib\site-packages\cv2\data\haarcascade_frontalface_default.xml")
  4. recognizer = cv.face.LBPHFaceRecognizer_create()

分类器检测人脸,得到一个合适的窗口顶点坐标,高度,宽度

  1. face_detector = face_cascade#face_cascade的人脸检测器
  2. faces = face_detector.detectMultiScale(gray, 1.1, 5, 0, (W_size, H_size))#face_detector.detectMultiScale()用于检测输入图像中的人脸

这里调用face_detector(即face_cascade)的detectMultiScale方法来检测灰度图像gray中的人脸,然后返回一个四元组(x, y, w, h),其中(x, y)是矩形左上角的坐标,w是矩形的宽度,h是矩形的高度。​​​​​​​

遍历人脸图片,生成数组

  1. for imagePath in imagePaths:#打开图片,灰度化
  2. PIL_img = Image.open(imagePath).convert('L') #把图像转换为数组,
  3. img_numpy = np.array(PIL_img,'uint8')#获取图片人脸特征
  4. faces = face_detecter.detectMultiScale(img_numpy)#获取每张图片的id和姓名
  5. id = int(os.path.split(imagePath)[1].split('.')[0])#预防无面容照片
  6. for x,y,w,h in faces:
  7. ids.append(id)
  8. faceSamples.append(img_numpy[y:y+h,x:x+w]) #打印脸部特征和id
  9. print('id:',id)
  10. print('fs:',faceSamples)
  11. return faceSamples,ids

对比置信度,判断为存储的人像还是其他

  1. ids, confidence = recognizer.predict(gray_img[y:y + h, x:x + w])
  2. if confidence > 70:
  3. img = cv2AddChineseText(img, "外来人员(" + str(int(confidence)) + ")", (x + 10, y + 10), (0, 255, 0), 30)
  4. else:
  5. img = cv2AddChineseText(img, str(names[idn.index(ids)]) + "(" + str(int(confidence)) + ")",(x + 10, y - 25), (0, 255, 0), 30)
2.完整代码

代码分为了三个.py文件,face_collection,face_training,face_detection

其中face_collection(提前设置一个文件夹去存放采集到的图片)

face_training(提前设置一个文件夹去存放.xml模型文件)

1.face_collection
  1. import cv2 as cv#引入OpenCV库,并使用cv作为库的别名
  2. import imutils#图像处理工具库,可以简化常见的图像操作
  3. cv.ocl.setUseOpenCL(False)#禁止利用GPU等设备来加速图像处理和计算任务。
  4. #人脸采集
  5. def get_face(face_cascade, recognizer, camera, face_id, face_name, W_size, H_size, maximums_picture):
  6. #定义get_face,该函数接受参数face_cascade、recognizer、camera、face_id、face_name、W_size、H_size和maximums_picture。
  7. #从摄像头捕获人脸图像,并使用级联分类器(face_cascade)和识别器(recognizer)来检测和识别人脸。
  8. print("正在从摄像头采集新人脸信息 \n")
  9. picture_num = 0 # 设置录入照片的初始编号
  10. while (camera.isOpened()): # 从摄像头读取图片
  11. success, img = camera.read()#读取图像帧
  12. if not success:
  13. break
  14. gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY) # 转为灰度图片
  15. #具体用法如下:dst_image = cv.cvtColor(src_image, code[, dstCn])
  16. #src_image 是输入图像
  17. #code 是颜色空间转换的标志,cv.COLOR_BGR2GRAY(BGR 到灰度)
  18. face_detector = face_cascade#face_cascade的人脸检测器
  19. faces = face_detector.detectMultiScale(gray, 1.1, 5, 0, (W_size, H_size))#face_detector.detectMultiScale()用于检测输入图像中的人脸
  20. for (x, y, w, h) in faces: # 矩形框选人脸(xy为左上角的坐标,w为宽,h为高)
  21. cv.rectangle(img, (x, y), (x + w, y + h), (255, 0, 0))#函数在图像上绘制矩形框
  22. picture_num += 1 # 照片编号加一
  23. t = face_name
  24. d = face_id
  25. # 截取人脸部分,保存图片,图片名格式为:人脸唯一编号.人脸姓名.camera照片编号.jpg
  26. cv.imencode(".jpg", img[y:y + h, x:x + w])[1].tofile(
  27. "D:\\python23\\Facetext\\picture\\" + str(d) + "." + str(t) + ".camera" + str(picture_num) + ".jpg")
  28. print('保存图片:' + str(d) + "." + str(t) + ".camera" + str(picture_num) + ".jpg")
  29. # 采集规定数量人脸后退出
  30. if picture_num > maximums_picture:#定义数目
  31. break
  32. cv.namedWindow("ShowFace", cv.WINDOW_AUTOSIZE) # 命名窗口
  33. img = imutils.resize(img, height=800)
  34. cv.imshow("ShowFace", img)
  35. k = cv.waitKey(1) & 0xFF
  36. if k == ord(' '):
  37. break
  38. if __name__ == '__main__':
  39. #face_id = 0 # 该人脸的唯一编号
  40. face_id = input("请输入人脸编号: ")
  41. face_name = input("请输入人脸的名字: ")
  42. maximums_picture = 200 # 设置人脸照片数量的上限
  43. # 加载OpenCV人脸检测分类器
  44. face_cascade = cv.CascadeClassifier(
  45. "D:\python23\Facetext\.venv\Lib\site-packages\cv2\data\haarcascade_frontalface_default.xml")
  46. recognizer = cv.face.LBPHFaceRecognizer_create()
  47. camera = cv.VideoCapture(0) # 0:电脑摄像头, 2是外接的摄像头
  48. # 网络摄像头,iphone可以安装免费APP:IP摄像头Lite
  49. # camera = cv.VideoCapture("http://admin:123456@192.168.137.20:8081/video")
  50. W_size = int(0.1 * camera.get(3)) # 在视频流的帧的宽度
  51. H_size = int(0.1 * camera.get(4)) # 在视频流的帧的高度
  52. print(str(W_size) + '×' + str(H_size))
  53. get_face(face_cascade, recognizer, camera, face_id, face_name, W_size, H_size, maximums_picture)
  54. #获取人脸的函数。它接受的参数包括:
  55. #face_cascade:人脸级联分类器,用于检测和识别人脸。
  56. #recognizer:人脸识别器,用于识别已知的人脸。
  57. #camera:相机设备,用于捕获图像或视频流。
  58. #face_id:人脸ID,用于标识不同的人脸。
  59. #face_name:人脸名称,用于关联人脸ID和人脸的姓名。3
  60. #W_size 和 H_size:图像或视频流的宽度和高度尺寸。
  61. #maximums_picture:最大图像数量,用于限制获取的人脸图像数量。
  62. camera.release()
  63. cv.destroyAllWindows()
2.face_training
  1. import os#os模块可以用于文件路径操作、目录创建等操作
  2. import cv2 as cv#导入 OpenCV 库,并将其命名为 cv
  3. from PIL import Image#PIL模块是Python Imaging Library,用于图像处理和操作
  4. import numpy as np#导入numpy做数学计算,和数组变换
  5. def getImageAndLabels(path):#获取图片
  6. #存储人脸数据
  7. faceSamples = []
  8. #存储姓名数据
  9. ids=[]
  10. #储存图片信息
  11. imagePaths = [os.path.join(path,f) for f in os.listdir(path)]
  12. #os.path.join(path, f) 用于将路径 path 和文件名 f 连接起来,生成完整的文件路径。
  13. #os.listdir(path) 函数用于获取指定路径下的所有文件和目录的名称,并返回一个字符串列表
  14. #print(imagePaths)
  15. #人脸检测分类器
  16. face_detecter = cv.CascadeClassifier("D:\python23\Facetext\.venv\Lib\site-packages\cv2\data\haarcascade_frontalface_default.xml")
  17. #遍历列表中的图片
  18. for imagePath in imagePaths:#打开图片,灰度化
  19. PIL_img = Image.open(imagePath).convert('L') #把图像转换为数组,
  20. img_numpy = np.array(PIL_img,'uint8')#获取图片人脸特征
  21. faces = face_detecter.detectMultiScale(img_numpy)#获取每张图片的id和姓名
  22. id = int(os.path.split(imagePath)[1].split('.')[0])#预防无面容照片
  23. for x,y,w,h in faces:
  24. ids.append(id)
  25. faceSamples.append(img_numpy[y:y+h,x:x+w]) #打印脸部特征和id
  26. print('id:',id)
  27. print('fs:',faceSamples)
  28. return faceSamples,ids
  29. if __name__ == '__main__':
  30. #图片路径
  31. path = "D:\python23\Facetext\picture\\"
  32. #获取图像数组和id标签数组
  33. faces,ids = getImageAndLabels(path) #加载识别器
  34. recognizer = cv.face.LBPHFaceRecognizer_create()
  35. #调用 cv.face.LBPHFaceRecognizer_create(),你正在初始化一个可以用于后续训练和识别人脸的模型。
  36. recognizer.train(faces,np.array(ids))#识别器如何根据给定的图像和标签数据来“学习”识别不同的人脸
  37. #保存文件
  38. recognizer.write('D:\\python23\\Facetext\\face_trainer\\face_trainer.xml')
3.face_detection
  1. import cv2 as cv
  2. import imutils
  3. from PIL import ImageDraw, ImageFont, Image
  4. import numpy as np
  5. import os
  6. def cv2AddChineseText(img, text, position, textColor=(0, 255, 0), textSize=30):
  7. if (isinstance(img, np.ndarray)): # 判断是否OpenCV图片类型
  8. img = Image.fromarray(cv.cvtColor(img, cv.COLOR_BGR2RGB))
  9. # 创建一个可以在给定图像上绘图的对象
  10. draw = ImageDraw.Draw(img)
  11. # 字体的格式
  12. fontStyle = ImageFont.truetype("simsun.ttc", textSize, encoding="utf-8")
  13. # 绘制文本
  14. draw.text(position, text, textColor, font=fontStyle)
  15. # 转换回OpenCV格式
  16. return cv.cvtColor(np.asarray(img), cv.COLOR_RGB2BGR)
  17. def name():
  18. path = "D:\\python23\\Facetext\\picture\\"
  19. names = []
  20. # 对应的标签
  21. idn = []
  22. # 准备识别的图片
  23. imagePaths = [os.path.join(path, f) for f in os.listdir(path)]
  24. for imagePath in imagePaths:
  25. name = str(os.path.split(imagePath)[1].split('.')[1])
  26. id = int(os.path.split(imagePath)[1].split('.')[0]) #预防无面容照片
  27. # 避免重复
  28. if id not in idn:
  29. names.append(name)
  30. idn.append(id)
  31. return names, idn
  32. # 人脸检测
  33. def face_detect_method(img, names, idn):
  34. gray_img = cv.cvtColor(img, cv.COLOR_BGRA2GRAY)
  35. imgsize = min(gray_img.shape) # 灰度图长宽最小尺寸
  36. facemin = int(imgsize * 0.04)
  37. facemax = int(imgsize * 0.8)
  38. # 加载训练数据集文件
  39. recognizer = cv.face.LBPHFaceRecognizer_create()
  40. # 读取训练好的系统文件
  41. recognizer.read('D:\\python23\\Facetext\\face_trainer\\face_trainer.xml')
  42. face_detector = cv.CascadeClassifier(
  43. "D:\python23\Facetext\.venv\Lib\site-packages\cv2\data\haarcascade_frontalface_alt2.xml")
  44. #人脸检测级联分类器模型,采用的是基于树的分类器结构,相比于前面的模型,对于一些复杂情况下的人脸检测可能会更准确,但可能需要更长的计算时间
  45. face = face_detector.detectMultiScale(gray_img, 1.1, 3, 0, (facemin, facemin), (facemax, facemax))
  46. for x, y, w, h in face:
  47. cv.rectangle(img, (x, y), (x + w, y + h), color=(255, 255, 0), thickness=3)
  48. # 人脸识别
  49. ids, confidence = recognizer.predict(gray_img[y:y + h, x:x + w])
  50. if confidence > 70:
  51. img = cv2AddChineseText(img, "外来人员(" + str(int(confidence)) + ")", (x + 10, y + 10), (0, 255, 0), 30)
  52. else:
  53. img = cv2AddChineseText(img, str(names[idn.index(ids)]) + "(" + str(int(confidence)) + ")",(x + 10, y - 25), (0, 255, 0), 30)
  54. cv.namedWindow("ShowFace", cv.WINDOW_AUTOSIZE) # 命名窗口
  55. img = imutils.resize(img, width=850)
  56. cv.imshow("ShowFace", img)
  57. return img
  58. cap = cv.VideoCapture(0)
  59. #cap = cv.VideoCapture(camera_id)
  60. num = 1
  61. # 读取姓名
  62. names, idn = name()
  63. while (cap.isOpened()):
  64. ret, frame = cap.read()
  65. if not ret:
  66. break
  67. img = face_detect_method(frame, names, idn)
  68. k = cv.waitKey(1) & 0xFF
  69. if k == ord('s'):
  70. cv.imwrite("E:\\Python_Program\\figs\\save\\people" + str(num) + ".face.jpg", img)
  71. print("Saved people" + str(num) + "'s face!!")
  72. num += 1
  73. elif k == ord(' '):
  74. break
  75. #空格键退出
  76. cap.release()
  77. cv.destroyAllWindows()

三.效果演示

写入一个标签0,名称为“老李”,获取人脸:

训练模型:

导入第二个人脸,标签为3,名称为“ll”:

识别出两人:

多人识别也能搞定:

四.问题与解决方法

1.python和opencv版本不对应,报错

对应版本可以看这个博文:Python版本与opencv版本的对应关系_opencv-python对应版本-CSDN博客

2.使用的外接摄像头打不开

将代码部分摄像头编号从0改成2,3等就好了

4.faces = detector.detectMultiScale(img_numpy) # 人脸检测
cv2.error: OpenCV(3.4.11) C:\Users\appveyor\AppData\Local\Temp\1\pip-req-build-9ii_q38u\opencv\modules\objdetect\src\cascadedetect.cpp:1729: error: (-215:Assertion failed) !empty() in function 'cv::CascadeClassifier::detectMultiScale'

这个报错表明在进行人脸检测时,CascadeClassifier 检测器未成功加载分类器模型文件导致的问题。在使用 detectMultiScale() 函数之前,需要确保已经成功加载了人脸检测的分类器 XML 文件。其实就是路径要找对。
5.File "D:\python23\Facetext\face_training.py", line 47, in <module>
recognizer.write("D:\python23\Facetext\face_trainer\\trainer.yml")
cv2.error: OpenCV(3.4.11) C:\Users\appveyor\AppData\Local\Temp\1\pip-req-build-9ii_q38u\opencv_contrib\modules\face\src\facerec.cpp:70: error: (-2:Unspecified error) File can't be opened for writing! in function 'cv::face::FaceRecognizer::write'

这个错误提示表明 OpenCV 在尝试将人脸识别器的训练结果写入指定的文件时遇到了问题。具体原因是因为文件无法被打开进行写入操作

6.cv2.error: OpenCV(3.4.11) C:\Users\appveyor\AppData\Local\Temp\1\pip-req-build-9ii_q38u\opencv\modules\core\src\ocl.cpp:5518: error: (-220:Unknown error code -220) OpenCL error CL_INVALID_COMMAND_QUEUE (-36) during call: clEnqueueWriteBuffer(q, handle=000002BD87B27A20, CL_TRUE, offset=0, sz=186432, data=000002BD87B6D820, 0, 0, 0) in function 'cv::ocl::OpenCLAllocator::upload'

表明在使用 OpenCV 进行 OpenCL 相关操作时出现了 CL_INVALID_COMMAND_QUEUE (-36) 错误。这种错误通常是由于 OpenCL 中的命令队列无效或者已经关闭导致的。
这个时候可以禁用opencl也就是cv2.ocl.setUseOpenCL(False),
7. recognizer = cv2.face.LBPHFaceRecognizer_create()
AttributeError: module 'cv2.cv2' has no attribute 'face'

这个问题也就是说opencv里面没有cv2库,由于版本问题,很多版本的cv2已经被包含在opencv-contrib-python里面了,所以根据版本去下载opencv和opencv-contrib-python就可以解决这个问题

8.AttributeError: module 'cv2.cv2' has no attribute 'face_LBPHFaceRecognizer'

可能是由于OpenCV版本不同导致的方法名称不匹配。在新版本的OpenCV中,可能已经对LBPH人脸识别器的方法进行了更改。所以这个问题还是跟版本有关系,找到合适的版本就可以解决了。

OK了,这就是这次的全部内容了,还是一样,希望对大家有微薄的帮助,如果有什么问题,也希望大家能提出。

本文内容由网友自发贡献,转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号