【Tensorflow】人脸128个关键点识别基于卷积神经网络实现

引言:

卷积神经网络

  • 卷积神经网络最早是为了解决图像识别的问题,现在也用在时间序列数据和文本数据处理当中,卷积神经网络对于数据特征的提取不用额外进行,在对网络的训练的过程当中,网络会自动提取主要的特征.
  • 卷积神经网络直接用原始图像的全部像素作为输入,但是内部为非全连接结构.因为图像数据在空间上是有组织结构的,每一个像素在空间上和周围的像素是有关系的,和相距很远的像素基本上是没什么联系的,每个神经元只需要接受局部的像素作为输入,再将局部信息汇总就能得到全局信息. 权值共享和池化两个操作使网络模型的参数大幅的减少,提高了模型的训练效率.

卷积神经网络主要特点

  • 权值共享: 在卷积层中可以有多个卷积核,每个卷积核与原始图像进行卷积运算后会映射出一个新的2D图像,新图像的每个像素都来自同一个卷积核.这就是权值共享.
  • 池化: 降采样,对卷积(滤波)后,经过激活函数处理后的图像,保留像素块中灰度值最高的像素点(保留最主要的特征),比如进行 2X2的最大池化,把一个2x2的像素块降为1x1的像素块.

进入内容

首先项目

实现架构和结果图

1.训练模型

train.py

"""
训练模型
"""
from keras.callbacks import TensorBoard, ModelCheckpoint
from generator import get_train_test, create_generator  # 数据切分,创建生成器
from model_framework.frontend import get_model  # 导入模型def train():"""功能:训练模型,并保存模型"""model = get_model((64, 64, 3)) # 获取模型X_train, X_test, y_train, y_test= get_train_test('data/dataset') #   完成数据集切分tbCallBack = TensorBoard( log_dir='./logs')model_checkpoint = ModelCheckpoint(f'trained_model/checkpoint_model.h5',monitor='val_loss',verbose=0,save_weights_only=False,save_best_only=True) # 注:save_weights_only = False,表示保存的由ModelCheckpoint()保存的模型既可以用load_model加载,也可以用load_weights加载model.fit_generator(create_generator( X_train, y_train, 40),steps_per_epoch=50,epochs=30,validation_data=create_generator( X_test,y_test,40),validation_steps=10,callbacks=[tbCallBack, model_checkpoint]) # TODO完成训练模型代码model.save_weights('trained_model/weight.h5') # 保存权重model.save( './trained_model/model.h5')#   完成保存模型文件代码if __name__ == '__main__':train()

 

2.数据处理相关功能


import os
import cv2
import numpy as np
from sklearn.model_selection import train_test_splitdef read_img(path):"""功能:读取图片# 参数:path: 数据集的路径# 返回:res: 不同人的图片。"""res = []for (root, dirs, files) in os.walk(path):if files:tmp = []files = np.random.choice(files, 4)for f in files:img = os.path.join(root, f)image = cv2.imread(img)image = cv2.resize(image, (64, 64),interpolation=cv2.INTER_CUBIC)image = np.array(image, dtype='float32')image /= 255.tmp.append(image)res.append(tmp)return resdef get_paris(path):"""功能:构造用于训练的成对数据# 参数:path: 数据集的路径# 返回:sm1: 一对数据中的第一个对象sm2: 一对数据中的第二个对象y1: 成对数据的标签,相同为1,不同为0."""sm1, sm2, df1, df2 = [], [], [], []res = read_img(path)persons = len(res)for i in range(persons):for j in range(i, persons):p1 = res[i]p2 = res[j]if i == j:for pi in p1:for pj in p2:sm1.append(pi)sm2.append(pj)else:df1.append(p1[0])df2.append(p2[0])df1 = df1[:len(sm1)]df2 = df2[:len(sm2)]y1 = list(np.zeros(len(sm1)))y2 = list(np.ones(len(df1)))sm1.extend(df1)sm2.extend(df2)y1.extend(y2)return sm1, sm2, y1def create_generator(x, y, batch):"""功能:构造数据生成器# 参数:x: 数据y: 标签batch: 数据生成器每次生成数据的个数# 返回:[x1, x2]: 成对数据yb: 数据标签"""while True:index = np.random.choice(len(y), batch) # 每次选择batch个数据索引x1, x2, yb = [], [], []for i in index:x1.append(x[i][0])x2.append(x[i][1])yb.append(y[i])x1 = np.array(x1)x2 = np.array(x2)yield [x1, x2], ybdef get_train_test(path):"""功能:切分数据集# 参数:path: 数据集的路径# 返回:X_train: 用于训练的数据X_test: 用于测试的数据y_train: 用于训练的标签y_test: 用于测试的标签"""im1, im2, y = get_paris(path) # 构造成对数据im = list(zip(im1, im2))X_train, X_test, y_train, y_test = train_test_split(im, y, test_size=0.33)  # 利用sklearn切分数据集return X_train, X_test, y_train, y_test

