使用CNN实现手机头像解锁

之前公司项目有使用CNN识别人脸,于是写写博客,复习一下~~~

手机头像的解锁功能,首先是在第一次设置头像解锁的时候,使用前置摄像头拍摄一段关于自己的小视频,再处理成N张自己的照片,将这些图片打上标签,再与其他人的照片混合在一起,就构成了图片的原始训练数据集和测试数据集。

然后使用CNN模型进行训练,在需要解锁的时候,使用前置摄像头识别头像,再进行分类,识别我与非我。我,解锁。非我,不解锁。

首先,加载我们的图片们

#打开训练图片数据
filedir = "C:\\Users\\lenovo\\Documents\\tfstudy\\pic"
categorys = ["me","notme"]
imagearrays,labels,_ = util.image_arrays(categorys, filedir, True)
imagearrays.shape
#打开测试图片数据
filedir = "C:\\Users\\lenovo\\Documents\\tfstudy\\pic\\meornotme"
testarrays,testlabels,_ = util.image_arrays(categorys, filedir, True)
testarrays.shape

这里加载的图片大小为1920 * 1080

图片的labels使用get_dummies()方法进行哑变量处理,即:

labels = pd.get_dummies(labels)
labels.columns = [1, 2]
labels

创建一个next_batch()的方法,以便后续的随机梯度下降:

#准备训练数据
def next_batch(batchsize, x, y):
    n_batches = x.shape[0] // batchsize
    x = x[:n_batches * batch_size, :, : , :]
    y = y.iloc[:n_batches * batchsize, :]
    
    for n in range(0, len(y), batchsize):
        batch_x = x[n : n + batchsize, :, :, :]
        batch_y = y.iloc[n : n + batchsize, :]
        yield batch_x, batch_y

在处理完我们的训练集数据和测试集数据后,我们还可以顺便选一张图片显示一下,保证取出数据的准确性:

#展示其中一张图片
%matplotlib inline
import matplotlib.pyplot as plt
plt.imshow(np.reshape(data[11],(1920,1080)), cmap ='gray')

 运行得到博主我的女友照片一张(哈哈,没人可以和我抢!!):

准备工作现在完成,开始我们CNN网络的搭建,CNN网络的搭建参考Alexnet,图片处理流程图如下:

#设置超参数
learning_rate = 0.01
epochs = 10000 #一共运行几大轮
batch_size = 256 #随机梯度下降,一小轮含多少张图片

#用来验证和计算模型评分的样本数
test_valid_size = 256

#神经网络参数
n_classess = 2 #只有两类,我和非我
drop_out = 0.75
weights = {
    #卷积层1 : 11 * 11 数量48个 步长4
    "wc1" : tf.Variable(tf.truncated_normal([11, 11, 1, 48], dtype=tf.float32)),
    #卷积层2 : 5 * 5 数量128个 步长1
    "wc2" : tf.Variable(tf.truncated_normal([5, 5, 48, 128], dtype=tf.float32)),
    #卷积层3: 3 * 3 数量192个 步长1
    "wc3" : tf.Variable(tf.truncated_normal([3, 3, 128, 192], dtype=tf.float32)),
    #卷积层4: 3 * 3 数量192个 步长1
    "wc4" : tf.Variable(tf.truncated_normal([3, 3, 192, 192], dtype=tf.float32)),
    #卷积层5: 3 * 3 数量128个 步长1
    "wc5" : tf.Variable(tf.truncated_normal([3, 3, 192, 128], dtype=tf.float32)),
    #全连接层1: 含1024个隐藏神经元
    "wd1" : tf.Variable(tf.truncated_normal([60 * 34 * 128, 1024], dtype=tf.float32)),
    #全连接层2:  含1024个隐藏神经元
    "wd2" : tf.Variable(tf.truncated_normal([1024, 1024], dtype=tf.float32)),
    #softmax全连接层: 含两个out神经元
    "out" : tf.Variable(tf.truncated_normal([1024, n_classess], dtype=tf.float32))
}

biases = {
    "bc1" : tf.Variable(tf.zeros([48], dtype=tf.float32)),
    "bc2" : tf.Variable(tf.zeros([128], dtype=tf.float32)),
    "bc3" : tf.Variable(tf.zeros([192], dtype=tf.float32)),
    "bc4" : tf.Variable(tf.zeros([192], dtype=tf.float32)),
    "bc5" : tf.Variable(tf.zeros([128], dtype=tf.float32)),
    "bd1" : tf.Variable(tf.zeros([1024], dtype=tf.float32)),
    "bd2" : tf.Variable(tf.zeros([1024], dtype=tf.float32)),
    "out" : tf.Variable(tf.zeros([n_classess], dtype=tf.float32))
}

