基於卷積神經網路的人臉識別專案_使用Tensorflow-gpu+dilib+sklearn

31415926535x發表於2019-06-11

https://www.cnblogs.com/31415926535x/p/11001669.html

基於卷積神經網路的人臉識別專案_使用Tensorflow-gpu+dilib+sklearn

概述

學期末了啊,,,最後這個人臉識別的專案弄完了,,有很多的不足,,很多東西都是隻知道怎麼用,但是不知道其背後的邏輯,,感覺自己學習東西對於那些潛意識優先順序不高的就放棄了,,,emmm

這篇文章主要是大致介紹一下我們最後弄出來的人臉識別專案的成果吧,,整個專案放到了我的github,,可以直接下載執行的,,不過這也只是一個我們的思路,,這塊東西還是多閱讀別人的專案程式碼,,然後自己寫一下好些,,根據自己的需求嘗試自己寫程式碼,實在不行再看別人的思路,,才能提升自己的思維吧,,,

專案思路

拋開那些花裡胡哨的東西,人臉識別的大致流程只有三個: 人臉資料的錄入、構建卷積神經網路並訓練模型、識別

不過這前要配置好環境,,我用的Anaconda來配置的整體環境,,,可以看我的這篇部落格 ,,(到能成功驗證環境即可

具體的執行流程:

  • 啟用建立的anaconda環境
  • 執行初始化模組(可有可無) python init.py
  • 執行錄入人臉模組,此時會提示輸入姓名,然後錄製視訊,按q結束(20幾喵即可) python getFaceByCamera.py
  • 執行訓練模組,python tensorflow_face.py
  • 等待,,結束後會列印準確度,,
  • 執行識別模組,python tensorflow_face.py ,,,沒錯還是這個,,第二次執行會呼叫識別模組的,,,

人臉資料的錄入

這部分的程式碼在這裡

這部分我們的大致思路是:

  • 錄入待錄入者的姓名
  • 錄製一段視訊
  • 利用dlib人臉檢測器以及opencv對圖片的操作來裁剪200張相片,,當然也可以使用opencv的人臉檢測器,,,不足應該就是準確率不怎麼高吧,,但是快些,,,
  • 迴圈錄入所有人的資訊

這一部分的程式碼:

getFaceByCamera.py

import cv2
import os
import dlib
import sys
import random
import shutil

 
def make_video(name):
    # 錄製視訊
    #shutil.rmtree(name)
    """使用opencv錄影"""
    cap = cv2.VideoCapture(0)  # 預設的攝像頭
    # 指定視訊程式碼
    fourcc = cv2.VideoWriter_fourcc(*"DIVX")
    out = cv2.VideoWriter('233.avi', fourcc, 20.0, (640,480))   # 設定錄製的視訊的格式
    while(cap.isOpened()):
        ret, frame = cap.read()
        if ret:
            out.write(frame)
            #
            cv2.imshow('frame',frame)
            # 等待按鍵q操作關閉攝像頭
            if cv2.waitKey(1) & 0xFF == ord('q'):
                break
        else:
            break
    cap.release()                   # 釋放攝像頭資源
    out.release()                   # 釋放檔案資源
    cv2.destroyAllWindows()         # 關閉拍攝視窗




# 改變圖片的亮度與對比度
def relight(img, light=1, bias=0):
    w = img.shape[1]
    h = img.shape[0]
    #image = []
    for i in range(0,w):
        for j in range(0,h):
            for c in range(3):
                tmp = int(img[j,i,c]*light + bias)
                if tmp > 255:
                    tmp = 255
                elif tmp < 0:
                    tmp = 0
                img[j,i,c] = tmp
    return img

def getDataByDlib(name):
    # 利用dlib來實現
    output_dir = name       # 使用錄入的名字作為資料夾的名字
    size = 64               # 相片的大小為64*64

    if not os.path.exists(output_dir):      # 沒有資料夾是主動建立一個
        os.makedirs(output_dir)
    #使用dlib自帶的frontal_face_detector作為我們的特徵提取器
    detector = dlib.get_frontal_face_detector()
    # 開啟攝像頭 引數為輸入流,可以為攝像頭或視訊檔案
    #camera = cv2.VideoCapture(0)
    camera = cv2.VideoCapture("233.avi")    # 相片來自上一步拍攝的視訊

    index = 1
    while True:
        if (index <= 200):                  # 每一段視訊只取200張
            print('Being processed picture %s' % index) # 顯示處理的過程
            # 從攝像頭讀取照片
            success, img = camera.read()    # 從視訊流中讀取照片
            # 轉為灰度圖片
            gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
            # 使用detector進行人臉檢測
            dets = detector(gray_img, 1)

            if success == False:
                break

            for i, d in enumerate(dets):
                x1 = d.top() if d.top() > 0 else 0
                y1 = d.bottom() if d.bottom() > 0 else 0
                x2 = d.left() if d.left() > 0 else 0
                y2 = d.right() if d.right() > 0 else 0

                face = img[x1:y1,x2:y2]
                # 調整圖片的對比度與亮度, 對比度與亮度值都取隨機數,這樣能增加樣本的多樣性
                face = relight(face, random.uniform(0.5, 1.5), random.randint(-50, 50))
                # 裁剪出人臉相片,大小為64*64
                face = cv2.resize(face, (size,size))    
                # 顯示最後裁剪出的人臉相片
                cv2.imshow('image', face)
                # 儲存到檔案下,檔名為1 - 200.jpg
                cv2.imwrite(output_dir+'/'+str(index)+'.jpg', face)

                index += 1
            key = cv2.waitKey(30) & 0xff
            if key == 27:
                break
        else:
            print('Finished!')
            break
    # 刪除視訊
    shutil.rmtree('./233.avi')



def getDataByOpencv2():
    # 利用opencv來實現
    output_dir = './my_faces'
    size = 64
    if not os.path.exists(output_dir):
        os.makedirs(output_dir)                                 
    # 獲取分類器
    haar = cv2.CascadeClassifier(r'G:\DIP\Anaconda3\envs\test1\Library\etc\haarcascades\haarcascade_frontalface_default.xml')

    # 開啟攝像頭 引數為輸入流,可以為攝像頭或視訊檔案
    camera = cv2.VideoCapture("233.avi")

    n = 1
    while 1:
        if (n <= 10000):
            print('It`s processing %s image.' % n)
            # 讀幀
            success, img = camera.read()

            gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
            faces = haar.detectMultiScale(gray_img, 1.3, 5)
            for f_x, f_y, f_w, f_h in faces:
                face = img[f_y:f_y+f_h, f_x:f_x+f_w]
                face = cv2.resize(face, (64,64))
                '''
                if n % 3 == 1:
                    face = relight(face, 1, 50)
                elif n % 3 == 2:
                    face = relight(face, 0.5, 0)
                '''
                face = relight(face, random.uniform(0.5, 1.5), random.randint(-50, 50))
                cv2.imshow('img', face)
                cv2.imwrite(output_dir+'/'+str(n)+'.jpg', face)
                n+=1
            key = cv2.waitKey(30) & 0xff
            if key == 27:
                break
        else:
            break

if __name__ == '__main__':
    name = input('please input yourename: ')        # 獲取錄入者的名字
    name = os.path.join('./image/trainfaces', name) # 生成儲存的檔案路徑名
    make_video(name)                                # 拍攝視訊
    getDataByDlib(name)                             # 利用dlib處理裁剪人臉原始相片

構建卷積神經網路,然後訓練模型

這一部分大概就是做人臉識別的主要目的了吧,,,

構建卷積神經網路

這一部分幾乎網上寫的程式碼的框架都是差不多的,,,所以只要理解每一層是什麼意思,,怎麼用就行了,,當然可以繼續深究下去,,理解每一層為什麼這麼做,,這麼做的方法是什麼等等,,

我們之前在這一部分投入的精力也最多,,出現的問題也是很多的,,其中我感覺最印象深刻的就是層數的疊加和那個神奇的 loss=0.69.....

層數的疊加就是說大部分的程式碼都是做的3層的神經網路,,但是很少有做多層的,,當時找了很多的資料才一點一點的大致會算怎麼計算下一層

關於那一個神奇的 loss=0.69 ,,貌似不同的網路、需求下可能不會出現這種情況,,,但是如果出現不管比怎麼調參出來的loss都保持在0.69附近的話,,可以試著查一下這一個問題,,我們最後的解決方法是再新增一層 batch nomalization層 ,,具體幹什麼的網上有很多講解的,,,加了它就可以使loss快速收斂,,,

訓練模型

這一部分的框架都是差不多的,,變化可能有引數的變化,,優化器的不同等等

程式碼:

#!/usr/bin/python
#coding=utf-8
''' face detect convolution'''
# pylint: disable=invalid-name
import os
import sys
import logging as log
import matplotlib.pyplot as plt
import common
import numpy as np
from tensorflow.examples.tutorials.mnist import input_data
import tensorflow as tf
import cv2
from sklearn.model_selection import train_test_split
import random

SIZE = 64

x = tf.placeholder(tf.float32, [None, SIZE, SIZE, 3])
y_ = tf.placeholder(tf.float32, [None, None])
keep_prob_5 = tf.placeholder(tf.float32)
keep_prob_75 = tf.placeholder(tf.float32)


def weightVariable(shape):
    ''' build weight variable'''
    init = tf.random_normal(shape, stddev=0.01)
    #init = tf.truncated_normal(shape, stddev=0.01)
    return tf.Variable(init)

def biasVariable(shape):
    ''' build bias variable'''
    init = tf.random_normal(shape)
    #init = tf.truncated_normal(shape, stddev=0.01)
    return tf.Variable(init)

def conv2d(x, W):
    ''' conv2d by 1, 1, 1, 1'''
    return tf.nn.conv2d(x, W, strides=[1, 1, 1, 1], padding='SAME')

def maxPool(x):
    ''' max pooling'''
    return tf.nn.max_pool(x, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='SAME')

def dropout(x, keep):
    ''' drop out'''
    return tf.nn.dropout(x, keep)

def batch_norm_layer(value,is_training=False,name='batch_norm'):
    '''
    批量歸一化  返回批量歸一化的結果
    
    args:
        value:代表輸入,第一個維度為batch_size
        is_training:當它為True,代表是訓練過程,這時會不斷更新樣本集的均值與方差。當測試時,要設定成False,這樣就會使用訓練樣本集的均值和方差。
              預設測試模式
        name:名稱。
    '''
    if is_training is True:
        #訓練模式 使用指數加權函式不斷更新均值和方差
        return tf.contrib.layers.batch_norm(inputs=value,decay=0.9,updates_collections=None,is_training = True)
    else:
        #測試模式 不更新均值和方差,直接使用
        return tf.contrib.layers.batch_norm(inputs=value,decay=0.9,updates_collections=None,is_training = False)


def cnnLayer(classnum, isTrue):
    ''' create cnn layer'''
    # 第一層
    W1 = weightVariable([3, 3, 3, 32]) # 卷積核大小(3,3), 輸入通道(3), 輸出通道(32)
    b1 = biasVariable([32])
    conv1 = tf.nn.relu(batch_norm_layer(conv2d(x, W1) + b1, isTrue))
    pool1 = maxPool(conv1)
    # 減少過擬合,隨機讓某些權重不更新
    drop1 = dropout(pool1, keep_prob_5) # 32 * 32 * 32 多個輸入channel 被filter內積掉了

    # 第二層
    W2 = weightVariable([3, 3, 32, 64])
    b2 = biasVariable([64])
    conv2 = tf.nn.relu(batch_norm_layer(conv2d(drop1, W2) + b2, isTrue))
    pool2 = maxPool(conv2)
    drop2 = dropout(pool2, keep_prob_5) # 64 * 16 * 16

    # 第三層
    W3 = weightVariable([3, 3, 64, 64])
    b3 = biasVariable([64])
    conv3 = tf.nn.relu(conv2d(drop2, W3) + b3)
    pool3 = maxPool(conv3)
    drop3 = dropout(pool3, keep_prob_5) # 64 * 8 * 8
        
    # 全連線層
    Wf = weightVariable([8*8*64,512])
    bf = biasVariable([512])
    drop3_flat = tf.reshape(drop3, [-1, 8*8*64])
    dense = tf.nn.relu(tf.matmul(drop3_flat, Wf) + bf)
    dropf = dropout(dense, keep_prob_75)

    # 輸出層
    Wout = weightVariable([512, classnum])
    bout = weightVariable([classnum])
    #out = tf.matmul(dropf, Wout) + bout
    out = tf.add(tf.matmul(dropf, Wout), bout)
    return out

    # # 第三層
    # W3 = weightVariable([3, 3, 64, 128])
    # b3 = biasVariable([128])
    # conv3 = tf.nn.relu(batch_norm_layer(conv2d(drop2, W3) + b3, True))
    # pool3 = maxPool(conv3)
    # drop3 = dropout(pool3, keep_prob_5) # 128 * 8 * 8

    # # 第四層
    # W4 = weightVariable([3, 3, 128, 512])
    # b4 = biasVariable([512])
    # conv4 = tf.nn.relu(batch_norm_layer(conv2d(drop3, W4) + b4, True))
    # pool4 = maxPool(conv4)
    # drop4 = dropout(pool4, keep_prob_5) # 512 * 4 * 4

    # # 第五層
    # W5 = weightVariable([3, 3, 512, 1024])
    # b5 = biasVariable([1024])
    # conv5 = tf.nn.relu(batch_norm_layer(conv2d(drop4, W5) + b5, True))
    # pool5 = maxPool(conv5)
    # drop5 = dropout(pool5, keep_prob_5) # 1024 * 2 * 2

    # # 第六層
    # W6 = weightVariable([3, 3, 1024, 1024])
    # b6 = biasVariable([1024])
    # conv6 = tf.nn.relu(conv2d(drop5, W6) + b6)
    # pool6 = maxPool(conv6)
    # drop6 = dropout(pool6, keep_prob_5) # 2048 * 1 * 1




    # # 全連線層
    # Wf = weightVariable([1*1*1024, 2048])
    # bf = biasVariable([2048])
    # drop3_flat = tf.reshape(drop6, [-1, 1*1*1024])
    # dense = tf.nn.relu(tf.matmul(drop3_flat, Wf) + bf)
    # # dense = tf.nn.relu(tf.matmul(max_pool22_flat, Wf) + bf)
    # dropf = dropout(dense, keep_prob_75)

   

    # # 輸出層
    # Wout = weightVariable([2048, classnum])
    # bout = weightVariable([classnum])
    # #out = tf.matmul(dropf, Wout) + bout
    # out = tf.add(tf.matmul(dropf, Wout), bout)
    # #return out



def train(train_x, train_y, tfsavepath):
    ''' train'''
    ##### log.debug('train')

    # 隨機劃分測試集與訓練集
    train_x,test_x,train_y,test_y = train_test_split(train_x, train_y, test_size=0.05, random_state=random.randint(0,100))

    # 得到卷積結果
    out = cnnLayer(train_y.shape[1],True)

    # 引數:圖片資料的總數,圖片的高、寬、通道
    train_x = train_x.reshape(train_x.shape[0], SIZE, SIZE, 3)
    test_x = test_x.reshape(test_x.shape[0], SIZE, SIZE, 3)
    
    print('train size:%s, test size:%s' % (len(train_x), len(test_x)))
    sys.stdout.flush()

    # 圖片塊,每次取32張圖片
    batch_size = 32
    num_batch = len(train_x) // batch_size  

    # 交叉熵
    cross_entropy = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits=out, labels=y_))

    # Adam優化器,學習速率:0.001
    train_step = tf.train.AdamOptimizer(0.001).minimize(cross_entropy)
    # train_step = tf.train.AdadeltaOptimizer(0.001).minimize(cross_entropy)

    # 比較標籤是否相等,再求的所有數的平均值,tf.cast(強制轉換型別)
    # 準確率計算公式
    accuracy = tf.reduce_mean(tf.cast(tf.equal(tf.argmax(out, 1), tf.argmax(y_, 1)), tf.float32))



    # 將loss與accuracy儲存以供tensorboard使用
    tf.summary.scalar('loss', cross_entropy)
    tf.summary.scalar('accuracy', accuracy)
    merged_summary_op = tf.summary.merge_all()

    # 資料儲存器的初始化
    saver = tf.train.Saver()

    with tf.Session() as sess:

        # tensorflow初始化
        sess.run(tf.global_variables_initializer())
        # tensorboard資料儲存
        summary_writer = tf.summary.FileWriter('./tmp', graph=tf.get_default_graph())

        # 迭代80次
        for n in range(80):
            # 每次取32(batch_size)張圖片
            for i in range(num_batch):

                # 訓練集、測試集分塊
                batch_x = train_x[i*batch_size : (i+1)*batch_size]
                batch_y = train_y[i*batch_size : (i+1)*batch_size]
                # 開始訓練資料,同時訓練三個變數,返回三個資料
                _,loss,summary = sess.run([train_step, cross_entropy, merged_summary_op],
                                                feed_dict={x:batch_x,y_:batch_y, keep_prob_5:0.5,keep_prob_75:0.75})

                # tensorboard記錄資料    
                summary_writer.add_summary(summary, n*num_batch+i)

                
                # 列印損失
                print(n*num_batch+i, loss)
                sys.stdout.flush()

        #         if (n*num_batch+i) % batch_size == 0:
        #             # 獲取測試資料的準確率
        #             acc = accuracy.eval({x:test_x, y_:test_y, keep_prob_5:1.0, keep_prob_75:1.0})
        #             print(n*num_batch+i, acc, '--', n)
                    
        #             accc = acc

        #             # 準確率大於0.98時儲存並退出
        #             if acc > 0.95 and n > 2:
        #                 # saver.save(sess, './train_faces.model', global_step=n*num_batch+i)
        #                 saver.save(sess, tfsavepath)
        #                 # saver.save(sess, tfsavepath)
        #                 sys.exit(0)
        # # saver.save(sess, './train_faces.model', global_step=n*num_batch+i)
        # # saver.save(sess, tfsavepath)
        # print('accuracy less 0.98, exited!')   

        # 準確率計算表示式
        acc = accuracy.eval({x:test_x, y_:test_y, keep_prob_5:1.0, keep_prob_75:1.0})
        print('after 80 times run: accuracy is ', acc)
        sys.stdout.flush()

        # 模型儲存
        saver.save(sess, tfsavepath) 