3.工具包相关内容

"""
工具包:提取特征、图像处理
"""
import cv2
import numpy as np
from model_framework.frontend import get_model,contrastive_loss
from keras.models import Model,load_modelfrom keras.applications.mobilenet import relu6,DepthwiseConv2Ddef get_feature_model(url,mode = 'weight'):"""功能:获取提取特征模型# 参数:url:模型或模型权重的路径mode:'weight'或'model_framework'# 返回:feat_model: 返回提取特征模型"""if mode == 'weight':  # 加载权重model = get_model((64, 64, 3),plot_model_path='data/images/face_net.png')model.load_weights(url)elif mode == 'model': # 加载模型  注:加载模型时,若包含自定义层或自定义对象时,需要使用custom_objects参数。model = load_model(url,custom_objects={'contrastive_loss': contrastive_loss,'relu6': relu6,'DepthwiseConv2D':DepthwiseConv2D})feat_model = Model(inputs=model.get_layer('model_1').get_input_at(0),outputs=model.get_layer('model_1').get_output_at(0))return feat_modeldef process_image(img):"""功能:预处理图像# 返回:image: 处理后的图像"""image = cv2.resize(img, (64, 64),interpolation=cv2.INTER_CUBIC)  # 重新设置图像大小image = np.array(image, dtype='float32') # 将图像格式改为arrayimage /= 255. # 归一化image = np.expand_dims(image, axis=0) # 增加维度return image

4.用到两个模型框架

siamese network 和 MobileNet v2 模型框架的具体使用如下

