import os
import cv2
import numpy as np
import tensorflow as tf
h_pool2_flat = 12288
n_classes = 1
data_home = 'data/imgdata/'
image_to_label = {}
with open('data/label.txt', 'r') as fr:
    lines = fr.readlines()
    for line in lines:
        line = line.strip()
        key, value = line.split(' ')
        image_to_label[key] = value
X_train = []
y_train = []
for jpg in os.listdir(data_home):
    image = cv2.imread(data_home + jpg)
    x = cv2.resize(image, (64, 64))
    X_train.append(x)
    y = image_to_label[jpg]
    y_train.append(y)
X_train = np.array(X_train).reshape((1000, -1))
y_train = np.array(y_train).reshape((-1, 1))
def get_biases(shape):
    '''
    函数的偏置定义。tf.get_variable(name,shape,dtype,initializer)
    参数
        1.name:“biases”
        2.shape:[size],即[输出维度]
        3.dtype:tf.float32
        4.initializer:初始化方式initial,我们选择常量初始化
            语法:tf.constant_initializer(value)
            参数:
            1)value:常数。0.1
    :param shape: 偏置输出维度
    :return: 偏置变量
    '''
    
    initial = tf.constant_initializer(0.1)
    
    biases = tf.get_variable("biases",
                             shape=shape,
                             dtype=tf.float32,
                             initializer=initial)
    return biases
def get_weights(shape):
    '''
    定义参数,卷积核/权值
    语法:tf.get_variable(name,shape,dtype,initializer)
    参数:
        1.name:“weights”
        2.shape:根据不同的变量,输入不同的shape
        3.dtype:tf.float32
        4.initializer:初始化方式initial,我们选择初始化方式为截断的正太分布
            语法:tf.truncated_normal_initializer(stddev,dtype)
            参数:
                1)stedev:要生成的随机值的标准偏差。可设置stedev=0.005
                2) dtype:数据类型。只支持浮点类型 可设置dtype=tf.float32。
    :param shape:参数shape
    :return: 变量参数
    '''
    
    initial = tf.truncated_normal_initializer(stddev=0.005, dtype=tf.float32)
    
    weights = tf.get_variable("weights",
                              shape=shape,
                              dtype=tf.float32,
                              initializer=initial)
    return weights
def add_fc_layer(inputs, insize, outsize, activation_function=None):
    '''
    添加全连接层
    1.定义权值weights
    2.定义偏置bias
    3.完成全连接操作:inputs*weights+bias
    4.如果没有激活函数,返回softmax结果
      如果有激活函数则,返回activation_function结果
    :param inputs: 输入图像
    :param insize: 输入维度
    :param outsize: 输出维度
    :param activation_function: 激活函数
    :return: 计算结果
    '''
    
    weights = get_weights([insize, outsize])
    
    bias = get_biases([outsize])
    
    wx_plus_b = tf.matmul(inputs, weights) + bias
    
    if activation_function == None:
        outputs = tf.nn.softmax(wx_plus_b)
    else:
        outputs = activation_function(wx_plus_b)
    return outputs
def inference(inputs):
    
    with tf.variable_scope("fc1", reuse=tf.AUTO_REUSE) as scope:
        
        fc1 = add_fc_layer(inputs, h_pool2_flat, 128, tf.nn.relu)
    
    with tf.variable_scope("fc2", reuse=tf.AUTO_REUSE) as scope:
        fc2 = add_fc_layer(fc1, 128, 64, tf.nn.tanh)
    
    with tf.variable_scope("fc3", reuse=tf.AUTO_REUSE) as scope:
        fc3 = add_fc_layer(fc2, 64, 32, tf.nn.sigmoid)
        
        fc3_drop = tf.nn.dropout(fc3, 0.5)
    
    with tf.variable_scope("fc4", reuse=tf.AUTO_REUSE) as scope:
        fc4 = add_fc_layer(fc3_drop, 32, n_classes, tf.nn.relu)
    return fc4
x_pl = tf.placeholder(tf.float32)
y_pl = tf.placeholder(tf.float32)
y_pred = inference(x_pl)
k = (y_train - y_pred)
loss = tf.reduce_mean(tf.square(k))
optimizer = tf.train.AdamOptimizer(learning_rate=0.01)
train_op = optimizer.minimize(loss)
saver = tf.train.Saver()
with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())
    for epoch in range(150000):
        _, train_loss = sess.run([train_op, loss], feed_dict={x_pl: X_train, y_pl: y_train})
        if epoch % 1000 == 0:
            print('epoch:{}, train_losses:{}'.format(epoch, train_loss))
    saver.save(sess, "model/model.ckpt", global_step=epoch)
    print('epoch:{}, save model'.format(epoch))