if __name__ == '__main__':
    pass

識別

這部分就是將訓練好的模型載入,,然後實時的獲取每一張相片處理等等,,,

tensorflow_face.py 這部分程式碼第一次執行會給每一個人建立一個標籤,,獲得標籤集,,然後和訓練集一同訓練,,,而第二次執行就是識別,,,

import os
import logging as log
import matplotlib.pyplot as plt
import common
import numpy as np
from tensorflow.examples.tutorials.mnist import input_data
import tensorflow as tf
import cv2
# import convert as myconv
import tensorflow_face_conv as myconv
import dlib
import random
from sklearn.model_selection import train_test_split
import time

import sys


# rm
import shutil

def createdir(*args):       # 建立一個資料夾
    ''' create dir'''
    for item in args:
        if not os.path.exists(item):
            os.makedirs(item)

IMGSIZE = 64
SIZE = 64

rootpath = 'G:\\DIP\\mine'

def getpaddingSize(shape):  # 將相片兩側填充為正方形
    ''' get size to make image to be a square rect '''
    h, w = shape
    longest = max(h, w)
    result = (np.array([longest]*4, int) - np.array([h, h, w, w], int)) // 2
    return result.tolist()

def dealwithimage(img, h=64, w=64): # 裁剪出人臉的圖片
    ''' dealwithimage '''
    #img = cv2.imread(imgpath)
    top, bottom, left, right = getpaddingSize(img.shape[0:2])
    img = cv2.copyMakeBorder(img, top, bottom, left, right, cv2.BORDER_CONSTANT, value=[0, 0, 0])
    img = cv2.resize(img, (h, w))
    return img

