文章目录
python图像处理教程:初步📷插值变换📷形态学处理📷滤波
在Python中实现目标识别任务,最常用的方法是调用dlib模块。dlib由C++编写,基于boost,在Python中有很多依赖,推荐用conda
来安装,一行代码轻松搞定
conda install -c conda-forge dlib
人脸识别
人脸识别是应用最广泛的目标识别任务之一,dlib对此提供了非常成熟的方案,包括基于HOG和CNN的两种算法,可以实现下面的效果。
其中,绿色框线即为检测到的人脸区域。
HOG算法的基本思想是计算图像的梯度和方向,然后用直方图对梯度值进行统计得到特征,并将这些特征送入SVM,从而实现分类,并检测出人脸。其实现代码如下
import numpy as np
import matplotlib.pyplot as plt
import dlib
path = ‘lena.jpg’
img = plt.imread(path)
detector = dlib.get_frontal_face_detector()
rect = detector(img, 1)[0]
def drawDetector(img, rect):
cnrs = [rect.bl_corner(), rect.br_corner(),
rect.tr_corner(), rect.tl_corner(),
rect.bl_corner()]
xs = [c.x for c in cnrs]
ys = [c.y for c in cnrs]
plt.imshow(img)
plt.plot(xs, ys, c=‘g’)
plt.axis(‘off’)
plt.show()
drawDetector(img, rect)
【get_frontal_face_detector】便用于生成HOG人脸检测器,detector为其返回值。作为一个人脸检测器,detector输入一个图像后,其返回值是一个矩形,通过提取矩形的四个点,并连成线之后,就可以把检测到的人脸框选出来。
CNN算法,即卷积神经网络,若想让其顺利工作,需要使用已经训练好的模型,可在这里下载mmod_human_face_detector.dat.bz2文件。
下载完成后,解压并调用
p = r"mmod_human_face_detector.dat" # 模型路径
cnnDetector = dlib.cnn_face_detection_model_v1(p)
在检测器创建后,其调用方法与内置检测器是完全相同的,但返回值对Rectangle
类型进行了二次封装,代码如下。
cnnRect = cnnDetector(img, 1)[0]
drawDetector(img, cnnRect.rect)
特征点识别
如果想鉴别某两张脸是同一个人,那么首先要得到人脸上的某些特殊的点,比如眼角、嘴角,然后根据这些点的位置关系,得到一些不随着人脸移动和表情变化而变化的不变量,并以此作为鉴别人物的依据。
为此需要从dlib.net下载68点的人脸模型 shape_predictor_68_face_landmarks.dat.bz2,下载后注意解压。
# 加载68点人脸模型
predictor = dlib.shape_predictor('shape_predictor_68_face_landmarks.dat')
# 此为人脸的特征点列表,img和rect是HOG算法检测到的结果。
face = predictor(img, rect)
keyPts = face.parts()
其中,shape_predictor为关键点检测器,face
可以理解为检测到关键点的脸,keyPts
为其检测后的关键点列表。效果如下
从这个图可以看到人脸特征点总共有68个,分布在脸的轮廓和五官的边缘,每个点有 x , y x,y x,y两个坐标,则总共有136个值,可以组成一个新的向量。绘图代码为
for i, pt in enumerate(keyPts):
plt.text(pt.x,pt.y, str(i))
plt.scatter([pt.x], [pt.y], marker='*')
plt.imshow(img)
plt.axis(‘off’)
plt.show()
人脸比对
对比两张脸是否相同,本质就是对比这136个值是否相近,只不过这种方案误差很大就是了。
【face_recognition_model_v1】提供了人脸对比模型,当然需要调用的模型还是需要到dlib中下载。考虑到在寻找脸部的68个特征点时,并未保证特征点之间是线性无关的,所以通过这个模型后,得到的是一个128维的向量,代码如下
pReg = "dlib_face_recognition_resnet_model_v1.dat"
faceRec = dlib.face_recognition_model_v1(pReg)
vec1 = faceRec.compute_face_descriptor(img, face)
接下来再打开两张图片,并求得对应的特征向量
def getReg(im):
rect = detector(im, 1)[0] # 此为人脸区域
face = predictor(im, rect)
vec = faceRec.compute_face_descriptor(im, face)
return np.array(vec)
img2 = plt.imread(‘test2.jpg’)
vec2 = getReg(img2)
img3 = plt.imread(‘test3.jpg’)
vec3 = getReg(img3)
接下来查看一下这三张图片的距离
np.linalg.norm(vec1-vec2)
0.40060397645976
np.linalg.norm(vec1-vec3)
0.8248735552156338
可见,vec1和vec2很有可能是一个人,和vec3则是两个人。
车辆识别
除了人脸识别模型之外,dlib还提供了车辆模型
- mmod_front_and_rear_end_vehicle_detector.dat
- mmod_rear_end_vehicle_detector.dat
接下来测试一下这两个模型的识别效果
p1 = r"mmod_front_and_rear_end_vehicle_detector.dat"
p2 = r"mmod_rear_end_vehicle_detector.dat"
fD = dlib.cnn_face_detection_model_v1(p1)
rD = dlib.cnn_face_detection_model_v1(p2)
然后打开一张车辆的图像进行识别
img = plt.imread("test.jpg")
fRects = fD(img)
rRects = rD(img)
由于图像中有多个车辆,所以重做一个展示函数
def getXY(rect):
cnrs = [rect.bl_corner(), rect.br_corner(),
rect.tr_corner(), rect.tl_corner(),
rect.bl_corner()]
xs = [c.x for c in cnrs]
ys = [c.y for c in cnrs]
return xs, ys
def drawDetector(img, rects, ax):
for r in rects:
xs, ys = getXY(r.rect)
ax.plot(xs, ys)
ax.imshow(img)
plt.axis(‘off’)
然后绘图
fig = plt.figure()
ax = fig.add_subplot(1,2,1)
drawDetector(img, fRects, ax)
ax = fig.add_subplot(1,2,2)
drawDetector(img, rRects, ax)
plt.show()
效果如下