目录
-
class 2 的实操
- 初级人脸识别
- 中极人脸识别
- 究极人脸识别
- 进阶:人脸定位和人脸核验
-
遇到的问题
- 安装 Face-recognition 库
- 图片灰度的问题
- plt显示图片的问题
-
拓展一下
- plt 图像处理基本操作
- Haar 算法的技术逻辑和 Adaboost 级联分类器原理
写在前面
老师上课说讲人脸识别,着实把我吓了一跳。这是我第二节课就可以学到的东西么?
直到开始实操,我才发现我们站在巨人的肩膀上。程序员朋友总是调侃“瞎造轮子”,对于我们这些非专业手,不会瞎造轮子,也不需要瞎造轮子(主要是不会)。学会从错误中学习,善用百度,能够结合现有的方式实现自己的需求,就很满足了。
Eg:要学会看技术文档。
一、Class 2 实操
第二节课的上机实操,通过 OpenCV 和 Face-recognition 进行人脸识别,对卷积神经网络有一个初步的体会。
老师介绍了三种实现人脸识别的方法,分别是 OpenCV 的 CascadeClassifier 级联分类器、Face-recognition 的 HOG 算法、Face-recognition 的 CNN 算法。
三种算法就能能力相差几何?各有什么优势?三组试验,拉出来溜溜。
环境Python3.7
Jupyter Notebook
用到的库OpenCV
dlib
face_recognition
matplotlib.pyplot
1. 初级人脸识别
在这一组比赛中,我们先使用难度较低的一张图进行识别。这幅图的难点在于遮挡(比如墨镜和脸不全):
首先使用 OpenCV,开干!
import cv2 as cv
import matplotlib.pyplot as plt
def detectFaces(image_name):
img = cv.imread(image_name)
face_cascade = cv.CascadeClassifier("data/haarcascade_frontalface_default.xml") #这里可以更换模型以满足不同的需求。
if img.ndim == 3:
gray = cv.cvtColor(img,cv2.COLOR_BGR2GRAY)
else:
gray = img
faces = face_cascade.detectMultiScale(gray, 1.3, 5)
for (x, y, w, h) in faces:
img = cv2.rectangle(img, (x, y), (x + w, y + h), (255, 0, 0), 2)
plt.imshow(img)
plt.axis("off")
plt.show()
cv.imwrite('图片输出.jpg',img)
detectFaces("图片导入.jpg")
查看输出的图片,识别率 4 / 6 ,算他及格。墨镜和遮挡都没有很好的识别出来:
继续使用 Face-recognition 的 HOG 算法和 Face-recognition 的 CNN 算法。代码如下:
# 使用 HOG 算法
import face_recognition
import cv2 as cv
import matplotlib.pyplot as plt
%matplotlib inline #在 jupyter Notebook 中正确输出图片
image = face_recognition.load_image_file("输入.jpg")
face_locations=face_recognition.face_locations(image)
face_num2=len(face_locations)
org = cv.imread("输入.jpg")
for i in range(0,face_num2):
top = face_locations[i][0]
right = face_locations[i][1]
bottom = face_locations[i][2]
left = face_locations[i][3]
start = (left, top)
end = (right, bottom)
color = (0,255,255)
thickness = 2
img=cv.rectangle(org, start, end, color, thickness)
plt.axis('off')
plt.show()
plt.imshow(img)
cv.imwrite('输出.jpg',img)
# 使用 CNN 算法
import face_recognition
import cv2 as cv
import matplotlib.pyplot as plt
image = face_recognition.load_image_file("输入.jpg")
face_locations_useCNN = face_recognition.face_locations(image,model='cnn') #同理可以更换不同模型
face_num1=len(face_locations_useCNN)
org = cv.imread("输入.jpg")
for i in range(0,face_num1):
top = face_locations_useCNN[i][0]
right = face_locations_useCNN[i][1]
bottom = face_locations_useCNN[i][2]
left = face_locations_useCNN[i][3]
start = (left, top)
end = (right, bottom)
color = (0,255,255)
thickness = 2
img=cv2.rectangle(org, start, end, color, thickness) # opencv 里面画矩形的函数
plt.imshow(img)
plt.axis('off') #去掉坐标轴
plt.show()
cv.imwrite('输出.jpg',img)
对比三次的识别结果,答案显而易见:深度学习就是牛!
2. 中级人脸识别
中级人脸识别难度上了一层楼。开始对 30 多人的大合影开始识别了!
由于代码基本没有调整,所以就直接上结果了。通过对比发现,结果差距不大。
3. 究极人脸识别
就前两轮的竞争来说,CNN 算法均是略胜一筹,但是 OpenCV 和 另外两种的差距还不算明显。但是我相信下面这一组的识别绝对超出你的想象。
这一组合影照片,不光人数众多,而且分辨率有限,遮挡也比较复杂。三种方法究竟谁能更胜一筹呢?上才艺!
从结果来看,表现优秀的 CNN 算法在这一轮翻车了,甚至还不如另外两种算法。相比较而言,OpenCV 对于低分辨率的人脸(比如后排同学)有着更好的识别能力;CNN 可以识别出更多的遮挡,反而 HOG 算法识别出了最多数量的人脸。
另外,CNN 算法的最大问题是运算时间比另外两种要久数倍,在一些需要快速响应的场景下就有很大的局限性了。
并不存在一劳永逸的万能算法和万能代码,各种方法实际上都各有利弊。没有最好,只有最合适。如何选择出最合适的代码,不仅要求对代码的运行原理有所了解,更重要的是对需求和应用场景有一个准确的判断。
4. 进阶:人脸定位和人脸核验
人脸定位是人脸检测的前置条件。这一功能可以实现对面部器官的形状、位置等等进行识别。我们经常使用的美颜、脸部贴纸、表情等等,都是基于人脸定位开始的。
下面的代码可以对图片上的人脸进行5点或是64点定位。
import cv2 as cv
import dlib
import matplotlib.pyplot as plt
img = cv.imread("图片.png")
gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
#人脸分类器
detector = dlib.get_frontal_face_detector()
# 获取人脸检测器
#predictor = dlib.shape_predictor(r"C:\Python36\Lib\site-packages\face_recognition_models\models\shape_predictor_68_face_landmarks.dat")
predictor = dlib.shape_predictor(r"data\shape_predictor_68_face_landmarks.dat")
dets = detector(gray, 1)
for face in dets:
shape = predictor(img, face) # 寻找人脸的68个标定点
# 遍历所有点,打印出其坐标,并圈出来
for pt in shape.parts():
pt_pos = (pt.x, pt.y)
img=cv2.circle(img, pt_pos, 2, (0, 255, 0), 1)
plt.imshow(img)
plt.axis('off') #去掉坐标轴
plt.show()
而人脸检测则可以对比不同图片中出现的脸部是否是同一人,并给出反馈。代码如下:
import cv2 as cv
import face_recognition
import matplotlib.pyplot as plt
known_image=cv.imread("ycy.jpg")
known_image = face_recognition.load_image_file("ycy.jpg")
unknown_image=cv.imread("ycy2.png")
unknown_image = face_recognition.load_image_file("ycy2.png")
known_encoding = face_recognition.face_encodings(known_image)[0]
unknown_encoding = face_recognition.face_encodings(unknown_image)[0]
results = face_recognition.compare_faces([known_encoding],unknown_encoding,tolerance=0.6)
if results[0] == True:
print("匹配成功,该未知图片与已有图片人脸可匹配!")
else:
print("匹配失败!")
#print(known_encoding)
#print(unknown_encoding)
plt.imshow(known_image)
plt.axis('off') #去掉坐标轴
plt.show()
plt.imshow(unknown_image)
plt.axis('off') #去掉坐标轴
二、遇到的问题
-
安装 Face-recognition 库
- 安装 Face-recognition 库需要先安装 dlib 库。而dlib 库又需要电脑有 VS C++ 的环境。所以应该先安装 VS (不是 VS Code,它只是一个编译器。)。
-
plt 显示图片的问题
在 jupyter 中,因为对图片进行了去色处理,所以
plt.show()
显示的是去色后的图片。只需要使用 OpenCV 的.imwrite
命令将图片存为本地即可。-
plt.show()
默认的图片输出分辨率其实很低。在进行图片编码时,一些行列的像素会被丢弃,所以有的图片上人脸的红框会消失。可以通过下面的代码调整图片分辨率和像素:plt.rcParams["savefig.dpi"] = 100 # 图片像素 plt.rcParams["figure.dpi"] = 100 # 分辨率
三、拓展一下
-
OpenCV 图像处理基本操作
-
OpenCV 和 FR 的基本技术原理