玩转Jetson Nano(七)人脸识别(一)

之前的几篇博文都是搭建环境,总觉得不拿nano做点什么写出来我的这个系列就好像缺点啥,今天难得有空,写写自己做的一个人脸识别的心得。这个小程序用了一天写出来,再加上已经很久不写代码了,瑕疵在所难免,请各位包涵了!

其实这个小项目是分两个部分,第一部分是通过Jetson Nano完成,主要工作是建立模型,训练模型以及导出模型参数。第二部分是在我的笔记本上完成,因为我的笔记本有摄像头,而且用windows系统设计界面要容易的多。

一,前期准备

1.   准备数据

       人脸识别系统的数据当然是人脸,我没用网上那些人脸库,而是用的自己同事的脸。因为我是团队的领导,这些同事迫于我的淫威...。 这里要说明一下图片存储的结构,因为以后做标签的时候方便。你应该给每一个同事设定一个文件夹,然后把这些文件夹存放在一个大的文件夹里。我的目录结构如下图所示,data文件夹下都是照片,每个人100张

2. 系统环境如下,如何搭建参看前文

nano 上: Keras2.2.4 ,OpenCV3.3.1,Python3.6.7

笔记本上: Keras2.2.4 ,OpenCV4.1, Python3.6.7,Pyqt5.0

二,代码编写

1.  建立样本集

import numpy as np
import os
import glob
import cv2
from keras.utils.np_utils import to_categorical
from keras.layers.convolutional import Conv2D, MaxPooling2D
from keras.models import Sequential
from keras.initializers import truncated_normal
from keras.layers import Flatten, Dense, Dropout
from keras import regularizers
from keras.optimizers import Adam

# 训练用图片存放路径
p_path = '/home/beckhans/Projects/FaceCNN/data'

# 将所有的图片resize成128*128
w = 128
h = 128
c = 3


def read_img(path):
    # 读取当前文件夹下面的所有子文件夹
    cate = [path + '/' + x for x in os.listdir(path) if os.path.isdir(path + '/' + x)]
    # 图片数据集
    imgs = []
    # 标签数据集
    labels = []
    for idx, folder in enumerate(cate):
        for im in glob.glob(folder + '/*.jpg'):
            print('reading the images:%s' % im)
            # 读取照片
            img = cv2.imread(im)
            # 将照片resize128*128*3
            img = cv2.resize(img, (w, h))
            imgs.append(img)
            labels.append(idx)
    return np.asarray(imgs, np.float32), np.asarray(labels, np.int32)

上面的代码关键位置都写了注释,相信大家都看得懂。标签部分我是用文件夹的索引值代替。下面截了一个我程序的debug画面来说明,其中0~4分别是每个人的索引值,我是4号。

2. 搭建模型

图片输入后,经历了4次卷积,每一次卷积后进行了池化。然后铺平,经过三个全连接层输出结果。代码并不难,相信大家能够看懂。

def cnnlayer():
    # 第一个卷积层(128——>64)
    model = Sequential()
    conv1 = Conv2D(
        input_shape=[128, 128, 3],
        filters=32,
        kernel_size=(5, 5),
        strides=(1, 1),
        padding="same",
        activation="relu",
        kernel_initializer=truncated_normal(mean=0.0, stddev=0.01, seed=None))
    pool1 = MaxPooling2D(pool_size=(2, 2),
                         strides=2)
    model.add(conv1)
    model.add(pool1)
    # 第二个卷积层(64->32)
    conv2 = Conv2D(filters=64,
                   kernel_size=(5, 5),
                   padding="same",
                   activation="relu",
                   kernel_initializer=truncated_normal(mean=0.0, stddev=0.01, seed=None))
    pool2 = MaxPooling2D(pool_size=[2, 2],
                         strides=2)
    model.add(conv2)
    model.add(pool2)

    # 第三个卷积层(32->16)
    conv3 = Conv2D(filters=128,
                   kernel_size=[3, 3],
                   padding="same",
                   activation="relu",
                   kernel_initializer=truncated_normal(mean=0.0, stddev=0.01, seed=None))
    pool3 = MaxPooling2D(pool_size=[2, 2],
                         strides=2)
    model.add(conv3)
    model.add(pool3)

    # 第四个卷积层(16->8)
    conv4 = Conv2D(filters=128,
                   kernel_size=[3, 3],
                   padding="same",
                   activation="relu",
                   kernel_initializer=truncated_normal(mean=0.0, stddev=0.01, seed=None))
    pool4 = MaxPooling2D(pool_size=[2, 2],
                         strides=2)
    model.add(conv4)
    model.add(pool4)
    model.add(Flatten())
    model.add(Dropout(0.5))
    # 全连接层
    dense1 = Dense(units=1024,
                   activation="relu",
                   kernel_initializer=truncated_normal(mean=0.0, stddev=0.01, seed=None),
                   kernel_regularizer=regularizers.l2(0.003))
    model.add(Dropout(0.5))
    dense2 = Dense(units=512,
                   activation="relu",
                   kernel_initializer=truncated_normal(mean=0.0, stddev=0.01, seed=None),
                   kernel_regularizer=regularizers.l2(0.003))
    model.add(Dropout(0.5))
    dense3 = Dense(units=5,
                   activation='softmax',
                   kernel_initializer=truncated_normal(mean=0.0, stddev=0.01, seed=None),
                   kernel_regularizer=regularizers.l2(0.003))
    model.add(dense1)
    model.add(dense2)
    model.add(dense3)
    return model

