CNN人脸识别项目(dlib+opencv)

CNN人脸识别

  • 获取数据集
  • 读取数据集
  • 数据预处理
  • 建立模型进行预训练
  • 对图片进行人脸进行检测并进行可视化
  • 总结

思路:一个CNN人脸识别项目首先必不可少的是数据集,获取的方式有网站数据库 PubFig:Public Figures Face Database、Large-scale CelebFaces Attribtes(CelebA) Dataset、BioID Face Database-FaceDB、YouTube Face等网站,或者是自己根据需求在网页抓取图像并进行图像的一些预处理操作
然后是建立一个model用于训练数据集,根据精度大小判断网络模型的好坏
最后就是选取一个图片或者一个批次图片进行测试,并对其进行可视化

获取数据集

这里首先以PubFig:Public Figures Face Database网站的数据集格式进行讲解,然后再选取自己的图片进行替换即可,不要问为什么不自己弄,一是拿来主义多好理解就行,而是人家是多少团队搞出来的肯定比自己制定的标准吧
开始正文:
在网站下载的数据集包括person Name.txt和url.txt两个文件,person Name.txt用于存储所有人脸图像的名字,类似标签文本,url.txt文件则包括人名、图片序号、URL地址、人脸坐标和MD5校验码
CNN人脸识别项目(dlib+opencv)_第1张图片
CNN人脸识别项目(dlib+opencv)_第2张图片

现在就需要对数据集进行处理了,因为网络模型需要的是标签和图像,标签有了,图像需要我们根据url.txt中的URl地址进行抓取了,然后将抓取的图像进行分类,根据不同人名建立文件夹进行存储获取到原始图片newddata,但是训练模型要求的其实人脸,所以还需要在原始图片上截取人脸,因为url.txt已经含有截取后的人脸坐标直接进行读取得到cutdata

CNN人脸识别项目(dlib+opencv)_第3张图片 cutdata
CNN人脸识别项目(dlib+opencv)_第4张图片newdata
**具体代码如下:**
from urllib.request import urlretrieve
from urllib import request
from PIL import Image
import requests
import urllib
import socket
import re
import cv2
import os
import time
import random
import datetime

# 设置请求头
def get_headers():
    '''
    随机获取一个headers
    '''
    user_agents = [
                    'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.3578.80 Safari/537.36',
                    'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36',
                    'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.80 Safari/537.36',
                    'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.109 Safari/537.36'           
                    ]
    headers = ('User-Agent', random.choice(user_agents))
    print(headers)
    return headers


headers = ("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.109 Safari/537.36")

# 定义代理ip
# proxy_addr="128.199.81.214:12357"
# 
proxy_addr = "138.197.196.222"
post = '13499'
# #设置代理
# proxy=urllib.request.ProxyHandler({'http':proxy_addr})

proxy = urllib.request.ProxyHandler({'http':(proxy_addr + ':' + post)})

# 创建一个opener
opener = request.build_opener()
# 将headers添加到opener中
opener.addheaders = [headers]
# 将opener安装为全局
request.install_opener(opener)
# 用urlopen打开网页
# data=urllib.request.urlopen(url).read().decode('utf-8','ignore')

# 设定一下无响应时间,防止有的坏图片长时间没办法下载下来,10秒
timeout = 10000
socket.setdefaulttimeout(timeout)


#自定义一个下载进度函数,然后urlretrieve中赋值给reporthook参数即可
def callbackfunc(blocknum, blocksize, totalsize):
    '''回调函数
    @blocknum: 已经下载的数据块
    @blocksize: 数据块的大小
    @totalsize: 远程文件的大小
    '''
    time_stamp = datetime.datetime.now()
    percent = 100.0 * blocknum * blocksize / totalsize
    if percent > 100 or percent < 0 :
        percent = 100
    print("已完成:%.2f%%" % percent + "     " + time_stamp.strftime('%Y.%m.%d-%H:%M:%S'))


