基于dlib和opencv库的人脸识别
需下载68个特征点的人脸检测模型:
http://dlib.net/files/
文件名为 shape_predictor_68_face_landmarks.dat
opencv包
img=cv2.imread(image)
功能:通过opev中的imread读取测试图片文件
参数:要读取的图片
img=cv2.cvtColor(img,cv2.COLOR_BGR2RGB)
功能:转换图片格式
参数:要转换的图片,转换的方式(这里是将BRG转换为RGB)
返回值:返回转换完成的图片
cv2.circle(img,center,radius,color,thickness)
功能:画一个圆
参数:要画圆的图片,图片中的圆心坐标,半径,颜色(color=(0,255,0)),粗细(thickness=2 必须为整数)
camera=cv2.VideoCapture(0)
功能:调用摄像头
camera.set(cv2.CAP_PROP_FRAME_WIDTH, 1080)
camera.set(cv2.CAP_PROP_FRAME_HEIGHT, 768)
功能:设置画面长宽
ret,frame=camera.read()
功能:获取摄像头中的每一帧的画面
返回值:ret为布尔值,如果读取帧是正确的则返回True,反之返回False;frame为每一帧的图像
frame=cv2.flip(frame,1)
功能:将获取的画面水平翻转
返回值:返回翻转后的画面
dlib包
检测器:
detector=dlib.get_frontal_face_detector()
功能:人脸检测画框
返回值:返回一个默认的人脸检测器
faces=detector(img,0)
功能:对图像画人脸框
参数:图片
返回值:人脸检测框的四点坐标
预测器:
predictor=dlib.shape_predictor("shape_predictor_68_face_landmarks.dat")
功能:标记人脸68个关键点
参数:保存的模型路径
返回值:68个人脸关键点的预测器
matplotlib包
plt.figure(figzise=(10,8))
功能:声明整个画布的大小
参数:大小(此处为长为10,宽为8)
pt.subplot(121)
功能:开始绘图
参数:代表在整个画布中,图片有1行2列,此时从第1列的图片开始绘制
plt.imshow(img)
功能:显示画布中的图片
参数:要显示的图片
plt.axis("off")
功能:结束绘图
plt.show()
功能:显示画布
图像识别代码
import cv2
import dlib
import matplotlib.pyplot as plt
import numpy as np
test_img="test.jpg"
#通过opev中的imread读取测试图片文件
img=cv2.imread(test_img)
#人脸检测画框,返回一个默认的人脸检测器
detector = dlib.get_frontal_face_detector()
#通过模型建立,返回一个标记68个人脸关键点的预测器
predictor_path="shape_predictor_68_face_landmarks.dat"
predictor = dlib.shape_predictor(predictor_path)
#对图像画人脸框,返回人脸检测矩形框4点坐标
faces=detector(img,0)
if len(faces):
print("Found {0} faces".format(len(faces)))
for i in range (len(faces)):
landmarks = np.matrix([[p.x, p.y] for p in predictor(img, faces[i]).parts()])
for point in landmarks:
pos = (point[0, 0], point[0, 1])
#给68个特征点都画一个圆
cv2.circle(img, pos, 3, color=(0, 255, 0),thickness=1)
else:
print("Face not found")
#opencv读取的图片是BRG通道的,需要转换成RGB
img=cv2.cvtColor(img,cv2.COLOR_BGR2RGB)
#表示figure的大小为宽为10,长为8
plt.figure(figsize=(10,8))
#12代表有图片有一行两列,1代表此时绘制第一个图
plt.subplot(121)
plt.imshow(plt.imread(test_img))
plt.axis("off")
#12代表有图片有一行两列,2代表此时绘制第二个图
plt.subplot(122)
plt.imshow(img)
plt.axis("off")
plt.show()
摄像头识别代码
import cv2
import dlib
import numpy as np
class FaceDetective():
def __init__(self):
# 人脸检测画框,返回一个默认的人脸检测器
self.detector = dlib.get_frontal_face_detector()
# 通过模型建立,返回一个标记68个人脸关键点的预测器
self.predictor = dlib.shape_predictor("shape_predictor_68_face_landmarks.dat")
def identify(self,frame):
# 对图像画人脸框,返回人脸检测矩形框4点坐标
faces=self.detector(frame,0)
if len(faces):
print("Found {0} face".format(len(faces)))
for i in range(len(faces)):
landmarks = np.matrix([[p.x, p.y] for p in self.predictor(frame, faces[i]).parts()])
for point in landmarks:
pos = (point[0, 0], point[0, 1])
cv2.circle(frame, pos, 3, color=(0, 0, 255), thickness=2)
else:
print("Face not found")
return frame
def run_camera(self):
# 调用摄像头
camera=cv2.VideoCapture(0)
# 设置长宽
camera.set(cv2.CAP_PROP_FRAME_WIDTH, 1080)
camera.set(cv2.CAP_PROP_FRAME_HEIGHT, 768)
while True:
# 读取摄像头每帧的画面
ret,frame=camera.read()
if ret:
# 水平翻转
frame=cv2.flip(frame,1)
# 对每帧的画面进行识别
frame=self.identify(frame)
cv2.imshow("CAM",frame)
# 按q退出
if cv2.waitKey(1) & 0xFF == ord('q'):
break
camera.release()
cv2.destroyAllWindows()
if __name__=='__main__':
FaceDetective().run_camera()
之前尝试不使用类来写摄像头识别的代码,发现调用摄像头后的运行效率极低,原因可能是类的使用能够减少python内存的消耗。