首先这个案例很简单,属于浅层次的神经网络,属于一个综合性案例。
分别需要以下几个步骤:
1.样本收集;2.图像预处理;3.tensorflow神经网络
这里对应的就是以下几个知识点:1.python图片的爬虫;2.opencv预处理;3.tensorflow卷积神经网络
一、样本收集
简单的爬虫使用;视频截取图片,ffmpeg命令行的使用。
1.理解爬虫原理,2.实现图片的爬虫:
1.了解http请求;2.了解html网页规则;3.正则表达式的过滤条件;4.其他
1.url;2.html网页的src路径;3.image图片;4.图片的url链接
对应的简单的爬虫代码如下:
import urllib
import urllib3
import os
from bs4 import BeautifulSoup
# 获取解析当前html的内容和图片
# 加载当前的urll
html = urllib.request.urlopen('https://class.imooc.com/?c=ios&mc_markin').read()
# 解析当前的url,解析的是url下的data数据;第一个参数:html整个页面,第二个参数:html.parser方法,第三个参数:编码方式
soup = BeautifulSoup(html, 'html.parser', from_encoding='utf-8')
# 获取当前image的标签,使用findAll方法获取图片的所有标签
images = soup.findAll('img')
print(images)
# 拿到图片运用for循环的方式进行遍历图片,进行图像的预处理
imageName = 0
for image in images:
# 遍历完后,我们通过src获取当前具体的一个url网址
link = image.get('src')
print('link=', link)
# 获取的网址不完整,因为没有http请求,接下来就需要就加上http请求
link = 'http:'+link
# 这里获取的.svg;.png;.jpg等文件,我们这里爬虫的是图片,所以需要过滤一下:
fileFormat = link[-3:] # 获取文件名,获取文件名中最后的三个字符
if fileFormat == 'png' or fileFormat == 'jpg':
fileSavePath = 'minst/'+str(imageName)+'.jpg'
imageName = imageName + 1
# 通过request下的urlretrieve方法进行文件的下载和保存
urllib.request.urlretrieve(link, fileSavePath)
结果的截图:
二、图像预处理
人脸的提取(haar+adaboost+xml文件)完成人脸的采集。这样得到的图片就是我们需要的数据。
ffmpeg的图片的处理:
样本采集车在某些路段进行视频的采集,然后运用利用视频分解图片。
之前有说过运用opencv的包来进行视频的截取,在这里,运用ffmpeg工具进行图片的截取。opencv截取视频的库的本质其实也是ffmpeg来做的。
ffmpeg是一个具有处理音视频功能的软件库。它是由一系列的音视频处理的编解码的api组成,源码开放,绝大部分的视频播放器要基于这个库来完成,可以完成文件格式的转换,编解码的转换等等,同时,还可以对视频的剪切,录制,提取和复用等等功能,在这里只是简单介绍了解一下。
接下来就是图片的截取了,将人脸图片截取下来进行存储,这个代码是之前的代码改编过来的,可以点击这里看一下之前的博客,人脸的截取部分的学习就可以知道了:
import cv2
import numpy as np
# 1.load xml文件 2.夹在图片 3.haar特征,灰度处理(所有的haar特征基于灰度图的),4.检测人脸 5.绘制标注
# 加载引入xml文件
face_xml = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')
eye_xml = cv2.CascadeClassifier('haarcascade_eye.xml')
img = cv2.imread('face.png')
cv2.imshow('src', img)
# 计算haar特征,但是opencv自带的已经解决,所以只需要转换成灰度图即可
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 检测;cv2中有自带的检测方法
faces = face_xml.detectMultiScale(gray, 1.3, 5)
# 检测图像中的人脸,第一个参数,灰度图片的数据,缩放系数,harr特征需要的比例缩放的操作;目标大小,人脸不能小于5
print('face=', len(faces))
# 绘制人脸,给人脸画宽高
index = 0
for (x, y, w, h) in faces:
cv2.rectangle(img, (x, y), (x+w, y+h), (255, 0, 0), 2)
roi_face = gray[y:y+h, x:x+w]
roi_color = img[y:y+h, x:x+w]
fileName = str(index)+'.jpg'
cv2.imwrite(fileName, roi_color) # 存储的是人脸像
index = index + 1
# 也必须是灰度图
eyes = eye_xml.detectMultiScale(roi_face)
print('eye=', len(eyes))
# for (x2, y2, w2, h2) in eyes:
# cv2.rectangle(img, (x2, y2), (x2+w2, y2+h2), (0, 255, 0), 2)
# 人脸识别之后需要做的是提取处理然后保存在本地进行训练,因为是一系列的样本,所以需要给他们一个下标
cv2.imshow('dst', img)
cv2.waitKey(0)
三、神经网络的搭建
主要是CNN的卷积神经网络,实现某个人脸的识别:
1.完成数据的准备,我们使用的是耶鲁大学的一i个人脸库
2.准备训练数据和训练的标签,完成label的标签的加载
3.搭建cnn网络进行训练
4.检测人脸识别是否可以运用
这里,我们主要是做第二步和第三步的准备
import tensorflow as tf
import numpy as np
import scipy.io as sio
f = open('Data.mat', 'rb') # 加载进来之后是一个字典的形式,所以我们将它存在字典里面
mdict = sio.loadmat(f) # 将当前文件的文件句柄加载进来,这里就会有训练数据和训练标签
# 训练数据的key是fea,value的key是gnd
train_data = mdict['fea']
train_label = mdict['gnd']
# 因为我们用的是网上的耶鲁大学的数据,所以我们需要抽取一部分数据来形成测试数据,所以在这里,我们还需要将其顺序打乱,组成新的训练数据
train_data = np.random.permutation(train_data) # 使得整个数据进行无序排列
train_label = np.random.permutation(train_label)
test_data = train_data[0: 64]
test_label = train_label[0: 64]
# 提取数据的前64个作为测试数据,然后再将训练数据和测试数据进行打乱
np.random.seed(100)
test_data = np.random.permutation(test_data) # 使得整个数据进行无序排列
test_label = np.random.permutation(test_label)
# 第一步数据的准备完成了,接下来就是其他步骤,准备train_label和train_data
# 读取进来之后,图片的大小是64x64的,灰度等级是0-255的,所以我们需要归一化处理
train_data = train_data.reshape(train_data.shape[0], 64, 64, 1).astype(np.flloat32)/255
# 这样处理完之后,训练数据就算归一化成功了
# 在训练进行数字识别的时候,它的数组是Nx10维度的数组,因为有10个数(0-9),所以耶鲁大学的数据里面,有15个人脸,所以标签数据就是15xN了
# 构建标签:
train_label_new = np.zeros((165, 15))
# 新建这个数组的原因是:耶鲁大学的数据库有165张图片,分别描述了15个人,所以这样定义的
# 对每一个维度进行赋值,刚刚开始所有的维度都为0,同理2这个标签表示为:[0,0,1,0,0,0,0,0,0,0],这里是类似的方式进行标签的制作
# 总共165组数据,
for i in range(0, 165):
# j表明当前train_label,这个train_label中的输入数据全部放到第i行,我们首先要根据train_label获取得到当前的这个图片描述的是哪个人
j = int(train_label[i, 0]) - 1 # 标签转换成0-14
train_label_new[i, j] = 1
test_data_input = test_data.reshape(train_data.shape[0], 64, 64, 1).astype(np.flloat32)/255
test_label_input = np.zeros((64, 15))
for i in range(0, 64):
# j表明当前train_label,这个train_label中的输入数据全部放到第i行,我们首先要根据train_label获取得到当前的这个图片描述的是哪个人
j = int(test_label[i, 0]) - 1 # 标签转换成0-14
test_label_input[i, j] = 1
# 接下来就是构建简单的神经网络
# 卷积神经网络,测试训练的检测概率,之前的方式是tf.nn的方法,这里是运用tf.layer,通过这个方法可以直接实现一个人工神经网络的搭建
data_input = tf.placeholder(tf.float32, [None, 64, 64, 1])
label_input = tf.placeholder(tf.float32, [None, 64, 64, 1])
layer1 = tf.layers.conv2d(inputs = data_input, filters=32, kernel_size=2, strides=1, padding='SAME', activation=tf.nn.relu)
layer1_pool = tf.layers.max_pooling2d(layer1, pool_size=2, strides=2) # 池化层,行列均减小一半
layer2 = tf.reshape(layer1_pool, [-1, 32*32*32]) # 池化层作为输入,我们想要实现一个n行的
layer2_relu = tf.layers.dense(layer2, 1024, tf.nn.relu) # 激励层
output = tf.layers.dense(layer2_relu, 15) # 全连接层,维度15,因为是15个人
# 让神经网络跑起来,然后计算预测的概率,交叉商
loss = tf.losses.softmax_cross_entropy(onehot_labels=label_input, logits=output)
train = tf.train.GradientDescentOptimizer(0.01).minimize(loss)
accuracy = tf.metrics.accuracy(labels=tf.arg_max(label_input, axis=1), predictions=tf.argmax(output, axis=1))[1]
# run
init = tf.group(tf.global_variables_initializer(), tf.local_variables_initializer)
with tf.Session() as sess:
sess.run(init)
for i in range(0, 200):
train_data_input = np.array(train_data)
train_label_input = np.array(train_label_new)
sess.run([train, loss], feed_dict={data_input: train_data_input, label_input: train_label_input})
acc = sess.run(accuracy, feed_dict={data_input: test_data_input, label_input: test_label_input})
print('acc:%.2f', accuracy)