"""
前端模型,siamese network
功能:该网络使得相似特征距离更近,否则尽可能远。
"""
from .backend import MobileNetv2 # 后端模型,用来提取人脸特征。
import keras.backend as K
from keras.layers import Input, Lambda
from keras.models import Model
from keras.optimizers import Adamdef euclidean_distance(inputs):"""欧氏距离功能:该函数计算两个特征之间的欧氏距离。# 参数:inputs: 两个特征,list类型.# 返回:Output: 欧氏距离,double类型."""u, v = inputsreturn K.sqrt(K.sum((K.square(u - v)), axis=1, keepdims=True))def contrastive_loss(y_true, y_pred):"""对比损失功能:计算对比损失.# 参数:y_true:表示样本是否匹配的标签,y_true = 1 表示匹配,0表示不匹配.整数类型。y_pred:欧氏距离,double类型.# ReturnsOutput:contrastive loss,double类型."""margin = 1. # 阈值return K.mean((1. - y_true) * K.square(y_pred) + y_true * K.square(K.maximum(margin - y_pred, 0.)))def get_model(shape,plot_model_path='data/images/face_net.png'):"""人脸识别网络功能:该网络使得相似特征距离更近,否则尽可能远。# 参数:shape: 输入图像input的形状,彩色图像或灰度图像.# 返回:模型model."""mn = MobileNetv2(shape) # 后端模型,用来提取特征。im1 = Input(shape=shape)im2 = Input(shape=shape)feat1 = mn(im1) # 提取特征,feat1和feat2分别为提取到的特征。feat2 = mn(im2)distance = Lambda(euclidean_distance)([feat1, feat2])# Lambda层,在此处用于欧氏距离的计算,该方式为函数式编程。face_net = Model(inputs=[im1, im2], outputs=distance) # 构造siamese network模型adam = Adam(lr = 0.0012,beta_1=0.9, beta_2=0.999)face_net.compile(optimizer=adam, loss=contrastive_loss) # 编译模型,损失函数为contrastive_lossreturn face_net
"""
MobileNet v2 模型框架
"""
from keras.models import Model
from keras.layers import Input, Conv2D, GlobalAveragePooling2D
from keras.layers import Activation, BatchNormalization, add, Reshape
from keras.regularizers import l2
from keras.layers.advanced_activations import LeakyReLU
from keras.applications.mobilenet import relu6, DepthwiseConv2D
from keras import backend as Kdef _conv_block(inputs, filters, kernel, strides):channel_axis = 1 if K.image_data_format() == 'channels_first' else -1x = Conv2D(filters, kernel, padding='same', strides=strides)(inputs)x = BatchNormalization(axis=channel_axis)(x)return Activation(relu6)(x)def _bottleneck(inputs, filters, kernel, t, s, r=False):channel_axis = 1 if K.image_data_format() == 'channels_first' else -1tchannel = K.int_shape(inputs)[channel_axis] * tx = _conv_block(inputs, tchannel, (1, 1), (1, 1))x = DepthwiseConv2D(kernel, strides=(s, s),depth_multiplier=1, padding='same')(x)x = BatchNormalization(axis=channel_axis)(x)x = Activation(relu6)(x)x = Conv2D(filters, (1, 1), strides=(1, 1), padding='same')(x)x = BatchNormalization(axis=channel_axis)(x)if r:x = add([x, inputs])return xdef _inverted_residual_block(inputs, filters, kernel, t, strides, n):x = _bottleneck(inputs, filters, kernel, t, strides)for i in range(1, n):x = _bottleneck(x, filters, kernel, t, 1, True)return xdef MobileNetv2(input_shape):"""MobileNetv2框架# 参数:input_shape: 输入值的shape# 返回:model_framework:MobileNetv2模型"""inputs = Input(shape=input_shape, name='single_input')x = _conv_block(inputs, 32, (3, 3), strides=(2, 2))x = _inverted_residual_block(x, 64, (3, 3), t=5, strides=2, n=2)x = _inverted_residual_block(x, 128, (3, 3), t=5, strides=2, n=2)x = _inverted_residual_block(x, 256, (3, 3), t=5, strides=1, n=1)x = _conv_block(x, 1280, (1, 1), strides=(1, 1))x = GlobalAveragePooling2D()(x)x = Reshape((1, 1, 1280))(x)x = Conv2D(512, (1, 1), padding='same', kernel_regularizer=l2(5e-4))(x)x = LeakyReLU(alpha=0.1)(x)x = Conv2D(128, (1, 1), padding='same', kernel_regularizer=l2(5e-4))(x)output = Reshape((128,), name='feat_out')(x)model = Model(inputs, output)return model

5.结果输入进行可视化操作

"""
结果可视化
"""
import os
import cv2
import numpy as np
import matplotlib.pyplot as plt
from sklearn.manifold import TSNE
from utils.utils import get_feature_model, process_imagedef plot_reduce_dimension(model):"""Plot reduced dimension result wiht t-SNE.功能:用t-SNE算法对预测结果降维,并可视化显示# 参数:model_framework: Model, 提取特征的模型"""outputs = []n = 5 # 类别paths = 'data/dataset'dirs = np.random.choice(os.listdir(paths), n) # 随机选择n个类别for d in dirs:p = os.path.join(paths, str(d))files = os.listdir(p)if files:for f in files:img = os.path.join(p, f) # 获取图像urlimage = cv2.imread(img) # 读取图像image = process_image(image) # 图像预处理output = model.predict(image)[0] # 显示预测结果outputs.append(output)embedded = TSNE(2).fit_transform(outputs) # 进行数据降维,降成两维colors = ['b', 'g', 'r', 'k', 'y']for i in range(n):m, n = i * 20, (i + 1) * 20plt.scatter(embedded[m: n, 0], embedded[m: n, 1],c=colors[i], alpha=0.5)plt.title('T-SNE')plt.grid(True)plt.show()def compare_distance(model,paths):"""功能:对比人与人之间的不同,即计算欧氏距离并可视化# 参数:model_framework: 特征提取模型"""dists = []outputs = []paths = paths # 预测数据的地址for img in os.listdir(paths):# img = paths + img + '.jpg' # 获取图片路径img = os.path.join(paths,img)image = cv2.imread(img) # 读取图片image = process_image(image) # 图片预处理output = model.predict(image) # 预测结果outputs.append(output)vec1 = outputs[0]for vec2 in outputs:dist = np.linalg.norm(vec1 - vec2) # 计算L2范数,即欧氏距离dists.append(dist)print(dists[1:])plt.bar(range(1, 6), (dists[1:]), color='lightblue')plt.xlabel('Person')plt.ylabel('Euclidean distance')plt.title('Similarity')plt.grid(True)plt.show()if __name__ == '__main__':# model_framework = get_feature_model(url = 'trained_model/weight.h5',mode='weight') # 加载模型model = get_feature_model(url='trained_model/model.h5 ',mode = 'model') #  完成加载模型代码# TODO完成可视化提取的样本特征代码plot_reduce_dimension(model)# TODO完成可视化人脸的相似度compare_distance(model,'./data/images/person')

