ボリュームニューラルネットワークとtensorflowに基づいて実現された顔認識

13594 ワード

まず原文の住所を貼ります.http://tumumu.cn/2017/05/02/deep-learning-face/
以前、ニューラルネットワークを勉強していたとき、面白いデモをたくさん見つけて、顔認識の例を見つけたことがありましたが、当時はまだ読めませんでした.しばらくしてから、上記の例を直して、調整してもいいかどうか試してみることにしました.私のコードと原文には大きな違いはないと思っていたが、何の間違いもないはずだったが、実際に自分が手に入れてから多くの問題を発見した.具体的なプログラムのインストールは、ここではもう説明しません.原文を参考にして、詳しく話してください.次は私のコードを貼ります.元のコードとは大差なく、真ん中のボリューム層を変更しました.自分の実際の操作はやはり多くのことを学んだ.原文に比べて、人の颜を集めることと他の人の颜を処理するコードはあまり変わっていませんが、原文コードの中で画像の明るさとコントラストを修正する部分を除いただけなので、私が収集した画像は同じ明るさと同じコントラストで、ここではこの2つの部分のコードを贴りません.ここでは,訓練部分のコードと最後にモデルを用いたコードを直接貼り付ける.
import tensorflow as tf
import cv2
import numpy as np
import os
import random
import sys
from sklearn.model_selection import train_test_split


my_faces_path = './gray_my_faces'
other_faces_path = './other_faces'

#        64*64
size = 64
imgs = []
labs = []#               
#          ,      ,         
def getPaddingSize(img):
    h,w,_ = img.shape#            
    top,bottom,left,right = (0,0,0,0)
    longest = max(h,w)

    if w < longest:
        tmp = longest - w
        left = tmp // 2
        right = tmp - left

    elif h < longest:
        tmp = longest - h
        top = tmp // 2
        bottom = tmp - top

    else:
        pass
    return top,bottom,left,right

def readData(path,h=size,w=size):
    for filename in os.listdir(path):
        if filename.endswith('.jpg'):
            filename = path + '/' + filename

            img = cv2.imread(filename)

            top,bottom,left,right = getPaddingSize(img)

            #     ,        ,                 
            #        padding   
            img = cv2.copyMakeBorder(img,top,bottom,left,right,cv2.BORDER_CONSTANT,value=[0,0,0])
            img = cv2.resize(img,(h,w))

            #                
            imgs.append(img)
            labs.append(path)

readData(my_faces_path)
readData(other_faces_path)

#             ,        
imgs = np.array(imgs)
labs = np.array([[0,1] if lab == my_faces_path else [1,0] for lab in labs])

#           ,        ,         
train_x,test_x,train_y,test_y = train_test_split(imgs,labs,test_size=0.05,random_state=random.randint(0,100))

#  :       ,    、 、  
train_x = train_x.reshape(train_x.shape[0], size, size,3)
test_x = test_x.reshape(test_x.shape[0], size, size, 3)

#        1  
train_x = train_x.astype('float32') / 255.0
test_x = test_x.astype('float32') / 255.0

#                   ,     
print('train size:%s,test size:%s' % (len(train_x),len(test_x)))

#   ,   100   
batch_size = 100
#      batch
num_batch = (len(train_x)) // batch_size

input = tf.placeholder(tf.float32,[None,size,size,3])
output = tf.placeholder(tf.float32,[None,2])

#   input       
images = tf.reshape(input,[-1,size,size,3])

keep_prob_5 = tf.placeholder(tf.float32)
keep_prob_75 = tf.placeholder(tf.float32)

#            
#     ,          64*64
def cnnlayer():
    conv1 = tf.layers.conv2d(inputs=images,
                            filters=32,
                            kernel_size=[5,5],
                            strides=1,
                            padding='same',
                            activation=tf.nn.relu)#     (64*64*32)
    #     
    pool1 = tf.layers.max_pooling2d(inputs=conv1,
                                    pool_size=[2,2],
                                    strides=2)#     (32*32*32)

    #     
    conv2 = tf.layers.conv2d(inputs=pool1,
                            filters=32,
                            kernel_size=[5,5],
                            strides=1,
                            padding='same',
                            activation=tf.nn.relu)#     (32*32*32)

    #     
    pool2 = tf.layers.max_pooling2d(inputs=conv2,
                                    pool_size=[2,2],
                                    strides=2)#     (16*16*32)

    #     
    conv3 = tf.layers.conv2d(inputs=pool2,
                            filters=32,
                            kernel_size=[5,5],
                            strides=1,
                            padding='same',
                            activation=tf.nn.relu)#(  16*16*32)
    #     
    pool3 = tf.layers.max_pooling2d(inputs=conv3,
                                    pool_size=[2,2],
                                    strides=2)#     (8*8*32)

    #     
    conv4 = tf.layers.conv2d(inputs=pool3,
                            filters=64,
                            kernel_size=[5,5],
                            strides=1,
                            padding='same',
                            activation=tf.nn.relu)#     (  8*8*64)

    # pool3 = tf.layers.max_pooling2d(inputs=conv4,
    #                                 pool_size=[2,2],
    #                                 strides=2)#     (  4*4*64)

