血一般的教训,整这个东西,代码没用多久,但是配环境真的把人快整吐了,这里先把踩过的坑和解决方法在这里说一下…
博主的环境: Ubuntu18.04+Pycharm
大一的时候实验室要求学习Tensorflow,又接手了学长们的一个项目,负责视觉方面的东西,水平不够学的一知半解,电脑上下载了一大堆库,一大堆环境,各种版本的环境交错融杂,文件夹胡乱摆放在犄角旮旯,这导致我电脑的环境非常凌乱,我自己没有概念,后面也没有删这些乱七八糟的东西,这种行为为此时的我埋下了无数恶果…
问题是从一个函数开始的:
recognizer = cv2.face.LBPHFaceRecognizer_create()
这句代码疯狂给我报错
module 'cv2' has no attribute 'face'
浏览国内外各种网站,试过了所有的解决方法,无外乎就是安装一个叫opencv-contrib-python
的拓展包,face是这个包里面的函数,
pip install opencv-python -i http://pypi.douban.com/simple --trusted-host pypi.douban.com
pip install opencv-contrib-python -i http://pypi.douban.com/simple --trusted-host pypi.douban.com
pip install opencv-contrib-python-headless -i http://pypi.douban.com/simple --trusted-host pypi.douban.com
按理说安好了这个拓展包,该函数就能用了,但我仍然报错,在磕了三四天无果后,决定彻底把cv2删掉重新配环境,首先使用指令
pip uninstall opencv-python
pip uninstall opencv-contrib-python
pip uninstall opencv-python-headless
以及检查了
这里面,确定是删掉了,可是当我把鼠标移到代码中的import cv2
,发现仍然可以点开,此时意识到是环境中仍然存在cv2路径。于是我进入到cv2的源码,发现了这个opencv来源于曾经安装的openvino,删除openvino后,彻底清除掉了环境中所有的opencv,再按上述方法安装后便成功了。
但是又出现了新的问题,就是cv2库中的函数无法自动补全,但是可以正常运行,至今未能解决…有办法的朋友可以私信我一下万分感谢!
环境配好了接下来就是人脸识别部分了,博主使用了两种方法
方法一. 调用face_recognition人脸识别库
识别人脸,如果不在人脸库,则可以选择是否加入人脸库
# -*- coding=UTF-8 -*-
import cv2
import os
import face_recognition
import numpy as np
import sys
cap = cv2.VideoCapture(0)
new = '/home/bj/PycharmProjects/facefound/drivers' #存照片的地方
Know_face_encodings = []
Know_face_names = []
face_locations = []
face_encodings = []
face_names = []
filelist = os.listdir(new)
process_this_frame = True
def add_Driver():
print("welcome to here ,new driver")
print("please input your name,and look at the camare,it will take photos after 3s:")
i = input(":")
ret, frame = cap.read()
cv2.imshow('cap', frame)
output_path = os.path.join(new, "%s.jpg" % i)
cv2.imwrite(output_path, frame)
out = face_recognition.load_image_file(output_path)
out_encoding = face_recognition.face_encodings(out)[0]
Know_face_encodings.append(out_encoding)
Know_face_names.append(i)
for i in filelist:
# creat arrays of record face name
img_path = os.path.join('drivers', "%s" % i)
image = face_recognition.load_image_file(img_path)
img_encoding = face_recognition.face_encodings(image)[0]
Know_face_encodings.append(img_encoding)
Know_face_names.append(i)
#Initialize some variables
while True:
ret, frame = cap.read()
flag = cv2.waitKey(1)
#Resize video's size to receive faster
small_frame = cv2.resize(frame, (0, 0), fx=0.25, fy=0.25)
#turn BGR to RGB color
rgb_small_frame = small_frame[:, :, ::-1]
if process_this_frame:
#Find all face and faceencodings to contract
face_locations = face_recognition.face_locations(rgb_small_frame,model="cnn")
face_encodings = face_recognition.face_encodings(rgb_small_frame,face_locations)
face_names=[]
for face_encoding in face_encodings:
#see if the face match the face we knowen
matchs = face_recognition.compare_faces(Know_face_encodings,face_encoding)在这里插入代码片
name = "Unknown"
# print("if you want to join us,push 'o':")
# if flag==13 :
# add_Driver()
# else:
#if we find the same face
#name =we knownface
face_distances = face_recognition.face_distance(Know_face_encodings,face_encoding)
best_match_index = np.argmin(face_distances)
print(best_match_index)
if matchs[best_match_index]:
name = Know_face_names[best_match_index]
if best_match_index == 0:
while(1):
print("do you want to join in?")
a=input()
if a == 'y':
add_Driver()
break
if a == 'n':
break
face_names.append(name)
process_this_frame = not process_this_frame
#display the results
for (top, right, bottom, left), name in zip(face_locations, face_names):
top *= 4
right *= 4
bottom *= 4
left *= 4
#Draw a box around face
cv2.rectangle(frame, (left-10, top-100), (right+10, bottom+50), (0, 0, 225), 2)
#Draw a label with a name below the face
cv2.rectangle(frame, (left-10, bottom+15), (right+10, bottom+50), (0, 0, 255), cv2.FILLED)
#set zi ti
font = cv2.FONT_HERSHEY_DUPLEX
cv2.putText(frame, name, (left+6, bottom+44), font, 1.0, (255, 255, 255),1)
cv2.imshow('cap', frame)
if flag == 27:
break
cap.release()
cv2.destroyAllWindows()
方法二:LBPHFaceRecognizer直方图识别法
1.创建人脸库,采集50张当前摄像头识别的人脸照片做素材
# -*- coding=UTF-8 -*-
import os
import sys
import numpy
import cv2
cap = cv2.VideoCapture(0)
face_detector = cv2.CascadeClassifier(r'/home/bj/PycharmProjects/FACE/haarcascade_frontalface_default.xml')
drivers_id = input('write down your name:')
path = '/home/bj/PycharmProjects/FACE/drivers'
if not os.path.exists(path+'/'+drivers_id):
os.makedirs(path+'/'+drivers_id)
count = 0
while True:
success, img = cap.read()
if success is True:
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
else:
break
faces = face_detector.detectMultiScale(gray, 1.3, 5)
for(x, y, w, h) in faces:
flag = cv2.waitKey(1)
cv2.rectangle(img, (x-500, y-500), (x+w+500, y+w+500), (225, 0, 0))
count += 1
thepath = os.path.join('drivers', drivers_id, "%s" % drivers_id)
cv2.imwrite(thepath+ str(count) + '.jpg', gray[y:y+h, x:x+w])
if flag == 27:
break
elif count>=50:
cap.release()
cv2.destroyAllWindows()
break
cv2.imshow('image', img)
2.训练人脸模型
# -*-coding:utf-8-*-
import cv2
import os
import numpy as np
def face_detect(image):
gray = cv2.cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
face_detector = cv2.CascadeClassifier("/home/bj/PycharmProjects/FACE/haarcascade_frontalface_default.xml")
faces = face_detector.detectMultiScale(gray, 1.2, 6)
if(len(faces)==0):
return None, None
(x, y, w, h) = faces[0]
return gray[y:y+w, x:x+h], faces[0]
def ReFileName(dirPath):
print(os.listdir(dirPath))
faces = []
for file in os.listdir(dirPath):
print(file)
if os.path.isfile(os.path.join(dirPath, file)) == True:
c = os.path.basename(file)
name = dirPath + '/' +c
img = cv2.imread(name)
face, rect = face_detect(img)
if face is not None:
faces.append(face)
cv2.waitKey(1)
cv2.destroyAllWindows()
return faces
dirPathslx = r"drivers/slx"
slx = ReFileName(dirPathslx)
print(len(slx))
lableslx = np.array([0 for i in range(len(slx))])
dirPathyg = r"drivers/yg"
yg = ReFileName(dirPathyg)
print(len(yg))
lableyg = np.array([1 for i in range(len(yg))])
x = np.concatenate((slx, yg), axis=0)
y = np.concatenate((lableslx, lableyg), axis=0)
index = [i for i in range(len(y))]
np.random.seed(1)
np.random.shuffle(index)
train_data = x[index]
train_label = y[index]
recognizer = cv2.face.LBPHFaceRecognizer_create()
recognizer.train(train_data, train_label)
# 保存训练数据
recognizer.write('train.yml')
3.实时识别当前摄像头人脸
# -*-coding:utf-8-*-
import cv2
cap = cv2.VideoCapture(0)
face_detector = cv2.CascadeClassifier("haarcascade_frontalface_default.xml")
facelabel = ["slx", "yg"]#人物名
#人脸检测函数
def face_detect_demo(image):
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
faces = face_detector.detectMultiScale(gray, 1.2, 6)
# 如果未检测到面部,则返回原始图像
if (len(faces) == 0):
return None, None
# 目前假设只有一张脸,xy为左上角坐标,wh为矩形的宽高
(x, y, w, h) = faces[0]
# 返回图像的脸部部分
return gray[y:y + w, x:x + h], faces[0]
#导入训练结果
recognizer = cv2.face.LBPHFaceRecognizer_create()
recognizer.read('train.yml')#读取前文训练的结果
# 根据给定的人脸(x,y)坐标和宽度高度在图像上绘制矩形
def draw_rectangle(img, rect):
(x, y, w, h) = rect#矩形框
cv2.rectangle(img, (x, y), (x + w, y + h), (255, 255, 0), 2)
# 根据给定的人脸(x,y)坐标写出人名
def draw_text(img, text, x, y):
cv2.putText(img, text, (x, y), cv2.FONT_HERSHEY_COMPLEX, 1, (128, 128, 0), 2)
# 此函数识别图像中的人物并在脸部周围绘制一个矩形及其人名
def predict(image):
# 生成图像的副本,保留原始图像
# 检测人脸区域
face, rect = face_detect_demo(img)#face_detect_demo前面的人脸检测函数
#print(rect)=[x,y,w,h]
# 预测人脸名字
label = recognizer.predict(face)
print(label)#label[0]为名字,label[1]可信度数值越低,可信度越高(
if label[1]<=70:
# 获取由人脸识别器返回的相应标签的人名
label_text = facelabel[label[0]]
# 在检测到的脸部周围画一个矩形
draw_rectangle(img, rect)
# 标出预测的人名
draw_text(img, label_text, rect[0], rect[1])
# 返回预测的图像
return img
else:
# 在检测到的脸部周围画一个矩形
draw_rectangle(img, rect)
# 标出预测的人名
draw_text(img, "not find", rect[0], rect[1])
# 返回预测的图像
return img
while True:
success, img = cap.read()
if success is True:
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
else:
break
faces = face_detector.detectMultiScale(gray, 1.3, 5)
for (x, y, w, h) in faces:
flag = cv2.waitKey(1)
cv2.rectangle(img, (x - 500, y - 500), (x + w + 500, y + w + 500), (225, 0, 0))
cv2.imwrite(str(1) + '.jpg', gray[y:y + h, x:x + w])
if flag == 27:
exit()
cv2.imshow('image', img)
#执行预测
pred_img = predict('1.jpg')
cv2.imshow('result', pred_img)
if flag == 27:
break
cv2.waitKey(0)
cv2.destroyAllWindows()
各个部分功能实现后,我开始把它们汇总,最终代码如下