然后打开标号为0的摄像头
camera = cv2.VideoCapture(0) # 摄像头
success, img = camera.read() # 从摄像头读取照片
复制代码
2.录入新面容

图4:录入人脸
2.1采集面容
创建文件夹data用于储存本次从摄像头采集到的照片,每次调用前先清空这个目录。
然后是一个循环,循环次数为需要采集的样本数,摄像头拍摄取样的数量,越多效果越好,但获取以及训练的越慢。
循环内调用camera.read()返回值赋给全局变量success,和img 用于在GUI中实时显示。
然后调用cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)用于将采集到的图片转为灰度图片减少计算量。
然后利用加载好的人脸分类器将每一帧摄像头记录的数据带入OpenCv中,让Classifier判断人脸。
# 其中gray为要检测的灰度图像,1.3为每次图像尺寸减小的比例,5为minNeighbors
faces = face_cascade.detectMultiScale(gray, 1.3, 5)
复制代码
faces为在img图像中检测到的人脸,然后利用cv2.rectangle在人脸一圈画个矩形。并把含有人脸的区域储存进入data文件夹 注意这里写入时,每个图片的标签时Total_face_num即当前共有多少个可识别用户(在录入之前加一),亦即当前用户的编号
cv2.rectangle(img, (x, y), (x + w, y + w), (255, 0, 0))
cv2.imwrite("./data/User." + str(T) + '.' + str(sample_num) + '.jpg', gray[y:y + h, x:x + w])
复制代码
然后在循环末尾最后打印一个进度条,用于提示采集图像的进度 主要原理就是每次输出不换行并且将光标移动到当前行的开头,输出内容根据进度不断变化即可,同时在控件的提示框也输出进度信息
print("r" + "%{:.1f}".format(sample_num / pictur_num * 100) + "=" * l + "->" + "_" * r, end="")
var.set("%{:.1f}".format(sample_num / pictur_num * 100)) # 控件可视化进度信息
window.update() # 刷新控件以实时显示进度
复制代码
2.2训练识别器
读取data文件夹,读取照片内的信息,得到两个数组,一个faces存的是所有脸部信息、一个ids存的是faces内每一个脸部对应的标签,然后将这两个数组传给 recog.train用于训练
# 训练模型 #将输入的所有图片转成四维数组
recog.train(faces, np.array(ids))
复制代码
训练完毕后保存训练得到的识别器到.yml文件中,文件名为人脸编号+.yml
recog.save(str(Total_face_num) + ".yml")
复制代码
2.3修改配置文件
每一次训练结束都要修改配置文件,具体要修改的地方是第一行和最后一行。 第一行有一个整数代表当前系统已经录入的人脸的总数,每次修改都加一。这里修改文件的方式是先读入内存,然后修改内存中的数据,最后写回文件。
f = open('config.txt', 'r+')
flist = f.readlines()
flist[0] = str(int(flist[0]) + 1) + "
"
f.close()
f = open('config.txt', 'w+')
f.writelines(flist)
f.close()
复制代码
还要在最后一行加入一个二元组用以标识用户。 格式为:标签+空格+用户名+空格,用户名默认为Userx(其中x标识用户编号)
f.write(str(T) + " User" + str(T) + "
")
复制代码
3.人脸识别(刷脸)

图5:刷脸流程图
由于这里采用多个.yml文件来储存识别器(实际操作时储存在一个文件中识别出错所以采用这种方式),所以在识别时需要遍历所有的.yml文件,如果每一个都不能识别才得出无法识别的结果,相反只要有一个可以识别当前对象就返回可以识别的结果。而对于每一个文件都识别十次人脸,若成功五次以上则表示最终结果为可以识别,否则表示当前文件无法识别这个人脸。
识别过程中在GUI的控件中实时显示拍摄到的内容,并在人脸周围画一个矩形框,并根据识别器返回的结果实时显示在矩形框附近。
idnum, confidence = recognizer.predict(gray[y:y + h, x:x + w])
# 加载一个字体用于输出识别对象的信息
font = cv2.FONT_HERSHEY_SIMPLEX
# 输出检验结果以及用户名
cv2.putText(img, str(user_name), (x + 5, y - 5), font, 1, (0, 0, 255), 1)
cv2.putText(img, str(confidence), (x + 5, y + h - 5), font, 1, (0, 0, 0), 1)
复制代码