# 处理文件数据
# 从文件中读取人名和url
pic_data = []
with open('ch09\9 FaceRecognition\src\Preunder\data/url.txt') as f:
    for i in f.readlines():
        pic_data.append(i.strip('\r\n'))

new_data = []
for data in pic_data:
    if len(data.split()) == 6:
        name, surname, _, url, coord, _ = data.split()  # 名,姓,图片数量,url,人脸坐标,md5校验和
        new_data.append(name + ' ' + surname + ' ' + url + ' ' + coord)  # 返回 name surname+url+coord

# 写入到文件里面
with open('ch09\9 FaceRecognition\src\Preunder\data/urlAdd.data', 'w') as f:
    for i in new_data:
        f.write(i)
        f.write('\n')

# 从文件里面读:名,姓,url,人脸坐标
pic_data = []
with open('ch09\9 FaceRecognition\src\Preunder\data/urlAdd.data') as f:
    for i in f.readlines():
        pic_data.append(i.strip('\r\n'))

# 从文件里面读名字
names = []
with open('ch09\9 FaceRecognition\src\Preunder\data/personName.txt') as f:
    for i in f.readlines():
        names.append(i.strip('\r\n'))
# print(names[1])
num = 0
sucess = 0
for name in names:
#     print('name:' + name)
    # 创建保存原图目录
    if os.path.exists('../Preunder/data/newdata/' + name) == False:  # 判断文件夹是否存在
        # 不存在,创建文件夹
        os.mkdir('D:\wendang/vscode\CV/face_opencv\ch09\9 FaceRecognition\src\Preunder\data/newdata/' + name)
    # 创建中间量图片
    if os.path.exists('../Preunder/data/middata/' + name) == False:  # 判断文件夹是否存在
        # 不存在,创建文件夹
        os.mkdir('D:\wendang/vscode\CV/face_opencv\ch09\9 FaceRecognition\src\Preunder\data\middata/' + name)                 
    # 创建保存截取图像目录
    if os.path.exists('../Preunder/data/cutdata/' + name) == False:  # 判断文件夹是否存在
        # 不存在,创建文件夹
        os.mkdir('D:\wendang/vscode\CV/face_opencv\ch09\9 FaceRecognition\src\Preunder\data\cutdata/' + name)                 
#   print('========================================')
    count = 200
    for data in pic_data:
        pname, surname, url, coord = data.split()  # 名,姓,url,坐标
        url = str(url)
        coords = []
        coords = coord.split(',')
#         print('+++++++++++++'+name.split()[0]+ ' ' +name.split()[1])
        if pname == name.split()[0] and surname == name.split()[1]:
#             print(name.split()[0] + ';' + pname + ';' + name.split()[1] + ';' + surname)
            print('name:' + pname + ' ' + surname + '           count:%d' %(count-200))                              
            # 通过urllibs的requests获取所有的图片
            try:
                # 获取图片并保存到本地文件夹
                print(url)
                time_stamp = datetime.datetime.now()
                print("当前时间:" + time_stamp.strftime('%Y.%m.%d-%H:%M:%S'))
                
                print('saving.......') 
                
                pic = urlretrieve(url=url, filename='../Preunder/data/newdata/' + name + '/%d.jpg' % count, reporthook=callbackfunc)
                     
                print(pname + ' ' + surname + ': picture %d' %(count - 200))
                # 截取图片
                print('cuting.......')
                image = Image.open('../Preunder/data/newdata/' + name + '/%d.jpg' % count)
#               image = cv2.imread('../Preunder/data/newdata/' + name + '/%d.jpg' % count)  #从指定路径读取图像
#               cropImg = image[coords[0]:coords[2],coords[1]:coords[3]]    #截取指定脸部
                img = image.crop((int(coords[0]), int(coords[1]), int(coords[2]), int(coords[3])))
                img.save('../Preunder/data/middata/' + name + '/%d.jpg' % count)  # 保存图片为中间图片
