简单⼈脸识别⼀之使⽤opencv+cnn⽹络实现⼈脸识别
最近在研究⽬标检测这个⽅向,看到⽹上有很多的⼈脸识别帖⼦,所以也想着上上⼿看看。当时是做了三个模型出来,第⼀个就是⽹上很通⽤普遍的opencv+简单三层cnn⽹络来实现的,说实话效果真的⼀般吧!具体的下⾯再细细陈述。第⼆个是把三层cnn⽹络换成了残差⽹络。因为⾃⼰刚好也是学习了残差⽹络。就想着⽣搬硬套过来,但效果说实话很迷,时好时坏,把我是整蒙逼了,后⾯也会提的。最后⼀个是⽤opencv+MTCNN+FaceNet来实现的,效果就⽐较好了,训练速度快,检测⼈脸的准确率也⽐前两个模型更好。我接下来会写三篇⽂章来⼀⼀介绍!
⾸先来说说第⼀个烂⼤街的模型,代码量很少,其实也很容易理解。但是我在⽹上demo的时候真的是踩了不少的坑,不知道是作者故意⽽为之还是有些⼈本来就是copy其他⼈的,⾃⼰还偷懒没有跑,反正就是⾃⼰下载的⼏个demo跑的时候都报错,还是⾃⼰⼀⾏⼀⾏的看,改正了⼀些bug之后才跑出来的。说到这⼉,我就想强调⼀句:我们互联⽹⼯作者应该有⾃⼰的⼯作原则嘛:对待项⽬代码应该⼀丝不苟,决不祸害别⼈!此处默默给⾃⼰厚颜⽆耻的点赞哈哈哈哈哈哈哈。我给⼤家分享的代码绝对是经得起推敲的,如若打脸,本⼈绝不接受(傲娇脸.jpg)开个玩笑哈,我会把⼀些常见bug给贴出来避免⼤家踩坑,当然如若⼤家还有bug,也可以积极留⾔,我看到了会给⼤家回复的嘿嘿。
我下⾯将会按照如下⼏点来写:
1. 前期环境配置
2. ⼈脸检测
3. 训练模型
4. ⼈脸识别
我会在每⼀⼩节⾥⾯把相应的知识点普及给⼤家。
1. 前期环境配置
之所以写这⼀⼩节,是因为⾃⼰真的是在这⼀⼩节踩了不少坑,让我很蛋疼,所以不想让⼤家也跟着遭殃。
1. Python3.6 (虽然现在都到了3.7了,但我仍是觉得3.6是⽬前⽐较稳定的⼀个版本,
2.7版本都要舍弃了,所以⼤家不要再使⽤这个版
本了) Anaconda5.2
2. opencv (如果使⽤pip安装,即:pip install opencv-python 这⾥⾯版本号没有限制)
3. scipy1.2.1 (这个⼀定要注意呀,使⽤pip install scipy安装这个包的时候,⼀般都会安装1.3+的版本,在我这个程序⾥⾯就会报错
了,因为我是使⽤了1.2版本⾥⾯的⽅法,在1.3版本⾥⾯该⽅法舍弃了)
4. tensorflow1.9
5. keras2.2.0
6. sklearn
7. USB摄像头⼀枚,这个是很关键啦!没有这个任你的技术再⽜逼拍不到⼈脸也⽆济于事啊
配置⼤概是这些了,可能有的没写出来,可能就需要⼤家踩⼀些坑配置了(此处是不是要啪啪打脸了啊)
2. ⼈脸检测
由于本模型主要是使⽤opencv这个API完成⼈脸检测包括⼈脸识别的,有⼀句话叫:⼯欲善其事必先利其器,即要想使⽤opencv,就必须先知道其能⼲什么,怎么做。于是API的重要性便体现出来了。
就本例⽽⾔,使⽤到的函数很少,也就普通的读取图⽚,灰度转换,显⽰图像,简单的编辑图像罢了。
1)读取图⽚
只需要给出待操作的图⽚的路径即可。
1import cv2
2image = cv2.imread(imagepath)
2)灰度转换
灰度转换的作⽤就是:转换成灰度的图⽚的计算强度得以降低。因为现在的彩⾊图⽚都是三通道的数据,不做任何处理,数据量会很⼤,对于我们学⽣⽤的机⼦来说hold不住。
1import cv2
2gray = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
灰⾊图⽚⼤概就是这样的。
3)画图
opencv 的强⼤之处的⼀个体现就是其可以对图⽚进⾏任意编辑,处理。
下⾯的这个函数最后⼀个参数指定的就是画笔的⼤⼩。其实就是要把检测到的⼈脸边框给描出来。
1import cv2
⼤概如下图所⽰,⼤家请不要垂涎我的美⾊哈哈哈哈哈哈哈(狗头保命)
4)显⽰图像
编辑完的图像要么直接的被显⽰出来,要么就保存到物理的存储介质。
1import cv2
2cv2.imshow("Image Title",image)
5)获取⼈脸识别训练数据
看似复杂,其实就是对于⼈脸特征的⼀些描述,这样opencv在读取完数据后很据训练中的样品数据,就可以感知读取到的图⽚上的特征,进⽽对图⽚进⾏⼈脸识别。
1import cv2
2face_cascade = cv2.CascadeClassifier(r'./haarcascade_l')
⾥⾯的xml⽂件⾮常关键,可以说是这个模型的核⼼了,就是靠它才能获取到⼈脸数据的。它是opencv在GitHub上共享出来的具有普适的训练好的数据。我们可以直接的拿来使⽤。
训练数据参考地址:
6)探测⼈脸
说⽩了,就是根据训练的数据来对新图⽚进⾏识别的过程。
1import cv2
2
3# 探测图⽚中的⼈脸
4
5faces = face_cascade.detectMultiScale(
6  gray,
7  scaleFactor = 1.15,
8  minNeighbors = 5,
9  minSize = (5,5),
10  flags = cv2.cv.CV_HAAR_SCALE_IMAGE
11)
我们可以随意的指定⾥⾯参数的值,来达到不同精度下的识别。返回值就是opencv对图⽚的探测结果的体现。
处理⼈脸探测的结果
结束了刚才的⼈脸探测,我们就可以拿到返回值来做进⼀步的处理了。但这也不是说会多么的复杂,⽆⾮添加点特征值罢了。
1import cv2
2
3print "发现{0}个⼈脸!".format(len(faces))
4for(x,y,w,h) in faces:
5  angle(image,(x,y),(x+w,y+w),(0,255,0),2)
okay,以上就介绍完了⼀些必备函数,包括⼈脸检测的函数。那我们就是要来讲这个模型了,讲模型其实很好讲,⾸先获取训练数据,然后写好模型训练,最后检测效果即可。按照这个顺序来,我们先讲讲如何来收集⼈脸数据。
我们只要收集两个⼈的图⽚即可,考虑到⼤家的笔记本电脑配置,每个⼈只要收集200张图⽚即可。⽂件名记为get_face.py,代码如下:
1def CatchPICFromVideo(window_name, camera_idx, catch_pic_num, path_name):
2    cv2.namedWindow(window_name)
3    # 视频来源,可以来⾃⼀段已存好的视频,也可以直接来⾃USB摄像头
4    cap = cv2.VideoCapture(camera_idx)
5
6    # 告诉OpenCV使⽤⼈脸识别分类器
7    data_path = "haarcascade_l"
8    classfier = cv2.CascadeClassifier(data_path)
9
10    # 识别出⼈脸后要画的边框的颜⾊,RGB格式
11    color = (0, 255, 0)
12
13    num = 0
14    while cap.isOpened():
15        ok, frame = ad()  # 读取⼀帧数据
16        if not ok:
17            break
18
19        grey = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)  # 将当前桢图像转换成灰度图像
20        # ⼈脸检测,1.2和2分别为图⽚缩放⽐例和需要检测的有效点数
21        faceRects = classfier.detectMultiScale(grey, scaleFactor=1.2, minNeighbors=3, minSize=(32, 32))
22        if len(faceRects) > 0:  # ⼤于0则检测到⼈脸
23            for faceRect in faceRects:  # 单独框出每⼀张⼈脸
24                x, y, w, h = faceRect
25
26                # 将当前帧保存为图⽚
27                img_name = '%s/%d.jpg ' %(path_name, num)
28                image = frame[y - 10: y + h + 10, x - 10: x + w + 10]
29                cv2.imwrite(img_name, image)
30                num += 1
31                if num > catch_pic_num:  # 如果超过指定最⼤保存数量退出循环
32                    break
33
34                # 画出矩形框
35                angle(frame, (x - 10, y - 10), (x + w + 10, y + h + 10), color, 2)
36
37                # 显⽰当前捕捉到了多少⼈脸图⽚了,这样站在那⾥被拍摄时⼼⾥有个数,不⽤两眼⼀抹⿊傻等着
38                font = cv2.FONT_HERSHEY_SIMPLEX
39                cv2.putText(frame ,'num:%d' % (num) ,(x + 30, y + 30), font, 1, (255 ,0 ,255) ,4)
40
41                # 超过指定最⼤保存数量结束程序
42        if num > catch_pic_num:
43            break
44
45        # 显⽰图像
46        cv2.imshow(window_name, frame)
47          c = cv2.waitKey(10)
48        if c & 0xFF == ord('q'):
49            break
50    # 释放摄像头并销毁所有窗⼝
51    lease()
52    cv2.destroyAllWindows()
那就是这块⼉了,⼤家很清楚的看到,这个save_path⽂件夹⾥⾯保存的就是你拍的照⽚,因为你要保存两个⼈的照⽚,所以你到时候要跑两次这个程序,⽂件夹名称也要相应改变,收集两个⼈的照⽚。CatchPICFromVideo()函数⾥0, 199参数表⽰的是图⽚的序列号,即是0到199的200张图⽚。⼤致就是这样,程序跑起来的时候,⼤家记得不要动,乖乖的看向镜头保持微笑哈哈哈哈哈,⼤幅度的做⼀些夸张动作,拍出来的照⽚你会发现你死的⼼都有,这是来⾃⼀个过来⼈的忠⼼建议。
拍出来 照⽚⼤概就是这样,还有⼀点要注意:就是你的照⽚⼀定要连续,不要偷懒搞复制粘贴弄出来⼀⼤堆副本,⽐如900副本.jpg这种形式,顺序不连续程序会报错的。
3. 训练模型
数据拿到了,接下来就是要写模型训练了。本模型是采⽤了3个卷积操作+1个全连接操作实现的,关于卷积操作,这⼉就默认你是和我⼀样精通卷积操作的⼤佬了啊哈哈哈哈哈哈哈哈。我这⼉有⼀篇⽂章讲的还不错,不熟悉的推荐给⼤家看看:
模型代码如下:
1def build_model(self, dataset, nb_classes=2):
2        # 构建⼀个空的⽹络模型,它是⼀个线性堆叠模型,各神经⽹络层会被顺序添加,专业名称为序贯模型或线性堆叠模型
3        del = Sequential()
4
5        # 以下代码将顺序添加CNN⽹络需要的各层,⼀个add就是⼀个⽹络层
6        del.add(Convolution2D(32, 3, 3, border_mode='same',
7                                    input_shape=dataset.input_shape))  # 1 2维卷积层
8        del.add(Activation('relu'))  # 2 激活函数层
9
10        del.add(MaxPooling2D(pool_size=(2, 2)))  # 5 池化层
11        del.add(Dropout(0.25))  # 6 Dropout层
12
13        del.add(Convolution2D(64, 3, 3, border_mode='same'))  # 7  2维卷积层
14        del.add(Activation('relu'))  # 8  激活函数层
15
16        del.add(MaxPooling2D(pool_size=(2, 2)))  # 11 池化层
17        del.add(Dropout(0.25))  # 12 Dropout层
18
19        del.add(Flatten())  # 13 Flatten层
20        del.add(Dense(512))  # 14 Dense层,⼜被称作全连接层
21        del.add(Activation('relu'))  # 15 激活函数层
22        del.add(Dropout(0.5))  # 16 Dropout层
23        del.add(Dense(nb_classes))  # 17 Dense层
24        del.add(Activation('softmax'))  # 18 分类层,输出最终结果
25
26        # 输出模型概况rectangle函数opencv
27        del.summary()
因为是⽤keras写的,所以看起来⽐较简洁。
训练模型的函数也很简洁

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。