def relight(imgsrc, alpha=1, bias=0):   # 更改圖片為二值圖
    '''relight'''
    imgsrc = imgsrc.astype(float)
    imgsrc = imgsrc * alpha + bias
    imgsrc[imgsrc < 0] = 0
    imgsrc[imgsrc > 255] = 255
    imgsrc = imgsrc.astype(np.uint8)
    return imgsrc

def getfilesinpath(filedir):            # 得到一個資料夾下的所有檔案
    ''' get all file from file directory'''
    for (path, dirnames, filenames) in os.walk(filedir):
        for filename in filenames:
            if filename.endswith('.jpg'):
                yield os.path.join(path, filename)
        for diritem in dirnames:
            getfilesinpath(os.path.join(path, diritem)) # 遞迴呼叫得到改資料夾下的檔案


def readimage(pairpathlabel):           # 得到一個資料夾下的照片檔名和標記labels, 返回一個列表
    '''read image to list'''
    imgs = []
    labels = []
    for filepath, label in pairpathlabel:
        for fileitem in getfilesinpath(filepath):
            img = cv2.imread(fileitem)
            imgs.append(img)
            labels.append(label)
    return np.array(imgs), np.array(labels)

def onehot(numlist):                    # 用於得到一個人的標籤
    ''' get one hot return host matrix is len * max+1 demensions'''
    b = np.zeros([len(numlist), max(numlist)+1])
    b[np.arange(len(numlist)), numlist] = 1
    return b.tolist()