#               cv2.imwrite("C:\\Users\\Desktop\\qwe\\",cropImg)     #保存到指定目录
                faceimage = cv2.imread('../Preunder/data/middata/' + name + '/%d.jpg' % count)  # 从指定路径读取图像
                  
                '''
                                    经过测试后得到脸部数据均小于128*128,
                                    所以暂时把灰度化和脸部截取统一大小改为后期进行或修改大小:64*64
                '''               
                  
                # 检查是否符合,符合则保存(128*128)  =>(64*64)
                sp = faceimage.shape  # 获取宽,高,深(深度有0-3,灰度-三种原色)
                print('recuting.......')
                if sp[0] > 128 and sp[1] > 128:    
                    gray = cv2.cvtColor(faceimage, cv2.COLOR_BGR2GRAY)  # 灰度化
                    face = cv2.resize(gray, (128, 128), interpolation=cv2.INTER_CUBIC)  # 设置截图大小并截取
                    cv2.imwrite('../Preunder/data/cutdata/' + name + '/%d.jpg' % count, face)  
                    print('save cutPic.......')
                else:
                    print("图片尺寸太小")
                sucess += 1
                count += 1
#                 time.sleep(random.randint(3, 10))  # 暂停5~10秒的整数秒,时间区间:[5,10]
            except Exception as e:
                print(Exception, ':', e)
                num += 1
                # 重新设置信息
                post = random.randint(139, 16000)
                proxy = urllib.request.ProxyHandler({'http':(proxy_addr + ':' + str(post))})
                opener = request.build_opener()
                # 将headers添加到opener中
                opener.addheaders = [get_headers()]
                # 将opener安装为全局
                request.install_opener(opener)
        else:
            count = 200  # 采取新人图像,初始化count
    
    # 输出一共采集成功数目和失败数目 
    print('采集对象  =====>>%s 成功次数:%d , 失败次数:%d' % (name, sucess, num))       
 
if __name__ == '__main__':
    get_headers()

以上代码看似很多其实很多是为了可视化美观,真正内容就根据url.txt图片url是抓取图片、建立人名文件夹放入对应图片,并根据url.txt人脸坐标信息将人脸图片同样放到人名文件里得到训练集图片

如果训练自己的图片数据集可以按照以上格式先建立相应的原始图片文件夹,然后利用dlib框架来检测人脸得到每个人名的人脸图片

首先读取自己设置的所有的原始图片newdata到列表里
这里的读取图片的前提是已经建立newdata文件夹,且里面包含不同人名的子文件夹,每个文件夹包含对应人名的原始图片,且每次只能读取一个人名类别的所有图片,如果想一次性读取所有人名类别的文件夹则需要优化部分代码

import os
import cv2


#根据输入的文件夹绝对路径,将该文件夹下的所有指定suffix的文件读取存入一个list,该list的第一个元素是该文件夹的名字
def readAllImg(path,*suffix):
    try:

        s = os.listdir(path)
        resultArray = []
        fileName = os.path.basename(path)
        resultArray.append(fileName)

        for i in s:
            if endwith(i, *suffix):
                document = os.path.join(path, i)
                img = cv2.imread(document)
                resultArray.append(img)
                
    except IOError:
        print("读取失败!")

    else:
        print("读取成功!")
        return resultArray

#输入一个字符串一个标签,对这个字符串的后续和标签进行匹配
def endwith(s,*endstring):
    resultArray = map(s.endswith,endstring)
    # if True in resultArray:
    #     return True
    # else:
    #     return False
    return resultArray

if __name__ == '__main__':

    result = readAllImg("ch09\shuju\LeiFeng_",'.jpg')
    print (result[0])
    cv2.namedWindow("Image")
    cv2.imshow("Image", result[1])
    cv2.waitKey(0)
    cv2.destroyAllWindows()

然后对图片检测人脸得到图片放入cutdata文件

import os
import cv2
import dlib
import time
from readImage import readAllImg

#从源路径中读取所有图片放入一个list,然后逐一进行检查,把其中的脸扣下来,存储到目标路径中
def readPicSaveFace(sourcePath,objectPath,*suffix):
    try:
        #读取照片,注意第一个元素是文件名
        resultArray=readAllImg(sourcePath,*suffix)

        #对list中图片逐一进行检查,找出其中的人脸然后写到目标文件夹下

        count = 1