#                       ,      
#                
    #   
    flat = tf.reshape(conv4,[-1,8*8*64])

    #      
    dense = tf.layers.dense(inputs=flat,
                            units=4096,
                            activation=tf.nn.relu)

    #drop_out  
    drop_out = tf.layers.dropout(inputs=dense,rate=0.5)

    #   
    logits = tf.layers.dense(drop_out,units=2)
    return logits
    # yield logits


def cnntrain():
    logits = cnnlayer()
    # logits = next(cnnlayer())

    #       
    cross_entropy = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits=logits,labels=output))
    #         GradientDescentOptimizer              AdamOptimizer
    #train_step = tf.train.GradientDescentOptimizer(0.01).minimize(cross_entropy)
    train_step = tf.train.AdamOptimizer(0.01).minimize(cross_entropy)
    #         ,          ,tf.cast(      )
    accuracy = tf.reduce_mean(tf.cast(tf.equal(tf.argmax(logits,1),tf.argmax(output,1)),tf.float32))
    # loss accuracy    tensorboard  
    tf.summary.scalar('loss',cross_entropy)
    tf.summary.scalar('accuracy',accuracy)
    #     Op   Op
    merged_summary_op = tf.summary.merge_all()

    #         
    saver = tf.train.Saver()

    with tf.Session() as sess:
        sess.run(tf.global_variables_initializer())
        # summary  Op          
        summary_writer = tf.summary.FileWriter('./tmp',graph=tf.get_default_graph())

        for n in range(10):
            #   100(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={input: batch_x, output: batch_y})
                summary_writer.add_summary(summary, n * num_batch + i)
                #     
                print(n * num_batch + i, loss)

                if (n * num_batch + i) % 100 == 0:
                    #           
                    acc = accuracy.eval({input: test_x, output: test_y,keep_prob_5:1.0,keep_prob_75:1.0})
                    print(" %f batch,   %f" % (n*num_batch+i, acc))

                    #      0.98      
                    if acc > 0.98 and n > 2:
                        saver.save(sess, './train_faces.model', global_step=n * num_batch + i)
                        sys.exit(0)
        print('accuracy less 0.98, exited!')

cnntrain()







最後にモデルを使用するコードを追加します.
import tensorflow as tf
import cv2
import numpy as np
import os
import random
import sys
from sklearn.model_selection import train_test_split
import dlib


my_faces_path = './my_faces'
other_faces_path = './other_faces'

#                  
size = 64
imgs = []
labs = []#               
def getPaddingSize(img):
    h,w,_ = img.shape#            
    top,bottom,left,right = (0,0,0,0)
    longest = max(h,w)

    if w < longest:
        tmp = longest - w
        left = tmp // 2
        right = tmp - left

    elif h < longest:
        tmp = longest - h
        top = tmp // 2
        bottom = tmp - top

    else:
        pass
    return top,bottom,left,right

def readData(path,h=size,w=size):
    for filename in os.listdir(path):
        if filename.endswith('.jpg'):
            filename = path + '/' + filename

            img = cv2.imread(filename)

            top,bottom,left,right = getPaddingSize(img)

            #     ,        ,                 

            img = cv2.copyMakeBorder(img,top,bottom,left,right,cv2.BORDER_CONSTANT,value=[0,0,0])
            img = cv2.resize(img,(h,w))

            imgs.append(img)
            labs.append(path)#               

readData(my_faces_path)
readData(other_faces_path)

#             
imgs = np.array(imgs)
labs = np.array([[0,1] if lab == my_faces_path else [1,0] for lab in labs])

#           
train_x,test_x,train_y,test_y = train_test_split(imgs,labs,test_size=0.05,random_state=random.randint(0,100))