def getfileandlabel(filedir):           # 用字典儲存一個人名的照片和對應的labels
    ''' get path and host paire and class index to name'''
    dictdir = dict([[name, os.path.join(filedir, name)] \
                    for name in os.listdir(filedir) if os.path.isdir(os.path.join(filedir, name))])
                    #for (path, dirnames, _) in os.walk(filedir) for dirname in dirnames])

    dirnamelist, dirpathlist = dictdir.keys(), dictdir.values()

    indexlist = list(range(len(dirnamelist)))

    return list(zip(dirpathlist, onehot(indexlist))), dict(zip(indexlist, dirnamelist))

def main(_):
    ''' main '''
    '''
    
    人臉識別專案主main函式
    
    + 在第一次執行該檔案時,會將上一次拍照儲存的多個人的照片資料進行處理,卷積、訓練等得到一個適合的模型
    + 在第二次執行該檔案時,會開啟攝像頭獲取一個照片,然後根據上一步得到的模型處理後分類(識別)出照片上出現的人臉是之前錄入的所有人中哪一個
    + 目前無法判斷其他未錄入人的人臉,即others

    '''
    #shutil.rmtree('./checkpoint')
    savepath = './checkpoint/face.ckpt'     # 記錄下模型的索引路徑
    isneedtrain = False                     # 不存在時認為時第一次執行,即進行卷積訓練
    if os.path.exists(savepath+'.meta') is False:
        isneedtrain = True


    # 根據錄入儲存的照片得到一個label和字典的路徑的列表
    pathlabelpair, indextoname = getfileandlabel(rootpath + '\\image\\trainfaces')
    
    print(indextoname)
    sys.stdout.flush()
    print(pathlabelpair)
    sys.stdout.flush()

    # 得到訓練集、測試集的照片和labels的列表
    train_x, train_y = readimage(pathlabelpair)
    # 將資料集歸一化 ???
    train_x = train_x.astype(np.float32) / 255.0



    #### log.debug('len of train_x : %s', train_x.shape) 



    if isneedtrain:
        # first generate all face
        
        # 呼叫另一檔案進行卷積訓練模型
        myconv.train(train_x, train_y, savepath)

       #### # log.debug('training is over, please run again')
    else:
        # second recognize faces 
        # 呼叫下面的函式進行實時識別

        testfromcamera(train_x, train_y, savepath)
        #print(np.column_stack((out, argmax)))