#         face_cascade = cv2.CascadeClassifier('D:\opencv\sources\data\haarcascades\haarcascade_frontalface_alt.xml')
        # 使用detector进行人脸检测
        # 使用dlib自带的frontal_face_detector作为我们的特征提取器
        detector = dlib.get_frontal_face_detector()
        for i in resultArray:
            if type(i) != str:
                gray = cv2.cvtColor(i, cv2.COLOR_BGR2GRAY)
#                 faces = face_cascade.detectMultiScale(gray, 1.3, 5)
                dets = detector(gray, 1) # 提取截图中所有人脸
                for i, d in enumerate(dets): # 依次区分截图中的人脸
                    x1 = d.top() if d.top() > 0 else 0
                    y1 = d.bottom() if d.bottom() > 0 else 0
                    x2 = d.left() if d.left() > 0 else 0
                    y2 = d.right() if d.right() > 0 else 0
                    listStr = [str(int(time.time())), str(count)]  #以时间戳和读取的排序作为文件名称
                    fileName = ''.join(listStr)
 
                    f = cv2.resize(gray[x1:y1, x2:y2], (128, 128))  #设置截图大小并截取
                    cv2.imwrite(objectPath+os.sep+'%s.jpg' % fileName, f)
                    count += 1
                
#                 for (x, y, w, h) in faces:
# 
#                     listStr = [str(int(time.time())), str(count)]  #以时间戳和读取的排序作为文件名称
#                     fileName = ''.join(listStr)
# 
#                     f = cv2.resize(gray[y:(y + h), x:(x + w)], (128, 128))  #设置截图大小并截取
#                     cv2.imwrite(objectPath+os.sep+'%s.jpg' % fileName, f)
#                     count += 1


    except IOError:
        print("Error")

    else:
        print('Already read '+str(count-1)+' Faces to Destination '+objectPath)

if __name__ == '__main__':
    # 从文件里面读名字
#     names = []
#     with open('../src//name.txt') as f:
#         for i in f.readlines():
#             names.append(i.strip('\r\n'))
#     for name in names:
#         print(name)
#         readPicSaveFace('../src/Preunder/data/middata/' + name,
#                     '../src/Preunder/data/cutdata/' + name,
#                     '.jpg','.JPG','png','PNG')
    readPicSaveFace('ch09\shuju\LeiFeng',
                    'ch09\shuju\LeiFeng_',
                    '.jpg','.JPG','png','PNG')

读取数据集

将制定好的不同人名文件夹存储不同的人脸gray图片(128*128大小)读取文件名也就是人名作为标签和人脸图像作为数据

import os
import cv2
import numpy as np

from readImage import endwith

#输入一个文件路径,对其下的每个文件夹下的图片读取,并对每个文件夹给一个不同的Label
#返回一个img的list,返回一个对应label的list,返回一下有几个文件夹(有几种label)

def readFile(path):
    img_list = []    #图片
    label_list = []  #标签
    dir_counter = 0  #子目录夹数
    IMG_SIZE = 128   #截取脸部大小

    #对路径下的所有子文件夹中的所有jpg文件进行读取并存入到一个list中
#     COUNT = 1
    for child_dir in os.listdir(path):
        child_path = os.path.join(path, child_dir)
#         count = 1
#         print('子文件夹:'+ child_path)
        for dir_image in  os.listdir(child_path):
            if endwith(dir_image,'jpg','JPG','png','PNG'):
                img = cv2.imread(os.path.join(child_path, dir_image))
                cv2image = cv2.cvtColor(img, cv2.COLOR_BGR2RGBA)
#                 ROTTT = img.shape
#                 print(ROTTT[0])
#                 print(ROTTT[1])
#                 print(ROTTT[2])
#                 print('count:%d'%count)
                recolored_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) ## 图片转为灰度图 