#  :       ,    、 、  
train_x = train_x.reshape(train_x.shape[0], size, size,3)
test_x = test_x.reshape(test_x.shape[0], size, size, 3)

#        1  ,           
train_x = train_x.astype('float32') / 255.0
test_x = test_x.astype('float32') / 255.0

#              ,     
print('train size:%s,test size:%s' % (len(train_x),len(test_x)))

#   ,   100   
batch_size = 100
num_batch = (len(train_x)) // batch_size#       

input = tf.placeholder(tf.float32,[None,size,size,3])
output = tf.placeholder(tf.float32,[None,2])#     ,true or false
#      tf.reshape  np.reshape
# images = tf.reshape(input,[-1,size,size,3])

keep_prob_5 = tf.placeholder(tf.float32)
keep_prob_75 = tf.placeholder(tf.float32)

#            
#     ,          64*64
def cnnlayer():
    #     
    conv1 = tf.layers.conv2d(inputs=input,
                            filters=32,
                            kernel_size=[5,5],
                            strides=1,
                            padding='same',
                            activation=tf.nn.relu)#(64*64*32)
#     
    pool1 = tf.layers.max_pooling2d(inputs=conv1,
                                    pool_size=[2,2],
                                    strides=2)#(32*32*32)

#     
    conv2 = tf.layers.conv2d(inputs=pool1,
                            filters=32,
                            kernel_size=[5,5],
                            strides=1,
                            padding='same',
                            activation=tf.nn.relu)#(32*32*32)

#     
    pool2 = tf.layers.max_pooling2d(inputs=conv2,
                                    pool_size=[2,2],
                                    strides=2)#(16*16*32)

#     
    conv3 = tf.layers.conv2d(inputs=pool2,
                            filters=32,
                            kernel_size=[5,5],
                            strides=1,
                            padding='same',
                            activation=tf.nn.relu)#(  16*16*32)
#     
    pool3 = tf.layers.max_pooling2d(inputs=conv3,
                                    pool_size=[2,2],
                                    strides=2)#(8*8*32)

#     
    conv4 = tf.layers.conv2d(inputs=pool3,
                             filters=64,
                             kernel_size=[5,5],
                             strides=1,
                             padding='same',
                             activation=tf.nn.relu)#(  8*8*64)
    # pool3 = tf.layers.max_pooling2d(inputs=conv4,
    #                                 pool_size=[2,2],
    #                                 strides=2)#(  4*4*6)

#                       
#     padding same            
#                
#   
    flat = tf.reshape(conv4,[-1,8*8*64])

#      
    dense = tf.layers.dense(inputs=flat,
                            units=4096,
                            activation=tf.nn.relu)

#drop_out,flat    
    drop_out = tf.layers.dropout(inputs=dense,rate=0.2)

#   
    logits = tf.layers.dense(drop_out,units=2)
    return logits
    # yield logits
out = cnnlayer()
# out = next(cnnlayer())
predict = tf.argmax(out,1)
saver = tf.train.Saver()
sess = tf.Session()
saver.restore(sess,tf.train.latest_checkpoint('.'))

def is_my_face(image):
    res = sess.run(predict, feed_dict={input: [image / 255.0]})
    if res[0] == 1:
        return True
    else:
        return False

        #   dlib   frontal_face_detector          


detector = dlib.get_frontal_face_detector()

cam = cv2.VideoCapture(0)

while True:
    _, img = cam.read()
    gray_image = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    dets = detector(gray_image, 1)
    if not len(dets):
        # print('Can`t get face.')
        cv2.imshow('img', img)
        key = cv2.waitKey(30) & 0xff
        if key == 27:
            sys.exit(0)

    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 = cv2.resize(face, (size, size))
        print('Is this my face? %s' % is_my_face(face))

        cv2.rectangle(img, (x2, x1), (y2, y1), (255, 0, 0), 3)
        cv2.imshow('image', img)
        key = cv2.waitKey(30) & 0xff
        if key == 27:
            sys.exit(0)

sess.close()

まとめ:今回の学習を経て、ボリュームニューラルネットワークをより深く理解し、私がコードを修正したとき、真ん中のボリューム層を修正しただけだったが、多くの問題が発生し、自分が書いたコードではなく書いたバグだと感じた.その間は長い間引っかかっていましたが、Stack Overflowの大物の助けで問題を解決しました(質問はしていませんが、前の答えがたくさん助けてくれました).要するに、自分でコードをかき回すのは、見ているだけで学んだことよりずっと多いのではないでしょうか.