Py学习记录
Python 常规学习
Python学习笔记(一)
Python学习笔记(二)
Python学习笔记(三)
Python学习笔记(四)
Python学习笔记(五)
Python学习笔记(六)
Python学习笔记(七)
Python习题(一)
Python习题(二)
Python习题(三)
Python习题(四)
Python习题(五)
Python常见Bug
Python编程环境
Python-依赖安装(三方库)
Python-VS Code
pip-换源
py 程序转 exe
Python-打开选择文件对话框
Python 项目
Python-密码学
Python-与佛伦禅
Python-喵语翻译
Python-翻译服务器
Python-邮件发送
Python-自动签到
Python-自动签到(Post请求)
Python-自动签到(模拟操作)
Python-图片添加二维码
Python-数据可视化
Python-端口扫描器
Python-未测试项目
Python-虚拟环境
Python-临时环境
Python-venv虚拟环境
Python-Conda
Python-OpenCV
OpenCV-人脸识别
Python-PyTorch
本文档使用 MrDoc 发布
-
+
首页
OpenCV-人脸识别
## 环境准备 需要下载并解压 [OpenCV最新源码](https://opencv.org/releases/) `Sources` 的就是 我们会用到 `...\data\haarcascades[_cuda]\` 下面预训练好的Haar特征级联分类器模型 **Haar特征级联分类器模型:** - haarcascade_eye.xml:用于眼睛检测的级联分类器模型。它可以用于检测图像或视频中的眼睛 - haarcascade_eye_tree_eyeglasses.xml:用于眼镜和眼睛联合检测的级联分类器模型。它可以检测图像或视频中戴眼镜的眼睛 - haarcascade_frontalface_default.xml:这是用于人脸检测的默认级联分类器模型。它是OpenCV中最常用的人脸检测模型之一,用于在图片或视频中检测正脸 - haarcascade_frontalface_alt.xml:这是另一种人脸检测级联分类器模型,相对于默认模型,这个模型在检测率上有所提升,但可能会产生一些误检测 - haarcascade_frontalface_alt2.xml:这是haarcascade_frontalface_alt.xml模型的改进版本,在保持较高检测率的同时,尽可能减少了误检测 - haarcascade_frontalface_alt_tree.xml:这也是一种人脸检测级联分类器模型,采用的是基于树的分类器结构,相比于前面的模型,对于一些复杂情况下的人脸检测可能会更准确,但可能需要更长的计算时间 - haarcascade_fullbody.xml:用于全身人体检测的级联分类器模型。它可用于在图像或视频中检测整个人体 - haarcascade_lefteye_2splits.xml:用于检测左眼的级联分类器模型。它可以用于检测图像或视频中的左眼 - haarcascade_righteye_2splits.xml:用于检测右眼的级联分类器模型。它可以用于检测图像或视频中的右眼 - haarcascade_lowerbody.xml:用于下半身人体检测的级联分类器模型。它可用于检测图像或视频中的下半身(例如腿部) - haarcascade_profileface.xml:用于侧脸检测的级联分类器模型。它可以用于检测图像或视频中的侧脸 - haarcascade_smile.xml:这是用于微笑检测的级联分类器模型。它可以用于在图像或视频中检测人脸上的微笑区域 - haarcascade_upperbody.xml:这是用于上半身人体检测的级联分类器模型。它可用于在图像或视频中检测上半身(例如头部和肩部) ```bash pip install opencv-python opencv-contrib-python # 安装机器学习算法和工具的库 ## CPU版 anaconda search -t conda dlib-cpu # 搜索dlib-cpu相关包 conda install -c https://conda.anaconda.org/conda-forge dlib-cpu # 指定从conda-forge(URL形式)安装dlib-cpu ## GPU版 anaconda search -t conda dlib-gpu # 搜索dlib-gpu相关包 conda install -c conda-forge dlib-gpu cudatoolkit=11.8 # 指定从conda-forge安装dlib-gpu,并指定cudatoolkit版本(conda会自动安装依赖) ``` ## 拍照采集 ```python # -*- coding: utf-8 -*- import os # 加载os模块,用于操作文件和目录 import cv2 # 加载cv2模块,用于图像处理 def capture_video(source, image_path): """ 从视频源(RTSP流或USB摄像头)捕获视频帧并保存 :param source: 视频源(RTSP流地址或摄像头索引) :param image_path: 保存图片的基础路径 """ # 根据视频源类型创建VideoCapture对象 if source.startswith('rtsp://'): # 如果视频源是RTSP流 cap = cv2.VideoCapture(source) # 捕获RTSP视频帧 else: # 否则视为USB摄像头 cap = cv2.VideoCapture(int(source)) # 捕获USB视频帧 num = 1 # 初始化图片编号 while cap.isOpened(): # 检查是否成功打开视频源 ret, frame = cap.read() # 读取一帧视频 cv2.imshow('Photograph', frame) # 显示当前帧 k = cv2.waitKey(1) & 0xFF # 等待按键输入(1ms),用于判断按键 if k == ord(' '): # 按下空格键,保存图片 cv2.imwrite('{}/{}.jpg'.format(image_path, num), frame) # 保存图片 print(f"{image_path}/{num}.jpg 已保存") # 打印保存路径 num += 1 # 图片编号加1 elif k == ord('Q') or k == ord('q'): # 按下Q键退出 break # 退出循环 cap.release() # 释放视频源 cv2.destroyAllWindows() # 关闭所有窗口 if __name__ == "__main__": image_path = "./images/1.name" # 存储图片路径按 序号.人名 格式保存(人名随意) if not os.path.exists(image_path): # 如果路径不存在,则创建路径 os.makedirs(image_path) # 创建路径 # 视频源可以是RTSP流地址或USB摄像头索引(例如0、1等) # source = "rtsp://admin:admin@192.168.100.111:554/Streaming/Channels/101" # RTSP流地址示例 source = "0" # USB摄像头索引示例 capture_video(source, image_path) # 调用函数进行拍照采集 ``` ## 数据训练 ```python # -*- coding: utf-8 -*- import os # 加载os模块,用于操作文件和目录 import cv2 # 加载cv2模块,用于图像处理 from PIL import Image # 加载PIL模块,用于图像处理 import numpy as np # 加载numpy模块,用于数值计算 def load_images_and_labels(ModelPath,path): """ 从指定路径加载人脸数据和标签 :param ModelPath: 人脸检测模型路径 :param path: 人脸数据的根目录路径 :return: 人脸样本列表和对应的标签列表 """ face_samples = [] # 存储人脸样本 ids = [] # 存储对应的标签 face_cascade = cv2.CascadeClassifier(ModelPath) # 加载人脸检测模型 # 存储序号和人名的对应关系 id_name = {} dirs = os.listdir(path) # 获取当前路径下的所有文件夹 for dir_name in dirs: # 遍历每个文件夹 dir_path = os.path.join(path, dir_name) # 获取文件夹路径 if not os.path.isdir(dir_path): # 确保是文件夹 continue # 继续 # 获取文件夹下的图片(图片格式) image_paths = [os.path.join(dir_path, f) for f in os.listdir(dir_path) if f.endswith(('.png', '.jpg', '.jpeg'))] id = int(dir_name.split('.')[0]) # 获取id(文件夹名.前面的数字作为id) id_name[id] = dir_name.split('.')[1] # 存储人名 print(f"加载 样本{id}, 姓名 {id_name[id]}") for image_path in image_paths: # 遍历图片 try: pil_img = Image.open(image_path).convert('L') # 转换为灰度图 img_numpy = np.array(pil_img, 'uint8') # 转换为数组 faces = face_cascade.detectMultiScale(img_numpy) # 检测人脸 for (x, y, w, h) in faces: # 遍历人脸 face_samples.append(img_numpy[y:y + h, x:x + w]) # 添加人脸数据 ids.append(id) # 添加id except Exception as e: print(f"处理图像时出错 {image_path}: {e}") return face_samples, ids, id_name # 返回人脸样本、标签和人名 if __name__ == '__main__': # 获取人脸数据和姓名(模型路径,图片路径) faces, ids, id_name = load_images_and_labels('./opencv-4.10.0/data/haarcascades_cuda/haarcascade_frontalface_alt2.xml',\ './images') # 注意模型路径,若是CPU不带_cuda后缀;若是GPU带_cuda后缀 recognizer = cv2.face.LBPHFaceRecognizer_create() # 导入人脸识别模型 recognizer.train(faces, np.array(ids)) # 训练模型 recognizer.save('./data/face_trainer.yml') # 保存模型 # 打印训练结果 print("=========================================\n训练完成!总共训练了 {} 人".format(len(id_name))) for id, name in id_name.items(): print("序号:{},姓名:{},训练样本数量:{} 个".format(id, name, np.sum(np.array(ids) == id))) ``` ## 人脸识别 ```python # -*- coding: utf-8 -*- import cv2 # 导入opencv库,用于图像处理 import numpy as np # 导入numpy库,用于数值计算 from PIL import ImageFont, ImageDraw, Image # 导入PIL库,用于图像处理 import threading # 导入线程库,用于多线程处理 import time # 导入时间库,用于时间处理 import subprocess # 导入subprocess库,用于执行命令行命令 # 添加文字到图片 def cv2ImgAddText(img, text, left, top, textColor=(0, 0, 255), textSize=20): """ 文字转换为图片并添加到图片上 :param img: 需要添加文字的图片 :param text: 添加的文字 :param left: 文字X坐标 :param top: 文字Y坐标 :param textColor: 文字颜色 :param textSize: 文字大小 """ if isinstance(img, np.ndarray): # 判断是否OpenCV图片类型 img = Image.fromarray(cv2.cvtColor(img, cv2.COLOR_BGR2RGB)) # 转换为PIL图片 draw = ImageDraw.Draw(img) # 创建一个可以在给定图像上绘图的对象 fontStyle = ImageFont.truetype( font_path, textSize, encoding="utf-8") # 字体的格式 draw.text((left, top), text, textColor, font=fontStyle) # 绘制文本 return cv2.cvtColor(np.asarray(img), cv2.COLOR_RGB2BGR) # 转换回OpenCV格式 # 人脸检测并标识 def detect_face(src_img, textSize=20): """ 人脸检测并标识在图片上 :param src_img: 待检测图片 :param textSize: 文字大小 """ gray = cv2.cvtColor(src_img, cv2.COLOR_BGR2GRAY) # 灰度转换 faces = face_cascade.detectMultiScale(gray) # 灰度图像,缩放因子,最小邻域,最大邻域,最小尺寸,最大尺寸 for (x, y, w, h) in faces: # 绘制人脸矩形 cv2.rectangle(src_img, (x, y), (x + w, y + h), (0, 0, 255), 2) # 图片绘制框线,左上角坐标,右下角坐标,颜色,线宽 id, confidence = recognizer.predict(gray[y:y + h, x:x + w]) # 人脸识别 # 判断是否为训练集中的人脸 if confidence < 70: # 置信度小于70%则认为是已知人脸(根据实际情况调整) name = names[id] # 获取姓名 confidence = "{0}%".format(round(100 - confidence)) # 计算置信度 else: name = 'Unknown' # 设置未知姓名 confidence = "{0}%".format(round(100 - confidence)) # 设置置信度(保留用于查看调试) src_img = cv2ImgAddText(src_img, name, x + 5, y + 5, (255, 0, 0), textSize) # 绘制姓名 src_img = cv2ImgAddText(src_img, confidence, x + 5, y + h - 5 - textSize, (255, 0, 0), textSize) # 绘制置信度 return src_img # 返回处理后的图片 # 处理视频流或图片 def process_source(source, textSize=20): """ 人脸检测并标识在图片上 :param source: 待检测图片或视频流 :param textSize: 文字大小 """ if source.startswith('rtsp://'): # 是否为RTSP流 cap = cv2.VideoCapture(source) # RTSP流地址 # cap.set(cv2.CAP_PROP_FPS, 15) # 设置帧率(usb摄像头无效并且会报错) elif source.isdigit(): # 是否为数字 cap = cv2.VideoCapture(int(source)) # USB摄像头索引 else: # 否则视为本地图片 img = cv2.imread(source, textSize) # 读取图片 img = detect_face(img) # 人脸检测并处理 cv2.imshow("face_detect", img) # 显示图片 cv2.waitKey(0) # 等待按键 cv2.destroyAllWindows() # 关闭所有窗口 return cap.set(cv2.CAP_PROP_BUFFERSIZE, 1) # 设置缓冲区大小为1,你可以根据需要调整 # 视频流处理 while cap.isOpened(): # 检查是否成功打开视频源 ret, frame = cap.read() # 读取一帧视频 img = detect_face(frame) # 人脸检测并处理 cv2.imshow("img", img) # 显示图片 k = cv2.waitKey(1) & 0xFF # 等待按键输入(1ms),用于判断按键 if k == ord('Q') or k == ord('q'): # 按下Q键退出 break # 退出循环 cap.release() # 释放视频源 cv2.destroyAllWindows() # 关闭所有窗口 if __name__ == '__main__': recognizer = cv2.face.LBPHFaceRecognizer_create() # 加载分类器 recognizer.read('./data/face_trainer.yml') # 读取训练数据 names = ['未知', 'ZWZW', 'Sherry'] # 人物ID对应名称(一般是从1开始,0可用于未知) font_path = './data/simhei.ttf' # 设置字体相关参数# 导入人脸检测模型 # 加载人脸检测模型(注意模型路径,若是CPU不带_cuda后缀;若是GPU带_cuda后缀) face_cascade = cv2.CascadeClassifier('./opencv-4.10.0/data/haarcascades_cuda/haarcascade_frontalface_alt2.xml') # 可以是RTSP流地址、USB摄像头索引或本地图片路径 # source = "rtsp://admin:admin@192.168.100.111:554/Streaming/Channels/101" # RTSP流地址示例 source = "0" # USB摄像头索引示例 # source = "./images/7.jpg" # 本地图片路径示例 process_source(source, 40) # 开始处理视频流或图片(视频或图片,添加的字体大小) ``` **相关链接:** [【opencv】python实现人脸检测和识别训练](https://blog.csdn.net/qq_40951951/article/details/135601084) [OpenCV 入门(一) —— OpenCV 基础](https://blog.csdn.net/tmacfrank/article/details/138391492)
造物者W
2024年11月25日 15:07
转发文档
收藏文档
上一篇
下一篇
手机扫码
复制链接
手机扫一扫转发分享
复制链接
Markdown文件
分享
链接
类型
密码
更新密码