def testfromcamera(train_x, train_y, chkpoint):

    # 開啟預設攝像頭
    camera = cv2.VideoCapture(0)
    #haar = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')
    pathlabelpair, indextoname = getfileandlabel(rootpath + '\\image\\trainfaces')

    # 得到預測值
    output = myconv.cnnLayer(len(pathlabelpair),False)

    predict = output
    
    # 得到dlib的人臉檢測器
    detector = dlib.get_frontal_face_detector()

    # 載入模型
    saver = tf.train.Saver()

    with tf.Session() as sess:
        #sess.run(tf.global_variables_initializer())
        saver.restore(sess, chkpoint)

        n = 1
        while 1:
            if (n <= 20000):
                print('It`s processing %s image.' % n)
                sys.stdout.flush()

                # 間隔0.2s
                time.sleep(0.2) 

                # 讀幀
                success, img = camera.read()
                # 得到灰度圖
                gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

                # 使用detector進行人臉檢測
                faces = detector(gray_img, 1)
                #faces = haar.detectMultiScale(gray_img, 1.3, 5)
                for i, d in enumerate(faces):
                    x1 = d.top() if d.top() > 0 else 0
                    y1 = d.bottom() if d.bottom() > 0 else 0
                    x2 = d.left() if d.left() > 0 else 0
                    y2 = d.right() if d.right() > 0 else 0
                
                    face = img[x1:y1,x2:y2]

                    face = cv2.resize(face, (IMGSIZE, IMGSIZE))
                    #could deal with face to train
                    test_x = np.array([face])
                    test_x = test_x.astype(np.float32) / 255.0
                    
                    res = sess.run([predict, tf.argmax(output, 1)],\
                                   feed_dict={myconv.x: test_x,\
                                   myconv.keep_prob_5:1.0, myconv.keep_prob_75: 1.0})
                    print(res, indextoname[res[1][0]], res[0][0][res[1][0]])
                    sys.stdout.flush()
                    
                    # 得到一組隨機的顏色值
                    r = random.randint(0, 255)
                    g = random.randint(0, 255)
                    b = random.randint(0, 255)

                    # 繪製檢測到的人臉的方框
                    cv2.rectangle(img, (x2,x1),(y2,y1), (r, g, b),3)
                    
                    # if res[0][0][res[1][0]] >= 500:
                    #     cv2.putText(img, 'others', (x1, y1 + 50), cv2.FONT_HERSHEY_SIMPLEX, 1, (col, col, col), 2)  #顯示名字
                    # else:        
                    #     cv2.putText(img, indextoname[res[1][0]], (x1, y1 - 40), cv2.FONT_HERSHEY_SIMPLEX, 1, (col, col, col), 2)  #顯示名字
                    cv2.putText(img, indextoname[res[1][0]], (x2 + 25, y1 + 40), cv2.FONT_HERSHEY_SIMPLEX, 1, (r, g, b), 2)  #顯示名字
                    
                    n+=1
                    cv2.imshow('img', img)
                key = cv2.waitKey(30) & 0xff
                if key == 27:
                    break
            else:
                break           
    camera.release()
    cv2.destroyAllWindows()

if __name__ == '__main__':
    # first generate all face
    main(0)
    #onehot([1, 3, 9])
    #print(getfileandlabel('./image/trainimages'))
    #generateface([['./image/trainimages', './image/trainfaces']])

總結

最後的模型的準確度還行,,但是不能識別未錄入者,,它會認為是與已錄入者最接近的人,,,

acc:

基於卷積神經網路的人臉識別專案_使用Tensorflow-gpu+dilib+sklearn

loss:

基於卷積神經網路的人臉識別專案_使用Tensorflow-gpu+dilib+sklearn

這個資料是通過tensorboard生成的,,

專案裡還有一個簡單的gui的實現,,因為沒有時間了,,所有沒有好好的優化一下,,,

(end 困。。。。)

相關文章