摘要:通过人脸识别与管理系统登录界面的开发(WinForm界面增强,OpenCV-Python智能识别),我将以一个用户登录窗体的两种不同登录验证方式向各位同学介绍如何利用WinForm开发出漂亮的应用程序窗体,为我们后面的各个章节中的窗体开发打下基础。另外也会向各位同学介绍WinForrm窗体如何调用Python程序让OpenCV-Python程序嵌入到我们的登录窗体中,从而实现人脸识别的。博文提供了完整的Python代码和使用教程,适合新入门的朋友参考,完整代码资源文件请转至文末的下载链接。本博文目录如下:
本章节主要介绍的内容如下:
一,如何利用opencv-python实现多个人脸的训练学习,生产yml的训练文件。
二,如果通过opencv-python自带的人脸检测器进行人脸检测,再通过已经训练好的yml进行人脸识别。
三,将已经识别到的人脸通sqlite中已经录入人脸的库进行用户比对。
目录:
1,创建人脸训练集结果
2,人脸识别实现
3,WinForm界面调用python实现扫脸登录
4,刷脸登录结果如下
===========================================================
1,创建人脸训练集结果
通过摄像头采集多个不同的人脸训练数据集,供后面的人脸训练使用。采集人脸的代码如下:a,将用户基础信息登记到sqlite数据库中,并将人脸图片保存到本地文件夹中。
def save(UserId,UserName,Pwd,Tel,Gender,Email,Idcard):
#连接到数据库
#数据库文件是“FaceDetection.db”
#如果数据库不存在的话,将会自动创建一个 数据库
conn = sqlite3.connect("..\\FaceDetection.db")
#创建一个游标 curson
cursor = conn.cursor()
#通过获取图片转BASE64存入sqlite3数据库
print("请看着摄像头!!!")
time.sleep(5)
print("请输入您的姓名:")
if(getFaceID.getFaceImg(UserId)):
#保存人脸训练集
getFaceID.getImagesAndLabels(UserId)
cjq_path = "../Facedata/training_data/" + UserId + "/"
#face_id = imgToBase64.ImgToBase64(cjq_path + str(UserId) + "."+UserName+".jpg")
#Faceinfo=face_id
print(cjq_path)
sql = "insert into UserInfo(id,UserName,Pwd,Tel,Gender,Email,Idcard) values(\'"+UserId+"\',\'"+UserName+"\',\'"+Pwd+"\',\'"+Tel+"\',\'"+Gender+"\',\'"+Email+"\',\'"+Idcard+"\')"
print(sql)
cursor.execute(sql)
print("信息录入成功")
#关闭游标:
cursor.close()
#提交事物
conn.commit()
#关闭连接
conn.close()
b,人脸信息采集如下:
def getFaceImg(userid):
face_cascade = cv2.CascadeClassifier(
"..\\haarcascades\\haarcascade_frontalface_default.xml")
eye_cascade = cv2.CascadeClassifier("..\\haarcascades\\haarcascade_eye.xml")
cap = cv2.VideoCapture(0)
cjq_path = "../Facedata/training_data/"+userid+"/"
mkdir(cjq_path)
count = 0
while True:
ret, img = cap.read()
if ret is True:
#如果摄像头成功读取图像,则将图像转换成灰度图像
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
else:
break
# 用人脸级联分类器引擎进行人脸识别,返回的faces为人脸坐标列表(x,y,w,h)
faces = face_cascade.detectMultiScale(gray, 1.1, 5)
# 如果检测出人脸,则对每一张人脸都做画矩形,并将其保存到同目录的Facedata文件夹中
for (x, y, w, h) in faces:
cv2.rectangle(img, (x, y), (x + w, y + w), (255, 0, 0))
count += 1 # 保存图像
cv2.imwrite(cjq_path + str(count) + "."+userid+".jpg", img)
#cv2.imwrite("face_id.jpg", img)
k = cv2.waitKey(30)
if k == 27: # 通过esc键退出摄像
break
elif count >= 50: # 得到50个样本后退出摄像
break # 关闭摄像头
cap.release()
cv2.destroyAllWindows()
return True
c,保存人脸训练集
# 根据图像存储的文件路径,获取当前图像,然后对其进行一一的训练
def getImagesAndLabels(userid):
faces = []
labels = []
cjq_path = "../Facedata/training_data/"
mkdir(cjq_path)
dirs = os.listdir(cjq_path)
for dir_name in dirs:
label = int(dir_name)
subject_dir_path = cjq_path + "/" + dir_name
subject_images_names = os.listdir(subject_dir_path)
for image_name in subject_images_names:
image_path = subject_dir_path + "/" + image_name
image = cv2.imread(image_path)
cv2.imshow("Training on image...", image)
cv2.waitKey(100)
# 检测脸部
face, rect = detect_face(image)
# 我们忽略未检测到的脸部
if face is not None:
# 将脸添加到脸部列表并添加相应的标签
faces.append(face)
labels.append(label)
print('labels:', labels)
print('faces:', faces)
#保存人脸特征
recognizer = cv2.face.LBPHFaceRecognizer_create()
recognizer.train(faces, np.array(labels))
#recognizer.write(r'face_trainer\trainer.yml')
mkdir(cjq_path + "..\\face_trainer\\")
recognizer.write(cjq_path + "..\\face_trainer\\trainer.yml")
print("总共存在{0}个人. 已完成识别".format(len(np.unique(labels))))
#print('脸部例子:',facesSamples[0])
#print('身份信息:',ids[0])
return faces,labels
2,人脸识别实现
#准备识别的图片
def face_detect_demo(img):
gray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)#转换为灰度
#face=face_detector.detectMultiScale(gray,1.1,5,cv2.CASCADE_SCALE_IMAGE,(100,100),(300,300))
face=face_detector.detectMultiScale(gray)
for x,y,w,h in face:
cv2.rectangle(img,(x,y),(x+w,y+h),color=(0,0,255),thickness=2)
cv2.circle(img,center=(x+w//2,y+h//2),radius=w//2,color=(0,255,0),thickness=1)
# 人脸识别
ids, confidence = recogizer.predict(gray[y:y + h, x:x + w])
#print('标签id:',ids,'置信评分:', confidence)
if confidence > 80:
global warningtime
warningtime += 1
if warningtime > 200:
#warning()
warningtime = 0
global checkResult
checkResult = False
cv2.putText(img, 'unkonw', (x + 10, y - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.75, (0, 255, 0), 1)
else:
#global checkResult
checkResult = True
global checkname
checkname = str(names[ids])
cv2.putText(img,checkname, (x + 10, y - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.75, (0, 255, 0), 1)
cv2.imshow('CheckFaceWindow',img)
return checkResult,checkname,warningtime
def checkface():
cap = cv2.VideoCapture(0)
while True:
# 获取每一帧的画面
ret, frame = cap.read()
if not ret:
break
resize_img = cv2.resize(frame, dsize=(346, 217))
flog,checkname,errnum = face_detect_demo(resize_img)
if flog:
print(str(checkResult)+','+checkname+','+str(warningtime))
break
if int(errnum) > 199:
print(str(checkResult)+','+checkname+','+str(warningtime))
break
if cv2.waitKey(1) & 0xFF == ord('q'):
break
if cv2.getWindowProperty("CheckFaceWindow", cv2.WND_PROP_VISIBLE) < 1:
break
cv2.destroyAllWindows()
cap.release()
return checkResult,checkname,warningtime
if __name__ == '__main__':
try:
# 代码行
# 加载训练数据集文件
recogizer = cv2.face.LBPHFaceRecognizer_create()
recogizer.read(os.path.abspath(pathyml))
checkface()
except Exception as err:
# 捕捉异常
str1 = 'default:' + str(err)
print(str1)
3,WinForm界面调用python实现扫脸登录
//执行刷脸登录
//调用opencv-python 打开摄像头
try
{
string path = Application.StartupPath + @"\Script_Python\03CheckFace.py";//py文件路径
string argText = "1";
StartTest(path, "getcheckface", argText);
}
catch (Exception e1)
{
MessageBox.Show(e1.Message);
}
//先启动第三方应用
//开线程来查找窗体,不然UI线程会卡死
Task.Run(() =>
{
//getlocalImg是要查找的窗体名称,自行替换
if (SetWindow.FindWindow("CheckFaceWindow"))
{
this.Invoke(new Action(() =>
{
SetWindow.SetParent(sp_Face.Handle, "CheckFaceWindow"); //设置父容器
}));
}
else
{
MessageBoxEx.Show("未能查找到人脸窗体!", "人脸检测", MessageBoxButtons.OK, MessageBoxIcon.Information, MessageBoxDefaultButton.Button1);
}
});
4,刷脸登录结果如下
5,源码分享,教学ppt分享
6,写在最后
生活不是过山车,不会永远都刺激。它更像是一条缓和的抛物线,有时在顶点,有时在谷底,有时需要我们攀爬,有时需要我们俯冲。当你暂时处于谷底,要做的不是怨天尤人,而是积蓄力量,为即将到来的攀登做好准备。