#                 count +=1 
#                 recolored_img = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)         #灰度化图像
                resized_img = cv2.resize(recolored_img, (IMG_SIZE, IMG_SIZE))  #截取脸部  
                img_list.append(resized_img)
                label_list.append(dir_counter)

        dir_counter += 1

    # 返回的img_list转成了 np.array的格式
    img_list = np.array(img_list)

    return img_list,label_list,dir_counter

#因为我们是把同一个人的脸部图像放到一个文件夹里
#所以,文件夹名称是识别脸部的简单方法,后面会采用信息数据库进行数据的存储
#读取训练数据集的文件夹,把他们的名字返回给一个list
def readNameList(path):
    nameList = []
    for child_dir in os.listdir(path):
        nameList.append(child_dir)
    return nameList



if __name__ == '__main__':
    img_list,label_list,counter = readFile('ch09\9 FaceRecognition\images')  #文件夹下几个子文件夹
    print(label_list)

数据预处理

将读取到的label与imgs、类别数继进行预处理
也即train_test_split划分数据集 ,对图片进行归一化,对标签进行二进制化

from readData import readFile
from sklearn.model_selection import train_test_split
from keras.utils import np_utils
import random
# import os
# # 
# #临时改变底层神经网络使用theano搭建
# os.environ['KERAS_BACKEND'] = 'tensorflow'
# 
import keras.backend as K
#  
# K.set_image_dim_ordering('tf')


#建立一个用于存储和格式化读取训练数据的类
class modelDataSet(object):
    #初始化
    def __init__(self,path):
        self.num_classes = None
        self.X_train = None
        self.X_test = None
        self.Y_train = None
        self.Y_test = None
        self.img_size = 128     #128*128
        self.extract_data(path) #在这个类初始化的过程中读取path下的训练数据

    def extract_data(self,path):
        #根据指定路径读取出图片、标签和类别数
        imgs,labels,counter = readFile(path)
#         print(labels)
        #将数据集打乱随机分组,交叉验证中常用的函数,功能是从样本中随机的按比例选取train data和testdata
        #train_data:所要划分的样本特征集;train_target:所要划分的样本结果;test_size:样本占比,如果是整数的话就是样本的数量;random_state:是随机数的种子。
        X_train,X_test,y_train,y_test = train_test_split(imgs,labels,test_size=0.2,random_state=random.randint(0, 100))

        #重新格式化和标准化(或正常化), theano和tensorflow有很大的差别
        
        if K.image_data_format() == 'channels_first':
            #基于Theano
            X_train = X_train.reshape(X_train.shape[0], 1, self.img_size, self.img_size)/255.0  #数值为0-255,除以255图像化为0-1之间
            X_test = X_test.reshape(X_test.shape[0], 1, self.img_size, self.img_size) / 255.0
        else:
            #基于TensorFlow
            X_train = X_train.reshape(X_train.shape[0], self.img_size, self.img_size, 1)/255       #数值为0-255,除以255图像化为0-1之间
            X_test = X_test.reshape(X_test.shape[0], self.img_size, self.img_size, 1)/255
         
        
        X_train = X_train.astype('float32')    #指定数据类型为float32
        X_test = X_test.astype('float32')

        #将labels转成二进制矩阵
        Y_train = np_utils.to_categorical(y_train, num_classes=counter) #标签变为counter个长度 用十个长度举例:1:01;2:10
        Y_test = np_utils.to_categorical(y_test, num_classes=counter)

        #将格式化后的数据赋值给类的属性上
        self.X_train = X_train
        self.X_test = X_test
        self.Y_train = Y_train
        self.Y_test = Y_test
        self.num_classes = counter

    def check(self):
        print('num of dim:', self.X_test.ndim)  #层数
        print('shape:', self.X_test.shape)      #标签
        print('size:', self.X_test.size)        #尺寸

        print('num of dim:', self.X_train.ndim)
        print('shape:', self.X_train.shape)
        print('size:', self.X_train.size)

建立模型进行预训练