卷积层处理:

def con2d(x, w , b, strides = 1, mode = "SAME"):
    x = tf.nn.conv2d(input=x, filter=w, 
                    strides = [1, strides, strides, 1], padding = mode)
    return tf.nn.relu(x)

池化层处理:

def maxpool2d(x, k = 2, mode = "SAME"):
    x = tf.nn.max_pool(x, strides=[1, k, k, 1],
                      ksize = [1, k, k, 1], padding = mode)
    return x

 CNN网络的搭建:

def conv_net(x, weights, biases, dropout = 1):
    #卷积层1 1920 * 1080 to 480 * 270
    conv1 = con2d(x, weights["wc1"], biases["bc1"], strides=4)
    #池化 480 * 270  to 240 * 135
    conv1 = maxpool2d(conv1, k = 2)
    
    #卷积层2 240 * 135 to 240 * 135
    conv2 = con2d(conv1, weights["wc2"], biases["bc2"], strides=1)
    #池化 240 * 135 to 120 * 68
    conv2 = maxpool2d(conv2, k = 2)
    
    #卷积层3 120 * 68 to 120 * 68
    conv3 = con2d(conv2, weights["wc3"], biases["bc3"], strides=1)
    
    #卷积层4 120 * 68 to 120 * 68
    conv4 = con2d(conv3, weights["wc4"], biases["bc4"], strides=1)
    
    #卷积层5 120 * 68 to 120 * 68
    conv5 = con2d(conv4, weights["wc5"], biases["bc5"], strides=1)
    #池化 120 * 68 to 60 * 34
    conv5 = maxpool2d(conv5, k = 2)
    
    #全连接层1 60 * 34 * 128 to 1024
    fc1 = tf.reshape(conv5, shape = [-1, weights["wd1"].get_shape().as_list()[0]])
    fc1 = tf.matmul(fc1, weights["wd1"])
    fc1 = tf.add(fc1, biases["bd1"])
    fc1 = tf.nn.relu(fc1)
    fc1 = tf.nn.dropout(fc1, keep_prob=dropout)
    
    #全连接层2 1024 to 1024
    fc2 = tf.matmul(fc1, weights["wd2"])
    fc2 = tf.add(fc2, biases["bd2"])
    fc2 = tf.nn.relu(fc2)
    fc2 = tf.nn.dropout(fc1, keep_prob=dropout)
    
    #输出层 1024 to 2
    out = tf.matmul(fc2, weights["out"])
    out = tf.add(out, biases["out"])
    return out

 构建损失,梯度下降,准确率:

#损失与梯度下降
logits = conv_net(x, weights, biases, keep_prob)
loss = tf.nn.softmax_cross_entropy_with_logits(logits=logits, labels=y)
optimizer = tf.train.AdamOptimizer(learning_rate=learning_rate).minimize(loss)

#准确率
correct_pred = tf.equal(tf.argmax(logits, 1), tf.argmax(y, 1))
accuracy = tf.reduce_mean(tf.cast(correct_pred, tf.float32))

一切准备就绪,现在开启Session会话,运行随机梯度下降,最后检测模型的准确度:

#启动会话,开始训练
with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())
    
    for epoch in range(epochs):
        accur = 0
        for batch_x, batch_y in next_batch(batch_size, data, labels):
            feed = {
                x : batch_x,
                y : batch_y,
                keep_prob : drop_out
            }
            
            feed_valid = {
                x : batch_x,
                y : batch_y,
                keep_prob : 1
            }
            
            sess.run(optimizer, feed_dict=feed)
            valid_accur = sess.run(accuracy, feed_dict=feed_valid)
            accur += valid_accur
            
        print("第",epoch, "轮,准确率为:", accur/(data.shape[0]// batch_size))

    #测试集准确率
    test_acc = sess.run(accuracy, feed_dict={
        x: testdata,
        y: testlabels,
        keep_prob :1.})
    print('Testing Accuracy: {}'.format(test_acc)) 

源码地址:

https://github.com/freeingfree/cnn

 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值