赞
踩
最近想做一个人脸识别,正好手上面有一块树莓派4B,借这个机会正好把树莓派玩一下。
树莓派(树莓派最好还是搞个风扇,不然又烫又卡)
摄像头(随便找的一块,不是很好,但是够用)
pycharm:
如果需要下载可以直接去官网下载,分为社区版和专业版,其中社区版免费但是被阉割过了,缺少部分功能,专业版功能强大,但是需付费,专业版许可证和账号可以去淘宝买,不会超过十块钱。
(1)资料查找
OpenCV是一个基于Apache2.0许可(开源)发行的跨平台计算机视觉和机器学习软件库,可以运行在Linux、Windows、Android和Mac OS操作系统上。 它轻量级而且高效——由一系列 C 函数和少量 C++ 类构成,同时提供了Python、Ruby、MATLAB等语言的接口,实现了图像处理和计算机视觉方面的很多通用算法。
(2)库文件安装:下载opencv和扩展包。
这里的opencv的两个包区别:
1.opencv-python 只包含了主要模块的包
2.opencv-contrib-python 包含了主要模块以及扩展模块
pycharm终端命令行输入pip指令,但是注意自己的opencv版本和python环境版本对应。
- pip install opencv-python
- pip install opencv-contrib-python
输入 python -V 或者 python --version
- python -V
- python --version
如果下载缓慢或者异常中断,可以加入国内镜像源去安装,例如
- pip install <安装包> -i https://pypi.tuna.tsinghua.edu.cn/simple/
-
下面是常用的几个源推荐:
- //清华源:
- https://pypi.tuna.tsinghua.edu.cn/simple/
- //中科大学:
- https://pypi.mirrors.ustc.edu.cn/simple/
- //华科大:
- http://pypi.hustunique.com/simple/
- //上海交大:
- https://mirror.sjtu.edu.cn/pypi/web/simple/
- //豆瓣:
- http://pypi.douban.com/simple/
- //山东理工:
- http://pypi.sdutlinux.org/
- //阿里云
- https://mirrors.aliyun.com/pypi/simple/
这里的源参考来源:国内常见pip使用镜像源地址_清华镜像源-CSDN博客
下载好了之后在解释器查看
代码使用的别人的,但是根据我的使用情况做了一些调整,原始代码出处:
opencv+python+pycharm实现人脸识别_pycharm怎么关闭摄像头-CSDN博客
导入库文件:
- import cv2 as cv#引入OpenCV库,并使用cv作为库的别名
- import imutils#图像处理工具库,可以简化常见的图像操作
- cv.ocl.setUseOpenCL(False)#禁止利用GPU等设备来加速图像处理和计算任务。
这里cv.ocl.setUseOpenCL(False)是因为不用GPU,而且报错,就删掉了openCL的库,也禁用它,如果你的电脑有GPU就把这句删掉就可以了。
打开摄像头读取每一帧,并转为灰度图片
- while (camera.isOpened()): # 从摄像头读取图片
- success, img = camera.read()#读取图像帧
- if not success:
- break
- gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY) # 转为灰度图片
初始化人脸检测分类器,这里要找到你的这个工程目录下的site-packages里面的.xml文件。
- # 加载OpenCV人脸检测分类器
- face_cascade = cv.CascadeClassifier(
- "D:\python23\Facetext\.venv\Lib\site-packages\cv2\data\haarcascade_frontalface_default.xml")
- recognizer = cv.face.LBPHFaceRecognizer_create()
分类器检测人脸,得到一个合适的窗口顶点坐标,高度,宽度
- face_detector = face_cascade#face_cascade的人脸检测器
- 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
是矩形的高度。
遍历人脸图片,生成数组
- for imagePath in imagePaths:#打开图片,灰度化
- PIL_img = Image.open(imagePath).convert('L') #把图像转换为数组,
- img_numpy = np.array(PIL_img,'uint8')#获取图片人脸特征
- faces = face_detecter.detectMultiScale(img_numpy)#获取每张图片的id和姓名
- id = int(os.path.split(imagePath)[1].split('.')[0])#预防无面容照片
- for x,y,w,h in faces:
- ids.append(id)
- faceSamples.append(img_numpy[y:y+h,x:x+w]) #打印脸部特征和id
- print('id:',id)
- print('fs:',faceSamples)
- return faceSamples,ids
对比置信度,判断为存储的人像还是其他
- ids, confidence = recognizer.predict(gray_img[y:y + h, x:x + w])
- if confidence > 70:
- img = cv2AddChineseText(img, "外来人员(" + str(int(confidence)) + ")", (x + 10, y + 10), (0, 255, 0), 30)
- else:
- img = cv2AddChineseText(img, str(names[idn.index(ids)]) + "(" + str(int(confidence)) + ")",(x + 10, y - 25), (0, 255, 0), 30)
代码分为了三个.py文件,face_collection,face_training,face_detection
其中face_collection(提前设置一个文件夹去存放采集到的图片)
face_training(提前设置一个文件夹去存放.xml模型文件)
-
- import cv2 as cv#引入OpenCV库,并使用cv作为库的别名
- import imutils#图像处理工具库,可以简化常见的图像操作
- cv.ocl.setUseOpenCL(False)#禁止利用GPU等设备来加速图像处理和计算任务。
-
- #人脸采集
- def get_face(face_cascade, recognizer, camera, face_id, face_name, W_size, H_size, maximums_picture):
- #定义get_face,该函数接受参数face_cascade、recognizer、camera、face_id、face_name、W_size、H_size和maximums_picture。
- #从摄像头捕获人脸图像,并使用级联分类器(face_cascade)和识别器(recognizer)来检测和识别人脸。
- print("正在从摄像头采集新人脸信息 \n")
- picture_num = 0 # 设置录入照片的初始编号
- while (camera.isOpened()): # 从摄像头读取图片
- success, img = camera.read()#读取图像帧
- if not success:
- break
- gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY) # 转为灰度图片
- #具体用法如下:dst_image = cv.cvtColor(src_image, code[, dstCn])
- #src_image 是输入图像
- #code 是颜色空间转换的标志,cv.COLOR_BGR2GRAY(BGR 到灰度)
-
- face_detector = face_cascade#face_cascade的人脸检测器
- faces = face_detector.detectMultiScale(gray, 1.1, 5, 0, (W_size, H_size))#face_detector.detectMultiScale()用于检测输入图像中的人脸
- for (x, y, w, h) in faces: # 矩形框选人脸(xy为左上角的坐标,w为宽,h为高)
- cv.rectangle(img, (x, y), (x + w, y + h), (255, 0, 0))#函数在图像上绘制矩形框
- picture_num += 1 # 照片编号加一
- t = face_name
- d = face_id
- # 截取人脸部分,保存图片,图片名格式为:人脸唯一编号.人脸姓名.camera照片编号.jpg
- cv.imencode(".jpg", img[y:y + h, x:x + w])[1].tofile(
- "D:\\python23\\Facetext\\picture\\" + str(d) + "." + str(t) + ".camera" + str(picture_num) + ".jpg")
- print('保存图片:' + str(d) + "." + str(t) + ".camera" + str(picture_num) + ".jpg")
- # 采集规定数量人脸后退出
- if picture_num > maximums_picture:#定义数目
- break
- cv.namedWindow("ShowFace", cv.WINDOW_AUTOSIZE) # 命名窗口
- img = imutils.resize(img, height=800)
- cv.imshow("ShowFace", img)
- k = cv.waitKey(1) & 0xFF
- if k == ord(' '):
- break
-
-
- if __name__ == '__main__':
- #face_id = 0 # 该人脸的唯一编号
- face_id = input("请输入人脸编号: ")
- face_name = input("请输入人脸的名字: ")
- maximums_picture = 200 # 设置人脸照片数量的上限
-
-
- # 加载OpenCV人脸检测分类器
- face_cascade = cv.CascadeClassifier(
- "D:\python23\Facetext\.venv\Lib\site-packages\cv2\data\haarcascade_frontalface_default.xml")
- recognizer = cv.face.LBPHFaceRecognizer_create()
-
- camera = cv.VideoCapture(0) # 0:电脑摄像头, 2是外接的摄像头
- # 网络摄像头,iphone可以安装免费APP:IP摄像头Lite
- # camera = cv.VideoCapture("http://admin:123456@192.168.137.20:8081/video")
-
- W_size = int(0.1 * camera.get(3)) # 在视频流的帧的宽度
- H_size = int(0.1 * camera.get(4)) # 在视频流的帧的高度
- print(str(W_size) + '×' + str(H_size))
-
- get_face(face_cascade, recognizer, camera, face_id, face_name, W_size, H_size, maximums_picture)
- #获取人脸的函数。它接受的参数包括:
- #face_cascade:人脸级联分类器,用于检测和识别人脸。
- #recognizer:人脸识别器,用于识别已知的人脸。
- #camera:相机设备,用于捕获图像或视频流。
- #face_id:人脸ID,用于标识不同的人脸。
- #face_name:人脸名称,用于关联人脸ID和人脸的姓名。3
- #W_size 和 H_size:图像或视频流的宽度和高度尺寸。
- #maximums_picture:最大图像数量,用于限制获取的人脸图像数量。
- camera.release()
- cv.destroyAllWindows()
- import os#os模块可以用于文件路径操作、目录创建等操作
- import cv2 as cv#导入 OpenCV 库,并将其命名为 cv
- from PIL import Image#PIL模块是Python Imaging Library,用于图像处理和操作
- import numpy as np#导入numpy做数学计算,和数组变换
-
- def getImageAndLabels(path):#获取图片
- #存储人脸数据
- faceSamples = []
- #存储姓名数据
- ids=[]
- #储存图片信息
- imagePaths = [os.path.join(path,f) for f in os.listdir(path)]
- #os.path.join(path, f) 用于将路径 path 和文件名 f 连接起来,生成完整的文件路径。
- #os.listdir(path) 函数用于获取指定路径下的所有文件和目录的名称,并返回一个字符串列表
- #print(imagePaths)
- #人脸检测分类器
- face_detecter = cv.CascadeClassifier("D:\python23\Facetext\.venv\Lib\site-packages\cv2\data\haarcascade_frontalface_default.xml")
- #遍历列表中的图片
- for imagePath in imagePaths:#打开图片,灰度化
- PIL_img = Image.open(imagePath).convert('L') #把图像转换为数组,
- img_numpy = np.array(PIL_img,'uint8')#获取图片人脸特征
- faces = face_detecter.detectMultiScale(img_numpy)#获取每张图片的id和姓名
- id = int(os.path.split(imagePath)[1].split('.')[0])#预防无面容照片
- for x,y,w,h in faces:
- ids.append(id)
- faceSamples.append(img_numpy[y:y+h,x:x+w]) #打印脸部特征和id
- print('id:',id)
- print('fs:',faceSamples)
- return faceSamples,ids
-
- if __name__ == '__main__':
- #图片路径
- path = "D:\python23\Facetext\picture\\"
- #获取图像数组和id标签数组
- faces,ids = getImageAndLabels(path) #加载识别器
- recognizer = cv.face.LBPHFaceRecognizer_create()
- #调用 cv.face.LBPHFaceRecognizer_create(),你正在初始化一个可以用于后续训练和识别人脸的模型。
- recognizer.train(faces,np.array(ids))#识别器如何根据给定的图像和标签数据来“学习”识别不同的人脸
- #保存文件
- recognizer.write('D:\\python23\\Facetext\\face_trainer\\face_trainer.xml')
- import cv2 as cv
- import imutils
- from PIL import ImageDraw, ImageFont, Image
- import numpy as np
- import os
- def cv2AddChineseText(img, text, position, textColor=(0, 255, 0), textSize=30):
- if (isinstance(img, np.ndarray)): # 判断是否OpenCV图片类型
- img = Image.fromarray(cv.cvtColor(img, cv.COLOR_BGR2RGB))
- # 创建一个可以在给定图像上绘图的对象
- draw = ImageDraw.Draw(img)
- # 字体的格式
- fontStyle = ImageFont.truetype("simsun.ttc", textSize, encoding="utf-8")
- # 绘制文本
- draw.text(position, text, textColor, font=fontStyle)
- # 转换回OpenCV格式
- return cv.cvtColor(np.asarray(img), cv.COLOR_RGB2BGR)
-
- def name():
- path = "D:\\python23\\Facetext\\picture\\"
- names = []
- # 对应的标签
- idn = []
- # 准备识别的图片
- 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])
- id = int(os.path.split(imagePath)[1].split('.')[0]) #预防无面容照片
- # 避免重复
- if id not in idn:
- names.append(name)
- idn.append(id)
- return names, idn
-
- # 人脸检测
- def face_detect_method(img, names, idn):
- gray_img = cv.cvtColor(img, cv.COLOR_BGRA2GRAY)
- imgsize = min(gray_img.shape) # 灰度图长宽最小尺寸
- facemin = int(imgsize * 0.04)
- facemax = int(imgsize * 0.8)
- # 加载训练数据集文件
- recognizer = cv.face.LBPHFaceRecognizer_create()
- # 读取训练好的系统文件
- recognizer.read('D:\\python23\\Facetext\\face_trainer\\face_trainer.xml')
- face_detector = cv.CascadeClassifier(
- "D:\python23\Facetext\.venv\Lib\site-packages\cv2\data\haarcascade_frontalface_alt2.xml")
- #人脸检测级联分类器模型,采用的是基于树的分类器结构,相比于前面的模型,对于一些复杂情况下的人脸检测可能会更准确,但可能需要更长的计算时间
-
- face = face_detector.detectMultiScale(gray_img, 1.1, 3, 0, (facemin, facemin), (facemax, facemax))
- for x, y, w, h in face:
- cv.rectangle(img, (x, y), (x + w, y + h), color=(255, 255, 0), thickness=3)
- # 人脸识别
- ids, confidence = recognizer.predict(gray_img[y:y + h, x:x + w])
- if confidence > 70:
- img = cv2AddChineseText(img, "外来人员(" + str(int(confidence)) + ")", (x + 10, y + 10), (0, 255, 0), 30)
- else:
- img = cv2AddChineseText(img, str(names[idn.index(ids)]) + "(" + str(int(confidence)) + ")",(x + 10, y - 25), (0, 255, 0), 30)
-
- cv.namedWindow("ShowFace", cv.WINDOW_AUTOSIZE) # 命名窗口
- img = imutils.resize(img, width=850)
- cv.imshow("ShowFace", img)
- return img
-
- cap = cv.VideoCapture(0)
- #cap = cv.VideoCapture(camera_id)
- num = 1
- # 读取姓名
- names, idn = name()
- while (cap.isOpened()):
- ret, frame = cap.read()
- if not ret:
- break
- img = face_detect_method(frame, names, idn)
-
- k = cv.waitKey(1) & 0xFF
- if k == ord('s'):
-
- cv.imwrite("E:\\Python_Program\\figs\\save\\people" + str(num) + ".face.jpg", img)
- print("Saved people" + str(num) + "'s face!!")
- num += 1
- elif k == ord(' '):
- break
- #空格键退出
- cap.release()
- 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了,这就是这次的全部内容了,还是一样,希望对大家有微薄的帮助,如果有什么问题,也希望大家能提出。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。