# -*- coding: utf-8 -*-
"""
Created on 2019/5/21 14:37
@Author: Johnson
@Email:593956670@qq.com
@File: face_reco01.py
"""
import os
import cv2
import numpy as np
from sklearn.model_selection import train_test_split
from keras.utils import to_categorical
from tensorflow.contrib.keras.api.keras.preprocessing.image import ImageDataGenerator,img_to_array
from keras.models import Sequential
from keras.layers.core import Dense, Dropout, Activation, Flatten
from keras.layers.advanced_activations import PReLU
from keras.layers.convolutional import Conv2D, MaxPooling2D,ZeroPadding2D,Convolution2D
from keras.preprocessing.image import load_img, img_to_array
from keras.optimizers import SGD
import numpy as np
import cv2
from keras.callbacks import *
import keras
path_name = ""
image_size = 128
def read_path(path_name): #搜索并读取对应路径下的图片,将其和其标签添加到数组 images和 lables中
numbers = []
images = []
labels = []
k = -1
for dir_item in os.listdir(path_name):
k = k + 1
numbers.append(str(dir_item))
# 从初始路径开始叠加,合并成可识别的操作路径
full_path = os.path.abspath(os.path.join(path_name, dir_item))
for image_item in os.listdir(full_path):
if image_item.endswith('.png'):
image_path = os.path.abspath(os.path.join(full_path, image_item))
image = cv2.imread(image_path)
images.append(image)
labels.append(k)
return images, labels, numbers
def load_dataset(path_name): # 从指定路径读取训练数据
images, labels, numbers = read_path(path_name)
# 将输入的所有图片转成四维数组,尺寸为(图片数量*IMAGE_SIZE*IMAGE_SIZE*3)
images = np.array(images)
return images, labels
def match_number(path_name): # 得到序号对应的学号
images, labels, numbers = read_path(path_name)
return numbers
class facetrain():
def __init__(self):
self.path_name = path_name
def dataload(self,img_rows=image_size,img_cols = image_size,img_channels=3,nb_classes=60):
#加载数据集到内存
images,labels = load_dataset(self.path_name)
#将数据集分别为训练集 验证集和测试集 划分比例为test_size
train_images,valid_images,train_labels,valid_labels = train_test_split(images,labels,test_size=0.2,random_state=0)
_, test_images, _, test_labels = train_test_split(images, labels, test_size=0.4,random_state = 0)
#tensorflow的维度顺序为行数 列数 通道数
#根据keras库要求的维度顺序重组训练数据集
train_images = train_images.reshape(train_images.shape[0],img_rows,img_cols,img_channels)
valid_images = valid_images.reshape(valid_images.shape[0],img_rows,img_cols,img_channels)
test_images = test_images.reshape(test_images.shape[0],img_rows,img_cols,img_channels)
self.input_shape = (img_rows,img_cols,img_channels)
#使用categorical_crossentropy作为损失函数
#根据累呗数量nb_classes将类别标签进行one-hot编码使其向量化
train_labels = to_categorical(train_labels,nb_classes)
valid_labels = to_categorical(valid_labels,nb_classes)
test_labels = to_categorical(test_labels,nb_classes)
#将数据浮点化方便归一化
train_images = train_images.astype("float32")
valid_images = valid_images.astype("float32")
test_images = test_images.astype("float32")
#归一化 图像的个像素值归一化到0-1区间
train_images/=255
valid_images/=255
test_images/=255
def build_model(self,dataset,nb_classes=60):
# 构建一个空的线性堆叠模型(序贯模型),各神经网络层会被顺序添加
self.model = Sequential()
# 以下代码将顺序添加CNN网络需要的各层,一个add就是一个网络层
self.model.add(Convolution2D(32, 3, 3, border_mode='same',input_shape = dataset.input_shape))# 1 2维卷积层
self.model.add(Activation('relu'))# 2 激活函数层
self.model.add(Convolution2D(32, 3, 3)) # 3 2维卷积层
self.model.add(Activation('relu')) # 4 激活函数层
self.model.add(MaxPooling2D(pool_size=(2, 2))) # 5 池化层
self.model.add(Dropout(0.25))# 6 Dropout层
self.model.add(Convolution2D(64, 3, 3, border_mode='same')) # 7 2维卷积层
self.model.add(Activation('relu')) # 8 激活函数层
self.model.add(Convolution2D(64, 3, 3)) # 9 2维卷积层
self.model.add(Activation('relu')) # 10 激活函数层
self.model.add(MaxPooling2D(pool_size=(2, 2))) # 11 池化层
self.model.add(Dropout(0.25)) # 12 Dropout层
self.model.add(Flatten()) # 13 Flatten层
self.model.add(Dense(512))# 14 Dense层,又被称作全连接层
self.model.add(Activation('relu')) # 15 激活函数层
self.model.add(Dropout(0.5)) # 16 Dropout层
self.model.add(Dense(nb_classes)) # 17 Dense层
self.model.add(Activation('softmax')) # 18 分类层,输出最终结果
self.model.summary() # 输出模型概况
def train(self,dataset,batch_size=20,nb_epoch=20): #训练模型
#采用SGD+momentum的优化器进行训练,首先生成一个优化器对象
sgd = SGD(lr=0.01,decay=1e-6,momentum=0.9,nesterov=True)
#完成实际的模型配置工作
self.model.compile(loss="categorical",optimizer=sgd,metrics=["accuracy"])
#使用实时数据提升,从训练数据中利用旋转,翻转 加噪声等方法创造新的训练数据
datagen = ImageDataGenerator(
rotation_range = 20,# 数据提升时图片随机转动的角度(范围为0~180)
width_shift_range = 0.2,# 数据提升时图片水平偏移的幅度
height_shift_range = 0.2, # 数据提升时图片垂直偏移的幅度
horizontal_flip = True) # 进行随机水平翻转
# 计算整个训练样本集的数量以用于特征值归一化、ZCA白化等处理
datagen.fit(dataset.train_images)
# 利用生成器开始训练模型
self.model.fit_generator(datagen.flow(dataset.train_images, dataset.train_labels, batch_size=batch_size),
samples_per_epoch=dataset.train_images.shape[0], nb_epoch=nb_epoch,validation_data = (dataset.valid_images, dataset.valid_labels))
MODEL_PATH = './model/facerec_model.h5'
def save_model(self, file_path=MODEL_PATH): # 存储模型
self.model.save(file_path)
def load_model(self, file_path=MODEL_PATH): # 加载模型
self.model = load_model(file_path)
def evaluate(self, dataset): # 模型评估
score = self.model.evaluate(dataset.test_images, dataset.test_labels, verbose=1)
print("%s: %.2f%%" % (self.model.metrics_names[1], score[1] * 100))
def face_recognize(self,image): #识别人脸
if K.image_dim_ordering()=="tf" and image.shape!=(1,image_size,image_size,3):
image = cv2.resize(image,(image_size,image_size))#尺寸必须与训练集保持一直
image = image.reshape((1,image_size,image_size,3))
image = image.astpe("float32")
image/=255
result = self.model.predict_proba(image) #给出输入属于各个类别的概率
result = self.model.predict_classes(image) #类别
return result[0] #
keras-人脸分类
最新推荐文章于 2021-02-25 14:51:59 发布