想不到吧,大四下学期还有课。/(ㄒoㄒ)/~~
课程中有个大作业研讨弄一个跟人工智能相关的东西,想来想去决定做一个人脸识别相关的东西。由于是第一次弄这一方面的,还有很多都不太会,结合了c站里各位大佬的成果,最后弄了个自己想要的样子,废话不多说,开整!
在我的理解中人脸识别分为三个步骤,第一个是获取人脸信息,第二个是训练自己的模型,第三个是识别分类。那么文章也就从这三个方面来一一介绍。
首先是获取人脸信息,我这里提供获取人脸信息的方式是直接从视频中获取,当然你也可以从照片中弄出来(用循环的方法一张一张从文件夹中获取图片取获取人脸信息)。人脸的获取用的是opencv官方的人脸识别分类器:haarcascade_frontalface_default.xml
下载地址:opencv/data/haarcascades at 4.x · opencv/opencv · GitHub
如果进去去的话文章末尾也有我的qq,可以找我发给你。
之后从视屏中获取的代码如下:
import os
import cv2
def load_img(path, trainpath,vedioname,name, mun=30, add_with=0, num_id=0,time=0):
if not os.path.exists(path):
os.mkdir(path)
# 获取人脸识别模型
classfier = cv2.CascadeClassifier('opencv-4.x/data/haarcascades/haarcascade_frontalface_default.xml')
# 创建一个窗口
cv2.namedWindow('face')
# 打开第一个个摄像头
# cap = cv2.VideoCapture(0)
# 输入视频
# cap = cv2.VideoCapture('trainvedio/zeliansiji/zeliansiji1.mp4')
cap = cv2.VideoCapture(trainpath+vedioname)
# 根据摄像头设置IP及rtsp端口
# url='rtsp://admin:admin@192.168.0.104:8554/live'
# cap = cv2.VideoCapture(url)
i = 0 # 计数
if cap.isOpened():
while i < mun:
ok, frame = cap.read() # 读取一帧图片
if not ok:
continue
faces = classfier.detectMultiScale(frame, 1.2, 3, minSize=(32, 32))
if len(faces) > 0:
for face in faces:
x, y, w, h = face
img = frame[y - add_with:y + h + add_with,
x - add_with:x + w + add_with]
# 显示人脸框
# cv2.rectangle(frame, (x-add_with, y-add_with),
# (x+w+add_with, y+h+add_with), (0, 255, 0), 2)
# save_path = path + '/' + name + '_' + str(i) + '.jpg'
# save_path = path + '/' + str(i) + '.jpg'
save_path = path + '/'+name+'.'+str(num_id) +'.'+ str(i+time*mun) + '.jpg'
print(save_path)
img2 = cv2.resize(img, (112, 112))
cv2.imwrite(save_path, img2)
i += 1
cv2.imshow('face', frame)
c = cv2.waitKey(10)
if c & 0xFF == ord('q'):
break
cap.release()
cv2.destroyAllWindows()
if __name__ == '__main__':
# 第一个参数为保存图片的路径
# 第二个参数为保存图片名字的开头
# 第三个参数为图片的数量
# 第四个参数可以调节图片的大小
# 第五个参数表示人脸id
# 第六个参数表示 (当前视频数-1)
# load_img('data/zeliansiji', 'zeliansiji', 300, 0, 1)
# load_img('data/zeliansiji', 'trainvedio/zeliansiji/','zeliansiji1.mp4','zeliansiji', 300, 0, 1,0)
trainpath='trainvedio/pujing/'
time=0
for vedioname in os.listdir(trainpath):
load_img('data/pujing', trainpath, vedioname, 'pujing', 900, 1, 0,time)
time+=1
第二步就是训练自己的模型,还是用上面的那个人脸分类器。
# -----建立模型、创建数据集-----#-----建立模型、创建数据集-----
import os
import cv2
import numpy as np
from PIL import Image
# 导入pillow库,用于处理图像
# 设置之前收集好的数据文件路径
path = 'data/class14'
# 初始化识别的方法
recog = cv2.face.LBPHFaceRecognizer_create()
# 调用熟悉的人脸分类器
detector = cv2.CascadeClassifier('opencv-4.x/data/haarcascades/haarcascade_frontalface_default.xml')
# 创建一个函数,用于从数据集文件夹中获取训练图片,并获取id
# 注意图片的命名格式为User.id.sampleNum
def get_images_and_labels(path):
image_paths = [os.path.join(path, f) for f in os.listdir(path)]
# 新建连个list用于存放
face_samples = []
ids = []
# 遍历图片路径,导入图片和id添加到list中
for image_path in image_paths:
# 通过图片路径将其转换为灰度图片
img = Image.open(image_path).convert('L')
# 将图片转化为数组
img_np = np.array(img, 'uint8')
if os.path.split(image_path)[-1].split(".")[-1] != 'jpg':
continue
# 为了获取id,将图片和路径分裂并获取
id = int(os.path.split(image_path)[-1].split(".")[1])
faces = detector.detectMultiScale(img_np)
# 将获取的图片和id添加到list中
for (x, y, w, h) in faces:
face_samples.append(img_np[y:y + h, x:x + w])
ids.append(id)
return face_samples, ids
# 调用函数并将数据喂给识别器训练
print('Training...')
faces, ids = get_images_and_labels(path)
# 训练模型
recog.train(faces, np.array(ids))
# 保存模型
recog.save('trainer/class14.yml')
最后就是检验自己成果的时候了!检测识别。检测的视频流有很多种,可以是摄像头也可以是自己的视频。
# -----检测、校验并输出结果-----
import cv2
import time
# 准备好识别方法
recognizer = cv2.face.LBPHFaceRecognizer_create()
# 使用之前训练好的模型
print('loading moudle......')
recognizer.read('trainer/class14.yml')
# 再次调用人脸分类器
print('loading classifier......')
cascade_path = "opencv-4.x/data/haarcascades/haarcascade_frontalface_default.xml"
face_cascade = cv2.CascadeClassifier(cascade_path)
# 加载一个字体,用于识别后,在图片上标注出对象的名字
font = cv2.FONT_HERSHEY_SIMPLEX
idnum = 0
# 设置好与ID号码对应的用户名,如下,如0对应的就是初始
names = ['shuaige','sb','xuzuowei','weiaojie','zhangyuan']
# 调用视频
print('loadin vedio......')
cam = cv2.VideoCapture(0)
minW = 0.1 * cam.get(3)
minH = 0.1 * cam.get(4)
while True:
start = time.time() # 开始计时
ret, img = cam.read()
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 识别人脸
faces = face_cascade.detectMultiScale(
gray,
scaleFactor=1.2,
minNeighbors=5,
flags=5,
minSize=(int(minW), int(minH))
)
# 进行校验
for (x, y, w, h) in faces:
cv2.rectangle(img, (x, y), (x + w, y + h), (0, 255, 0), 2)
idnum, confidence = recognizer.predict(gray[y:y + h, x:x + w])
# 计算出一个检验结果
if confidence < 100:
idum = names[idnum]
confidence = "{0}%", format(round(100 - confidence))
else:
idum = "unknown"
confidence = "{0}%", format(round(100 - confidence))
# 输出检验结果以及用户名
end = time.time() # 结束计时
seconds = end - start
fps = 1 / seconds # 计算帧率
cv2.putText(img, # 图像
"FPS: {0}".format(float('%.1f' % fps)), # fps数值
(50, # x坐标
50), # y坐标
cv2.FONT_HERSHEY_SIMPLEX, # 字体
1, # 字体大小
(0, 0, 255), # 颜色
1) # 粗细
cv2.putText(img, str(idum), (x + 5, y - 5), font, 1, (0, 255, 0), 2)
# cv2.putText(img, str('made by jhw'), (x + 5, y + h -5), font, 1, (255, 255, 255), 1)
# 展示结果
cv2.imshow('press q to exit', img)
k = cv2.waitKey(1)
if k == 27:
break
# c = cv2.waitKey(10)
# if c & 0xFF == ord('q'):
# break
# 释放资源
cam.release()
cv2.destroyAllWindows()
这样就大功告成啦,来看看效果吧!看看我们的普京大帝!
喜欢的就点个赞收藏一下吧
Q我 1609373452