以上就是本文的全部内容,希望对大家的学习有所帮助。

 

 

https://github.com/Liu0330

 

http://39.106.94.21/article/Github/# 

http://39.106.94.21/article/python0/

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/455636.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

python 爬虫 包_python爬虫学习之路-抓包分析

利用浏览器抓包,是爬虫中的很实用的技能。在爬虫编程之前,我们要对抓取的目标页面有所了解,比如浏览器的这个请求这个页面中间都经历了什么,数据是怎么发送和返回的。 抓包的作用 我把抓包分析的作用简单列一下: 分析请…

帧间EC原理和过程

出错的宏块(图中灰色表示)根据上、下、左、右四个方向相邻宏块的不同分割情况及预测类型进行插值。将最后的结果中进行比较,选取边界像素差值之和最小者为最优的EC方案。其步骤为: 1、判断相邻宏块左上角8*8块的预测模式是否大于R…

Maven依赖的是本地工程还是仓库jar包?

相信大家都碰见过maven配置的依赖或者是jar包或者是工程,在开发的过程当中,我们当然需要引入的是工程,这样查看maven依赖的文件的时候,就能直接查看到源码。 一、本地工程依赖 举个例子,其架构如下所示(以下…

关于django新版本无法使用MySQL数据库的问题

关于django新版本无法使用MySQL数据库的问题 参考这里 稍微记录下Django2.2使用MariaDB和MySQL遇到的坑 现在演示一下整个流程吧 1.创建项目和应用 PS:你也可以使用PyCharm直接创建项目 2.注册应用 先把刚刚创建的应用添加进去 3.配置MySQL或者MariaDB 4.PyMySQL替…

python连接sql数据库_python连接sql server数据库实现增删改查

简述 python连接微软的sql server数据库用的第三方模块叫做pymssql(document:http://www.pymssql.org/en/stable/index.html)。在官方文档可以看到,pymssql是基于_mssql模块做的封装,是为了遵守python的DBAPI规范接口.…

es5.0 安装head插件

es5.0的安装和之前的版本有些区别,我的电脑用plugin install 没成功, 查了一下资料,说是可以用grunt进行安装,启动; 1,先安装grunt: grunt是一个很方便的构建工具,可以进行打包压缩、测试、执行等等的工作,5.0里的head插件就是通过grunt启动的。 npm ins…

套接字 资料查阅

(3)套接字(socket) 一个完整的网络应用程序包括客户端和服务器两个部分。网间通信进程需要由两个进程组成,并且只能用同一种协议。也就是说,不能在通信的一端使用TCP协议,而另一端则用UDP协议。一个完整的网络通信需要一个五元组来标识…

linux mysql安装_Linux下安装mysql服务(超详细)

Mysql数据库的安装对于开发者来说,是我们必然会面对的问题,它的安装过程其实并不复杂,并且网络上的安装教程也非常多,但是对于新手来说,各种不同形式的安装教程,又给新手们带来了要选择哪种方式进行安装的难…

day2 操作系统

一.为何要有操作系统 程序员无法把所有的硬件操作细节都了解到,管理这些硬件并且加以优化使用是非常繁琐的工作,这个繁琐的工作就是操作系统来干的,有了他,程序员就从这些繁琐的工作中解脱了出来,只需要考虑自己的应用…

python安装不了jupyter_python学习笔记——Windowns下Python3之安装jupyter

Windowns下Python3之安装jupyter Jupyter notebook: 一个交互式笔记本,支持运行40多种编程语言。 利用它来写Python,代码和运行结果都可以保存下载,十分方便。本文主要以自身的安装过程为例,结合遇到的问题&#xff0c…

matlab 三维核密度图_Matlab精彩画图示例:三维网状图和三维曲面图

接上篇:Matlab精彩画图示例:绘制图上图这篇介绍两个绘制三维图的命令:mesh - 绘制三维网状图surf - 绘制三维曲面图matlab代码如下:绘制三维图的matlab代码示例程序运行结果如下:mesh(X,Y,Z) draws a wireframe mesh w…

JDBC1

1.jdbc的概述 是sun公司统一提供的一套接口规范,各个数据库生产商提供实现 注册驱动,获得连接,获得执行的SQL语句对象,释放资源 package com.learn.jdbc;import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException;import org.junit.Test;publ…

python程序怎么保存到u盘_python实现usb自动拷贝程序的方法

python实现usb自动拷贝程序的方法 发布时间:2020-06-28 09:07:05 来源:亿速云 阅读:135 作者:清晨 这篇文章将为大家详细讲解有关python实现usb自动拷贝程序的方法,小编觉得挺实用的,因此分享给大家做个参考…

young people can also be a leader

2019独角兽企业重金招聘Python工程师标准>>> The leaders or directors of organizations are often older people. But some people say that young people can also be a leader. To what extent do you agree or disagree? In my view , young people can also …

BZOJ 2004 公交线路(状压DP+矩阵快速幂)

注意到每个路线相邻车站的距离不超过K&#xff0c;也就是说我们可以对连续K个车站的状态进行状压。 然后状压DP一下&#xff0c;用矩阵快速幂加速运算即可。 #include <stdio.h> #include <stdlib.h> #include <string.h> #include <algorithm>#define…

python爬取网易云歌单_详解python selenium 爬取网易云音乐歌单名

目标网站&#xff1a;首先获取第一页的数据&#xff0c;这里关键要切换到iframe里打印一下获取剩下的页数&#xff0c;这里在点击下一页之前需要设置一个延迟&#xff0c;不然会报错。结果&#xff1a;一共37页&#xff0c;爬取完毕后关闭浏览器 完整代码&#xff1a; url htt…

Idea的一些调试技巧及设置todo

程序员的工作内容&#xff0c;除了大部分时间写代码之外&#xff0c;因为有不少的时间是用在调试代码上。甚至说不是在调试代码&#xff0c;就是即将调试代码。 :) 今天我们来谈谈调试代码的一些技巧&#xff0c;在使用IDE提供的debugger时一些快速定位问题的方式。 看到这里的…

Maven:基本使用

为什么80%的码农都做不了架构师&#xff1f;>>> 1.项目管理工具&#xff1a; Maven的repository&#xff0c;说白了就是dependency的仓库&#xff0c;它按照一定的规则将dependency存放起来&#xff0c;以作缓存&#xff0c;如果本机的 repository找不到某个depen…

大数据可视化html模板开源_大数据时代-可视化数据分析平台必不可少

公众号&#xff1a;不安分的猿人一、项目简介DataGear是一款数据管理与可视化分析平台&#xff0c;使用Java语言开发&#xff0c;采用浏览器/服务器架构&#xff0c;支持多种数据库&#xff0c; 主要功能包括数据管理、SQL工作台、数据导入/导出、数据集管理、图表管理、看板管…

【Netty】ChannelHandler和ChannelPipeline

一、前言 前面学习了Netty的ByteBuf&#xff0c;接着学习ChannelHandler和ChannelPipeline。 二、ChannelHandler和ChannelPipeline 2.1 ChannelHandler 在ChannelPipeline中&#xff0c;ChannelHandler可以被链在一起处理用户逻辑。 1. Channel生命周期 Channel接口定义了一个…