from modelDataSet import modelDataSet
from keras.models import Sequential,load_model
from keras.layers import Dense,Activation,Conv2D,MaxPooling2D,Flatten,Dropout
from keras.optimizers import *
import numpy as np




#建立一个基于CNN的人脸识别模型
class trainFaceModel(object):
    FILE_PATH = "ch09\9 FaceRecognition\image\model/model1.h5"   #模型进行存储和读取的地方
    IMAGE_SIZE = 128    #图片是64*64的

    def __init__(self):
        self.model = None

    #读取实例化后的modelDataSet类作为进行训练的数据源
    def read_trainData(self,modeldataset):
        self.modeldataset = modeldataset

    #建立一个CNN模型,一层卷积、一层池化、一层卷积、一层池化、抹平之后进行全连接、最后进行分类
    def build_model(self):
        #1.建立model:Sequential为按顺序建立model(一层一层来)
        self.model = Sequential()
        #标准卷积公式:Convolution1D主要用于nlp,Convolution2D主要用于cv
        #表面上Convolution1D没有给出卷积的大小,Convolution2D给出了
        
        #第一层
        self.model.add(
            Conv2D(
                filters=64,          #滤波器数量,最后出现多少层特征
                kernel_size=(4, 4), #row,low
                padding='same',      #padding(边界)模式,为"valid"或"same"
#                 dim_ordering='th',   #指明底层backend是theano(th)还是TensorFlow(tf)
                #作为第一层需提供input_shape参数
                input_shape=self.modeldataset.X_train.shape[1:]  
            )
        )
        self.model.add(Activation('relu'))  #激活
        self.model.add(
            MaxPooling2D(
                pool_size=(2, 2),  #向下取样多长多宽
                strides=(2, 2),    #跳的长度和宽度
                padding='same'     #padding(边界)模式,为"valid"或"same"
            )
        )
        
        #第二层
        self.model.add(
            Conv2D(
                filters=128, 
                kernel_size=(4, 4), 
                padding='same')
            )       
        self.model.add(Activation('relu'))
        self.model.add(MaxPooling2D(
            pool_size=(2, 2), 
            strides=(2, 2),
            padding='same'
            )
        )
                     
        #,第一个全连接层
        #把N维抹平为一维
        self.model.add(Flatten())
        #输入batch_size*row*col=1568,输出512,输出为自己设置的
        self.model.add(Dense(2048))
        self.model.add(Activation('relu'))
        
        #第二个全连接层,输出:self.modeldataset.num_classes
        self.model.add(Dense(self.modeldataset.num_classes))
        #分类
        self.model.add(Activation('softmax'))
        self.model.summary()
    #添加指标获取想要的信息
    def train_model(self):
        #定义优化器的另一种方法
#         rmsprop = RMSprop(lr=0.001,rho=0.9,epsilon=1e-08,decay=0.0)  #可以改参数
        #自定义损失函数
        self.model.compile(
            optimizer='adam',  #优化器
#             optimizer=rmsprop,  #优化器
            #目标函数,即损失函数,binary_crossentropy:对数损失
            #categorical_crossentropy:多类的对数损失,需将标签转化为形如(nb_samples, nb_classes)的二值序列
            loss='categorical_crossentropy',  
            metrics=['accuracy'])

        #epochs、batch_size为可调的参数,epochs为训练多少轮、batch_size为每次训练多少个样本
        self.model.fit(self.modeldataset.X_train,self.modeldataset.Y_train,epochs=3,batch_size=10)
    #使用前面的度量来评估模型
    def evaluate_model(self):
        print('\n测试中---------------')
        loss, accuracy = self.model.evaluate(self.modeldataset.X_test, self.modeldataset.Y_test)

        print('测试损失度:', loss)          
        print('测试精准度:', accuracy)
        return loss,accuracy

    def save(self, file_path=FILE_PATH):
        print('Model保存.')
        self.model.save(file_path)

    def load(self, file_path=FILE_PATH):
        print('Model加载.')
        self.model = load_model(file_path)

    #需要确保输入的img得是灰化之后(channel =1 )且 大小为IMAGE_SIZE的人脸图片
    def predict(self,img):
        img = img.reshape((1, self.IMAGE_SIZE, self.IMAGE_SIZE,1))#Reshape层用来将输入shape转换为特定的shape
        img = img.astype('float32')
        img = img/255.0    #标准化

        result = self.model.predict_proba(img)  #测算一下该img属于某个label的概率
        max_index = np.argmax(result) #找出概率最高的

        return max_index,result[0][max_index] #第一个参数为概率最高的label的index,第二个参数为对应概率


