【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.pswp.cn/news/455636.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/455636.shtml
英文地址,請注明出處:http://en.pswp.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替…

[轉]Spring事務tx:annotation-driven/

在使用SpringMVC的時候&#xff0c;配置文件中我們經常看到 annotation-driven 這樣的注解&#xff0c;其含義就是支持注解&#xff0c;一般根據前綴 tx、mvc 等也能很直白的理解出來分別的作用。<tx:annotation-driven/> 就是支持事務注解的&#xff08;Transactional&a…

【自動化測試】整理各種測試開發工具!持續更新

收集和整理各種測試工具&#xff0c;自動化測試工具&#xff0c;自動化測試框架&#xff0c;覺得有幫助記得三連一下。歡迎提交各類測試工具到本博客。 通用測試框架 JUnit: 最著名的xUnit類的單元測試框架&#xff0c;但是不僅僅可以做單元測試。TestNG: 更強大的Java測試框架…

python連接sql數據庫_python連接sql server數據庫實現增刪改查

簡述 python連接微軟的sql server數據庫用的第三方模塊叫做pymssql&#xff08;document&#xff1a;http://www.pymssql.org/en/stable/index.html&#xff09;。在官方文檔可以看到&#xff0c;pymssql是基于_mssql模塊做的封裝&#xff0c;是為了遵守python的DBAPI規范接口.…

es5.0 安裝head插件

es5.0的安裝和之前的版本有些區別,我的電腦用plugin install 沒成功, 查了一下資料,說是可以用grunt進行安裝,啟動; 1,先安裝grunt: grunt是一個很方便的構建工具&#xff0c;可以進行打包壓縮、測試、執行等等的工作&#xff0c;5.0里的head插件就是通過grunt啟動的。 npm ins…

Django后臺項目之用戶管理功能開發流程

項目功能開發流程 1 先寫列表頁&#xff08;加載出來數據就行&#xff09; ob User_vip.objects.filter(is_del004001).order_by(-cts)2 寫添加功能 2.1 創建addOrDoadd視圖方法 2.2 添加訪問addOrDoadd的路由 2.3 在index.html頁面吧添加的按鈕的鏈接不全 <a style&…

套接字 資料查閱

(3)套接字(socket) 一個完整的網絡應用程序包括客戶端和服務器兩個部分。網間通信進程需要由兩個進程組成&#xff0c;并且只能用同一種協議。也就是說&#xff0c;不能在通信的一端使用TCP協議&#xff0c;而另一端則用UDP協議。一個完整的網絡通信需要一個五元組來標識…

linux mysql安裝_Linux下安裝mysql服務(超詳細)

Mysql數據庫的安裝對于開發者來說&#xff0c;是我們必然會面對的問題&#xff0c;它的安裝過程其實并不復雜&#xff0c;并且網絡上的安裝教程也非常多&#xff0c;但是對于新手來說&#xff0c;各種不同形式的安裝教程&#xff0c;又給新手們帶來了要選擇哪種方式進行安裝的難…

dash 和 bash 切換

#先看看是用的哪個 shellls -al /bin/sh #如果是dash&#xff0c;切換到bashsudo ln -fs /bin/bash /bin/sh轉載于:https://www.cnblogs.com/abolide/p/6874265.html

Django中使用ajax技術概述

ajax 1.什么是ajax ajax就是在不刷新整個頁面的情況下&#xff0c;去更新局部頁面的內容&#xff08;無刷新技術&#xff09; 2.ajax有什么優點 最大的一點是頁面無刷新&#xff0c;在頁面內與服務器通信&#xff0c;給用戶的體驗非常好。 使用異步方式與服務器通信&#x…

IE、FF腳本兼容性問題

1.window.event IE有這個對象&#xff1b;FF沒有&#xff0c;FF通過參數傳遞 2.獲取事件源 IE&#xff1a;srcElement FF&#xff1a;target 3.添加與去除事件 IE&#xff1a;element.attachEvent("onclick", function(){}) element.detachEvent("onclick"…

ARM MOV和 LDR指令關系

ARM是RISC結構&#xff0c;數據從內存到CPU之間的移動只能通過L/S指令來完成&#xff0c;也就是ldr/str指令。比如想把數據從內存中某處讀取到寄存器中&#xff0c;只能使用ldr比如&#xff1a;ldr r0, 0x12345678就是把0x12345678這個地址中的值存放到r0中。而mov不能干這個活…

day2 操作系統

一.為何要有操作系統 程序員無法把所有的硬件操作細節都了解到&#xff0c;管理這些硬件并且加以優化使用是非常繁瑣的工作&#xff0c;這個繁瑣的工作就是操作系統來干的&#xff0c;有了他&#xff0c;程序員就從這些繁瑣的工作中解脫了出來&#xff0c;只需要考慮自己的應用…

Django之model模型

模型 1.如何安裝pymysql 1.file->settings->Project Interpreter 2.點擊右邊的"" 3.搜索pymysql 4.點擊最下面的"install package" 5.安裝成功會提示"Package "pymysql" install successfully"2.如何在django中配置mysql 1.在…

python安裝不了jupyter_python學習筆記——Windowns下Python3之安裝jupyter

Windowns下Python3之安裝jupyter Jupyter notebook&#xff1a; 一個交互式筆記本&#xff0c;支持運行40多種編程語言。 利用它來寫Python&#xff0c;代碼和運行結果都可以保存下載&#xff0c;十分方便。本文主要以自身的安裝過程為例&#xff0c;結合遇到的問題&#xff0c…

Java文件讀寫操作

http://blog.csdn.net/jiangxinyu/article/details/7885518/ 比較齊全&#xff0c;有多種文件讀寫操作轉載于:https://www.cnblogs.com/maowuyu-xb/p/7238170.html

視頻編碼與封裝方式詳解

1. 編碼方式和封裝格式... 1 2. 視頻編碼標準兩大系統... 2 MPEG-1. 2 MPEG-2. 3 MPEG-3. 3 MPEG-4. 3 ITU-T. 4 WMV. 4 3. 常用視頻編碼方式有Xvid( 4 4. 常見存儲封裝格式... 6 5. 幾種常見的轉換格式設置... 7 6. 無損視頻編碼... 9 1. 編碼方式和封裝格式常見…