3. 训练模型

if __name__ == '__main__':
    data, label = read_img(p_path)

    num_example = data.shape[0]
    arr = np.arange(num_example)
    
    # 打乱顺序
    np.random.shuffle(arr)
    data = data[arr]
    label = label[arr]

    # 将所有数据分为训练集和验证集
    ratio = 0.8
    s = np.int(num_example * ratio)
    x_train = data[:s]
    y_train = label[:s]
    y_train = to_categorical(y_train, num_classes=5)
    x_val = data[s:]
    y_val = label[s:]
    y_val = to_categorical(y_val, num_classes=5)

    # 使用Adam优化器
    model = cnnlayer()
    
    # 设定学习率0.01
    adam = Adam(lr=0.001)
    
    # 使用分类交叉熵作为损失函数
    model.compile(loss='categorical_crossentropy', optimizer=adam, metrics=['accuracy'])

    # 训练模型
    model.fit(x_train, y_train, batch_size=32, epochs=10)
    score = model.evaluate(x_val, y_val, batch_size=32)

    print('Test score:', score[0])
    print('Test accuracy:', score[1])
    # 模型保存
    model.save("CNN.model")

 运行上面这段代码时,pycharm给出的调试信息,禁用Ubuntu桌面后,freeMemory还是挺大的。

name: NVIDIA Tegra X1 major: 5 minor: 3 memoryClockRate(GHz): 0.9216
pciBusID: 0000:00:00.0
totalMemory: 3.87GiB freeMemory: 2.35GiB

经历了几分钟的等待,把十次Epoch的结果贴出来,准确率居然达到100%,看来我的388张测试照片还是有点单调。

2019-04-26 12:59:37.485012: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1512] Adding visible gpu devices: 0
2019-04-26 12:59:43.495710: I tensorflow/core/common_runtime/gpu/gpu_device.cc:984] Device interconnect StreamExecutor with strength 1 edge matrix:
2019-04-26 12:59:43.495780: I tensorflow/core/common_runtime/gpu/gpu_device.cc:990]      0 
2019-04-26 12:59:43.495805: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1003] 0:   N 
2019-04-26 12:59:43.495943: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1115] Created TensorFlow device (/job:localhost/replica:0/task:0/device:GPU:0 with 1632 MB memory) -> physical GPU (device: 0, name: NVIDIA Tegra X1, pci bus id: 0000:00:00.0, compute capability: 5.3)
2019-04-26 12:59:51.670396: I tensorflow/stream_executor/dso_loader.cc:153] successfully opened CUDA library libcublas.so.10.0 locally
388/388 [==============================] - 44s 114ms/step - loss: 2.7606 - acc: 0.2294
Epoch 2/10
388/388 [==============================] - 8s 20ms/step - loss: 1.8454 - acc: 0.2758
Epoch 3/10
388/388 [==============================] - 8s 19ms/step - loss: 1.1088 - acc: 0.6753
Epoch 4/10
388/388 [==============================] - 8s 19ms/step - loss: 0.5395 - acc: 0.9356
Epoch 5/10
388/388 [==============================] - 8s 19ms/step - loss: 0.3405 - acc: 0.9923
Epoch 6/10
388/388 [==============================] - 8s 19ms/step - loss: 0.3979 - acc: 0.9871
Epoch 7/10
388/388 [==============================] - 8s 19ms/step - loss: 0.5559 - acc: 0.9510
Epoch 8/10
388/388 [==============================] - 8s 19ms/step - loss: 0.3960 - acc: 0.9794
Epoch 9/10
388/388 [==============================] - 8s 20ms/step - loss: 0.3820 - acc: 0.9871
Epoch 10/10
388/388 [==============================] - 8s 19ms/step - loss: 0.3958 - acc: 0.9897
97/97 [==============================] - 3s 33ms/step
Test score: 0.31855019189647793
Test accuracy: 1.0

 

  • 17
    点赞
  • 112
    收藏
    觉得还不错? 一键收藏
  • 19
    评论
评论 19
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值