if __name__ == '__main__':
    modelDataSet = modelDataSet('ch09\9 FaceRecognition\images')
    model = trainFaceModel()
    model.read_trainData(modelDataSet)
    model.build_model()
    model.train_model()
    model.evaluate_model()
    model.save()

对图片进行人脸进行检测并进行可视化

可以对一个图片或者批次的图片进行检测,在人脸检测时可以利用dlib或者opencv的级联检测器都可以这里选择dlib

from readData import readNameList,readFile
from trainFaceModel import trainFaceModel
import dlib
import cv2
detector = dlib.get_frontal_face_detector()
face_cascade = cv2.CascadeClassifier('D:\miniconda\envs\py3.6\Lib\site-packages\cv2\data\haarcascade_frontalface_default.xml') 
IMAGE_SIZE = 128

def test_onePicture(path):
    model= trainFaceModel()
    model.load()
    img = cv2.imread(path)
    #检测里的人脸并标记
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) ## 图片转为灰度图            
    dets = detector(gray, 1) # 提取截图中所有人脸
    for i, d in enumerate(dets): # 依次区分截图中的人脸
        x1 = d.top() if d.top() > 0 else 0
        y1 = d.bottom() if d.bottom() > 0 else 0
        x2 = d.left() if d.left() > 0 else 0
        y2 = d.right() if d.right() > 0 else 0
        
        ROI = gray[x1:y1, x2:y2]
        ROI = cv2.resize(ROI, (IMAGE_SIZE, IMAGE_SIZE), interpolation=cv2.INTER_LINEAR)
        label,prob = model.predict(ROI)  #利用模型对cv2识别出的人脸进行比对
        if prob >0.775:
            name_list = readNameList('ch09\9 FaceRecognition\images')
            print(name_list[label],prob)
            cv2.putText(img, name_list[label]+":"+str(prob), (x2, x1), cv2.FONT_HERSHEY_SIMPLEX, 1, (150, 200, 56), 2)  #显示名字
            cv2.rectangle(img, (x2, x1), (y2, y1), (150, 200, 56), 2)  #在人脸区域画一个正方形出来
        else:
            print("无法识别此人!")
    #显示起来
    cv2.imshow('Image', img)
    cv2.waitKey(0) & 0xff
    cv2.destroyAllWindows()
#     img = cv2.resize(img, (128, 128))
#     img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
#     picType,prob = model.predict(img)
#     if picType != -1:
#         name_list = readNameList('../src/Preunder/data/cutdata')
#         print(name_list[picType],prob)
#         return name_list[picType],prob
#     else:
#         print("无法识别此人!")
#         return "无法识别此人!"

#读取文件夹下子文件夹中所有图片进行识别
def test_onBatch(path):
    model= trainFaceModel()
    model.load()
    index = 0
    img_list, label_list, counter = readFile(path)
    for img in img_list:
        picType,prob = model.predict(img)
        if picType != -1:
            index += 1
            name_list = readNameList('ch09\9 FaceRecognition\images')
            print(name_list[picType])
        else:
            print("无法识别此人!")

    return index

if __name__ == '__main__':
    test_onePicture('ch09\shuju/testima\LeiFengTest.jpg')

运行结果得到
CNN人脸识别项目(dlib+opencv)_第5张图片

总结

总体设计思路可以用以下流程图表示
CNN人脸识别项目(dlib+opencv)_第6张图片

你可能感兴趣的:(计算机视觉,深度学习,tensorflow,pytorch,深度学习)