比赛项目为一个基于神经网络的医疗垃圾分类垃圾桶
博主负责其中的图像处理/神经网络的搭建和训练以及通过GPIO口收发控制指令的部分
PerWork.py
'''
PreWork.py
功能:实现对指定大小的生成图片进行sample与label分类制作
获得神经网络输入的get_files文件,同时为了方便网络的训练,输入数据进行batch处理。
'''
import os
import numpy as np
from PIL import Image
import tensorflow as tf
import matplotlib.pyplot as plt
from numpy import *
kou_zhao = []
label_kou_zhao = []
mian_qian = []
label_mian_qian = []
yao_ping = []
label_yao_ping = []
zhu_she_qi = []
label_zhu_she_qi = []
# cwd= r'D:\anaconda\vscode-python\pic\\'
# 将image和label转为list格式数据,因为后边用到的的一些tensorflow函数接收的是list格式数据
def get_file(file_dir):
# step1:获取路径下所有的图片路径名,存放到
# 对应的列表中,同时贴上标签,存放到label列表中。
# os.listdir()方法用于返回指定的文件夹包含的文件或文件夹的名字的列表
for file in os.listdir(file_dir + '/kou_zhao'):
# append()方法用于在列表末尾添加新的对象。
kou_zhao.append(file_dir + '/kou_zhao' + '/' + file)
label_kou_zhao.append(0)
for file in os.listdir(file_dir + '/mian_qian'):
mian_qian.append(file_dir + '/mian_qian' + '/' + file)
label_mian_qian.append(1)
for file in os.listdir(file_dir + '/yao_ping'):
yao_ping.append(file_dir + '/yao_ping' + '/' + file)
label_yao_ping.append(2)
for file in os.listdir(file_dir + '/zhu_she_qi'):
zhu_she_qi.append(file_dir + '/zhu_she_qi' + '/' + file)
label_zhu_she_qi.append(3)
'''
for file in os.listdir(file_dir + '/sadness'):
sadness.append(file_dir + '/sadness' + '/' + file)
label_sadness.append(4)
for file in os.listdir(file_dir + '/surprised'):
surprised.append(file_dir + '/surprised' + '/' + file)
label_surprised.append(5)
'''
# 打印出提取图片的情况,检测是否正确提取
print("There are %d 口罩\nThere are %d 棉签\nThere are %d 药瓶\nThere are %d 注射器\n" %(len(kou_zhao), len(yao_ping), len(mian_qian),len(zhu_she_qi)))
# print("There are %d 注射器\n" %(len(zhu_she_qi)))
'''print结果 :
There are 20 口罩
There are 20 棉签
There are 20 药瓶
There are 20 注射器
'''
# step2:对生成的图片路径和标签List做打乱处理把所有的合起来组成一个list(img和lab)
# 合并数据numpy.hstack(tup)
# tup可以是python中的元组(tuple)、列表(list),或者numpy中数组(array),函数作用是将tup在水平方向上(按列顺序)合并
image_list = np.hstack((kou_zhao, mian_qian, yao_ping, zhu_she_qi))
label_list = np.hstack((label_kou_zhao, label_mian_qian, label_yao_ping, label_zhu_she_qi))
# 利用shuffle,转置、随机打乱
temp = np.array([image_list, label_list]) # 转换成2维矩阵
temp = temp.transpose() # 转置
# numpy.transpose(a, axes=None) 作用:将输入的array转置,并返回转置后的array
np.random.shuffle(temp) # 按行随机打乱顺序函数
# 将所有的img和lab转换成list
image_list = list(temp[:, 0]) # 取出第0列数据,即图片路径
label_list = list(temp[:, 1]) # 取出第1列数据,即图片标签
label_list = [int(i) for i in label_list] # 转换成int数据类型
'''
# 将所得List分为两部分,一部分用来训练tra,一部分用来验证val
n_sample = len(all_label_list)
n_val = int(math.ceil(n_sample * ratio)) # 验证样本数, ratio是验证集的比例
n_train = n_sample - n_val # 训练样本数
tra_images = all_image_list[0:n_train]
tra_labels = all_label_list[0:n_train]
tra_labels = [int(float(i)) for i in tra_labels] # 转换成int数据类型
val_images = all_image_list[n_train:-1]
val_labels = all_label_list[n_train:-1]
val_labels = [int(float(i)) for i in val_labels] # 转换成int数据类型
return tra_images, tra_labels, val_images, val_labels
'''
return image_list, label_list
# 为了方便网络的训练,输入数据进行batch处理
def get_batch(image, label, image_W, image_H, batch_size, capacity):
# image_W, image_H, :图像高度和宽度
# batch_size:每个batch要放多少张图片
# capacity:一个队列最大多少
# step1:将上面生成的List传入get_batch() ,转换类型,产生一个输入队列queue
# tf.cast()用来做类型转换
image = tf.cast(image, tf.string) # 可变长度的字节数组.每一个张量元素都是一个字节数组
label = tf.cast(label, tf.int32)
# tf.train.slice_input_producer是一个tensor生成器
# 作用是按照设定,每次从一个tensor列表中按顺序或者随机抽取出一个tensor放入文件名队列。
input_queue = tf.train.slice_input_producer([image, label])
label = input_queue[1]
image_contents = tf.io.read_file(input_queue[0]) # tf.read_file()从队列中读取图像
# step2:将图像解码,使用相同类型的图像
# 将图像使用JPEG的格式解码从而得到图像对应的三维矩阵。
# Tensorflow还提供了 tf.image.decode_png函数对png格式的图像进行编码。
# 解码之后的结果为一个张量, 在使用他的取值之前需要明确调用运行的过程。
image = tf.image.decode_jpeg(image_contents, channels=3)
# jpeg或者jpg格式都用decode_jpeg函数,其他格式可以去查看官方文档
# step3:数据预处理,对图像进行旋转、缩放、裁剪、归一化等操作,让计算出的模型更健壮。
# 剪裁或填充处理,会根据原图像的尺寸和指定的目标图像的尺寸选择剪裁还是填充,
# 如果原图像尺寸大于目标图像尺寸,则在中心位置剪裁,反之则用黑色像素填充。
image = tf.image.resize_with_crop_or_pad(image, image_W, image_H)
# 对resize后的图片进行标准化处理
image = tf.image.per_image_standardization(image)
# step4:生成batch
# image_batch: 4D tensor [batch_size, width, height, 3], dtype = tf.float32
# label_batch: 1D tensor [batch_size], dtype = tf.int32
image_batch, label_batch = tf.train.batch([image, label],
batch_size=batch_size,
num_threads=16,
capacity=capacity)
# 重新排列label,行数为[batch_size]
label_batch = tf.reshape(label_batch, [batch_size])
# image_batch = tf.cast(image_batch, tf.uint8) # 显示彩色图像
image_batch = tf.cast(image_batch, tf.float32) # 显示灰度图
# print(label_batch) Tensor("Reshape:0", shape=(6,), dtype=int32)
return image_batch, label_batch
# 获取两个batch,两个batch即为传入神经网络的数据
def PreWork():
# 对预处理的数据进行可视化,查看预处理的效果
IMG_W = 256
IMG_H = 256
BATCH_SIZE = 20
CAPACITY = 64
train_dir = '/home/leisureconfused/Desktop/project/OpenCV_and_TensorFlow/GC/pic_train'
# image_list, label_list, val_images, val_labels = get_file(train_dir)
# 获取神经网络输入
image_list, label_list = get_file(train_dir)
image_batch, label_batch = get_batch(image_list, label_list, IMG_W, IMG_H, BATCH_SIZE, CAPACITY)
print(label_batch.shape)
lists = ('kou_zhao', 'mian_qian', 'yao_ping', 'zhu_she_qi')
with tf.Session() as sess:
i = 0
coord = tf.train.Coordinator() # 创建一个线程协调器,用来管理之后在Session中启动的所有线程
threads = tf.train.start_queue_runners(coord=coord)
try:
while not coord.should_stop() and i < 1:
# 提取出两个batch的图片并可视化。
img, label = sess.run([image_batch, label_batch]) # 在会话中取出img和label
# img = tf.cast(img, tf.uint8)
'''
1、range()返回的是range object,而np.arange()返回的是numpy.ndarray()
range(start, end, step),返回一个list对象,起始值为start,终止值为end,但不含终止值,步长为step。只能创建int型list。
arange(start, end, step),与range()类似,但是返回一个array对象。需要引入import numpy as np,并且arange可以使用float型数据。
2、range()不支持步长为小数,np.arange()支持步长为小数
3、两者都可用于迭代
range尽可用于迭代,而np.nrange作用远不止于此,它是一个序列,可被当做向量使用。
'''
for j in np.arange(BATCH_SIZE):
# np.arange()函数返回一个有终点和起点的固定步长的排列
print('label: %d' % label[j])
plt.imshow(img[j, :, :, :])
title = lists[int(label[j])]
plt.title(title)
plt.show()
i += 1
except tf.errors.OutOfRangeError:
print('done!')
finally:
coord.request_stop()
coord.join(threads)
if __name__ == '__main__':
PreWork()
CNNModel.py
'''
CNNModel.py
含3层卷积池化层,2层全连接层,激活函数ReLU,采用dropout和softmax函数做分类器
'''
import tensorflow as tf
# 函数申明
def weight_variable(shape, n):
# tf.truncated_normal(shape, mean, stddev)这个函数产生正态分布,均值和标准差自己设定。
# shape表示生成张量的维度,mean是均值
# stddev是标准差,,默认最大为1,最小为-1,均值为0
initial = tf.random.truncated_normal(shape, stddev=n, dtype=tf.float32)
return initial
def bias_variable(shape):
# 创建一个结构为shape矩阵也可以说是数组shape声明其行列,初始化所有值为0.1
initial = tf.constant(0.1, shape=shape, dtype=tf.float32)
return initial
def conv2d(x, W):
# 卷积遍历各方向步数为1,SAME:边缘外自动补0,遍历相乘
# padding 一般只有两个值
# 卷积层后输出图像大小为:(W+2P-f)/stride+1并向下取整
return tf.nn.conv2d(x, W, strides=[1, 1, 1, 1], padding='SAME')
def max_pool_2x2(x, name):
# 池化卷积结果(conv2d)池化层采用kernel大小为3*3,步数也为2,SAME:周围补0,取最大值。数据量缩小了4倍
# x 是 CNN 第一步卷积的输出量,其shape必须为[batch, height, weight, channels];
# ksize 是池化窗口的大小, shape为[batch, height, weight, channels]
# stride 步长,一般是[1,stride, stride,1]
# 池化层输出图像的大小为(W-f)/stride+1,向上取整
return tf.nn.max_pool2d(x, ksize=[1, 3, 3, 1], strides=[1, 2, 2, 1], padding='SAME', name=name)
# 一个简单的卷积神经网络,卷积+池化层 x2,全连接层x2,最后一个softmax层做分类。
# 64个3x3的卷积核(3通道),padding=’SAME’,表示padding后卷积的图与原图尺寸一致,激活函数relu()
def deep_CNN(images, batch_size, n_classes):
# 搭建网络
# 第一层卷积
# 第一二参数值得卷积核尺寸大小,即patch;第三个参数是通道数;第四个是卷积核个数
with tf.compat.v1.variable_scope('conv1') as scope:
# 所谓名字的scope,指当绑定了一个名字到一个对象的时候,该名字在程序文本中的可见范围
w_conv1 = tf.Variable(weight_variable([3, 3, 3, 64], 1.0), name='weights', dtype=tf.float32)
b_conv1 = tf.Variable(bias_variable([64]), name='biases', dtype=tf.float32) # 64个偏置值
# tf.nn.bias_add 是 tf.add 的一个特例:tf.add(tf.matmul(x, w), b) == tf.matmul(x, w) + b
# h_conv1 = tf.nn.relu(tf.nn.bias_add(conv2d(images, w_conv1), b_conv1), name=scope.name)
h_conv1 = tf.nn.relu(conv2d(images, w_conv1)+b_conv1, name='conv1') # 得到128*128*64(假设原始图像是128*128)
# 第一层池化
# 3x3最大池化,步长strides为2,池化后执行lrn()操作,局部响应归一化,增强了模型的泛化能力。
# tf.nn.lrn(input,depth_radius=None,bias=None,alpha=None,beta=None,name=None)
with tf.compat.v1.variable_scope('pooling1_lrn') as scope:
pool1 = max_pool_2x2(h_conv1, 'pooling1') # 得到64*64*64
norm1 = tf.nn.lrn(pool1, depth_radius=4, bias=1.0, alpha=0.001 / 9.0, beta=0.75, name='norm1')
# 第二层卷积
# 32个3x3的卷积核(16通道),padding=’SAME’,表示padding后卷积的图与原图尺寸一致,激活函数relu()
with tf.compat.v1.variable_scope('conv2') as scope:
w_conv2 = tf.Variable(weight_variable([3, 3, 64, 32], 0.1), name='weights', dtype=tf.float32)
b_conv2 = tf.Variable(bias_variable([32]), name='biases', dtype=tf.float32) # 32个偏置值
h_conv2 = tf.nn.relu(conv2d(norm1, w_conv2)+b_conv2, name='conv2') # 得到64*64*32
# 第二层池化
# 3x3最大池化,步长strides为2,池化后执行lrn()操作
with tf.variable_scope('pooling2_lrn') as scope:
pool2 = max_pool_2x2(h_conv2, 'pooling2') # 得到32*32*32
norm2 = tf.nn.lrn(pool2, depth_radius=4, bias=1.0, alpha=0.001 / 9.0, beta=0.75, name='norm2')
# 第三层卷积
# 16个3x3的卷积核(16通道),padding=’SAME’,表示padding后卷积的图与原图尺寸一致,激活函数relu()
with tf.variable_scope('conv3') as scope:
w_conv3 = tf.Variable(weight_variable([3, 3, 32, 16], 0.1), name='weights', dtype=tf.float32)
b_conv3 = tf.Variable(bias_variable([16]), name='biases', dtype=tf.float32) # 16个偏置值
h_conv3 = tf.nn.relu(conv2d(norm2, w_conv3)+b_conv3, name='conv3') # 得到32*32*16
# 第三层池化
# 3x3最大池化,步长strides为2,池化后执行lrn()操作
with tf.variable_scope('pooling3_lrn') as scope:
pool3 = max_pool_2x2(h_conv3, 'pooling3') # 得到16*16*16
# print("=======================================================================================================")
# print(pool3)
# print("=======================================================================================================")
norm3 = tf.nn.lrn(pool3, depth_radius=4, bias=1.0, alpha=0.001 / 9.0, beta=0.75, name='norm3')
# 第四层全连接层
# 128个神经元,将之前pool层的输出reshape成一行,激活函数relu()
with tf.variable_scope('local3') as scope:
reshape = tf.reshape(norm3, shape=[batch_size, -1])
# print("=======================================================================================================")
# print(reshape)
# print("=======================================================================================================")
dim = reshape.get_shape()[1].value
# print("=======================================================================================================")
# print(dim)
# print("=======================================================================================================")
w_fc1 = tf.Variable(weight_variable([dim, 128], 0.005), name='weights', dtype=tf.float32)
b_fc1 = tf.Variable(bias_variable([128]), name='biases', dtype=tf.float32)
h_fc1 = tf.nn.relu(tf.matmul(reshape, w_fc1) + b_fc1, name=scope.name)
# 第五层全连接层
# 128个神经元,激活函数relu()
with tf.variable_scope('local4') as scope:
w_fc2 = tf.Variable(weight_variable([128 ,128], 0.005),name='weights', dtype=tf.float32)
b_fc2 = tf.Variable(bias_variable([128]), name='biases', dtype=tf.float32)
h_fc2 = tf.nn.relu(tf.matmul(h_fc1, w_fc2) + b_fc2, name=scope.name)
# 对卷积结果执行dropout操作
# keep_prob = tf.placeholder(tf.float32)
h_fc2_dropout = tf.nn.dropout(h_fc2, 0.5)
# tf.nn.dropout(x, keep_prob, noise_shape=None, seed=None, name=None)
# 第二个参数keep_prob: 设置神经元被选中的概率,在初始化时keep_prob是一个占位符
# Softmax回归层
# 将前面的FC层输出,做一个线性回归,计算出每一类的得分,在这里是6类,所以这个层输出的是六个得分。
with tf.variable_scope('softmax_linear') as scope:
weights = tf.Variable(weight_variable([128, n_classes], 0.005), name='softmax_linear', dtype=tf.float32)
biases = tf.Variable(bias_variable([n_classes]), name='biases', dtype=tf.float32)
softmax_linear = tf.add(tf.matmul(h_fc2_dropout, weights), biases, name='softmax_linear')
# softmax_linear = tf.nn.softmax(tf.add(tf.matmul(h_fc2_dropout, weights), biases, name='softmax_linear'))
return softmax_linear
# 最后返回softmax层的输出
# loss计算
# 传入参数:logits,网络计算输出值。labels,真实值,0或者1
# 返回参数:loss,损失值
def losses(logits, labels):
with tf.variable_scope('loss') as scope:
cross_entropy = tf.nn.sparse_softmax_cross_entropy_with_logits(logits=logits, labels=labels, name='xentropy_per_example')
loss = tf.reduce_mean(cross_entropy, name='loss')
tf.summary.scalar(scope.name + '/loss', loss)
return loss
# loss损失值优化
# 输入参数:loss。learning_rate,学习速率。
# 返回参数:train_op,训练op,这个参数要输入sess.run中让模型去训练。
def trainning(loss, learning_rate):
with tf.name_scope('optimizer'):
optimizer = tf.train.AdamOptimizer(learning_rate=learning_rate)
global_step = tf.Variable(0, name='global_step', trainable=False)
train_op = optimizer.minimize(loss, global_step=global_step)
return train_op
# 评价/准确率计算
# 输入参数:logits,网络计算值。labels,标签,也就是真实值,在这里是0或者1。
# 返回参数:accuracy,当前step的平均准确率,也就是在这些batch中多少张图片被正确分类了。
def evaluation(logits, labels):
with tf.variable_scope('accuracy') as scope:
correct = tf.nn.in_top_k(logits, labels, 1)
accuracy = tf.reduce_mean(tf.cast(correct, tf.float16))
tf.summary.scalar(scope.name + '/accuracy', accuracy)
return accuracy
Train.py
'''
Train.py
对搭建好的网络进行训练,并保存训练参数,以便下次使用
'''
# 导入文件
import os
import numpy as np
import tensorflow as tf
from PreWork import get_file, get_batch
from CNNModel import deep_CNN, losses, trainning, evaluation
# 变量声明
N_CLASSES = 4
IMG_W = 28 # resize图像,太大的话训练时间久
IMG_H = 28
BATCH_SIZE = 20 # 每个batch要放多少张图片
CAPACITY = 200 # 一个队列最大多少
MAX_STEP = 800 # 训练批次
learning_rate = 0.0001 # 一般小于0.0001
# 获取批次batch
train_dir = '/home/leisureconfused/Desktop/project/OpenCV_and_TensorFlow/GC/pic_train' # 训练样本的读入路径
logs_train_dir = '/home/leisureconfused/Desktop/project/OpenCV_and_TensorFlow/GC/logred' #logs存储路径
train, train_label = get_file(train_dir)
# 训练数据及标签
train_batch, train_label_batch = get_batch(train, train_label, IMG_W, IMG_H, BATCH_SIZE, CAPACITY)
# 训练操作定义
train_logits = deep_CNN(train_batch, BATCH_SIZE, N_CLASSES)
train_loss = losses(train_logits, train_label_batch)
train_op = trainning(train_loss, learning_rate)
train_acc = evaluation(train_logits, train_label_batch)
# 这个是log汇总记录
summary_op = tf.compat.v1.summary.merge_all()
# 产生一个会话
sess = tf.compat.v1.Session()
train_writer = tf.summary.FileWriter(logs_train_dir, sess.graph)
# 产生一个saver来存储训练好的模型
saver = tf.train.Saver()
# 所有节点初始化
sess.run(tf.global_variables_initializer())
# 队列监控
coord = tf.train.Coordinator() # 设置多线程协调器
threads = tf.train.start_queue_runners(sess=sess, coord=coord)
# 进行batch的训练
try:
# 执行MAX_STEP步的训练,一步一个batch
for step in np.arange(MAX_STEP):
if coord.should_stop():
break
# 启动以下操作节点,有个疑问,为什么train_logits在这里没有开启?
_, tra_loss, tra_acc = sess.run([train_op, train_loss, train_acc])
# 每隔50步打印一次当前的loss以及acc,同时记录log,写入writer
if step % 100 == 0:
print('Step %d, train loss = %.2f, train accuracy = %.2f%%' % (step, tra_loss, tra_acc * 100.0))
summary_str = sess.run(summary_op)
train_writer.add_summary(summary_str, step)
# 保存最后一次网络参数
checkpoint_path = os.path.join(logs_train_dir, 'thing.ckpt')
saver.save(sess, checkpoint_path)
'''
# 每隔100步,保存一次训练好的模型
if (step + 1) == MAX_STEP:
checkpoint_path = os.path.join(logs_train_dir, 'thing.ckpt')
saver.save(sess, checkpoint_path, global_step=step)
'''
except tf.errors.OutOfRangeError:
print('Done training -- epoch limit reached')
finally:
coord.request_stop()
coord.join(threads)
sess.close()
Test.py
'''
Test.py
测试。。
'''
# 导入必要的包
import os
import numpy as np
from PIL import Image
import tensorflow as tf
import matplotlib.pyplot as plt
from CNNModel import deep_CNN
N_CLASSES = 4
img_dir = '/home/leisureconfused/Desktop/project/OpenCV_and_TensorFlow/GC/pic_test1/'
log_dir = '/home/leisureconfused/Desktop/project/OpenCV_and_TensorFlow/GC/logred'
lists = ['kou_zhao', 'mian_qian', 'yao_ping','zhu_she_qi']
# 从测试集中随机挑选一张图片看测试结果
def get_one_image(img_dir):
# 返回指定的文件夹包含的文件或文件夹的名字的列表
imgs = os.listdir(img_dir)
# 求指定文件夹下列表的长度
img_num = len(imgs)
# print(imgs, img_num)
# 返回一个随机整型数,范围从低(包括)到高(不包括),即[low, high)。
# 如果没有写参数high的值,则返回[0,low)的值。
idn = np.random.randint(0, img_num)
# 取到随机的图片
image = imgs[idn]
# 返回测试图像路径
image_dir = img_dir + image
# print(image_dir)
# open() 函数用于打开一个文件并创建一个file对象
image = Image.open(image_dir)
plt.imshow(image)
plt.show()
# 改变图像尺寸(模糊化处理)
image = image.resize([28, 28])
# plt.imshow(image)
# plt.show()
# 将其变为n维数组
image_arr = np.array(image)
return image_arr
def test(image_arr):
# 返回一个上下文管理器,这个上下管理器使用这个图作为默认的图
with tf.Graph().as_default():
# 张量数据类型转换
image = tf.cast(image_arr, tf.float32)
# tf.image.per_image_standardization() 的运算过程是将整幅图片标准化(不是归一化),加速神经网络的训练。
# 主要有如下操作,(x - mean) / adjusted_stddev,其中x为图片的RGB三通道像素值,mean分别为三通道像素的均值,
# adjusted_stddev = max(stddev, 1.0/sqrt(image.NumElements()))。
# stddev为三通道像素的标准差,image.NumElements()计算的是三通道各自的像素个数。
image = tf.image.per_image_standardization(image)
# 改变测试图片大小为网络标准输入
image = tf.reshape(image, [1, 28, 28, 3])
# print(image.shape)
# 将测试图片输入网络
p = deep_CNN(image, 1, N_CLASSES)
# softmax的输入是一个张量,数据类型必须是half, float32, float64
# softmax简单的说就是把一个N*1的向量归一化为(0,1)之间的值,
# 由于其中采用指数运算,使得向量中数值较大的量特征更加明显。
logits = tf.nn.softmax(p)
x = tf.compat.v1.placeholder(tf.float32, shape=[28, 28, 3])
saver = tf.compat.v1.train.Saver()
sess = tf.compat.v1.Session()
sess.run(tf.compat.v1.global_variables_initializer())
# 从保存路径加载模型文件
ckpt = tf.train.get_checkpoint_state(log_dir)
if ckpt and ckpt.model_checkpoint_path:
# print(ckpt.model_checkpoint_path)
# 调用saver.restore()函数,加载训练好的网络模型
saver.restore(sess, ckpt.model_checkpoint_path)
# print('Loading success')
# 获取网络输出
prediction = sess.run(logits, feed_dict={x: image_arr})
# 返回一个numpy数组中最大值的索引值
max_index = np.argmax(prediction)
print('预测的标签为:', max_index, lists[max_index])
print('预测的结果为:', prediction)
if __name__ == '__main__':
img = get_one_image(img_dir)
test(img)
add_cv1.py
'''
Test&CV(未加串口)
'''
# 导入必要的包
import os
import numpy as np
from PIL import Image
import cv2
import tensorflow as tf
import matplotlib.pyplot as plt
from CNNModel import deep_CNN
N_CLASSES = 4
img_dir = 'D:/anaconda/vscode-python/pic_use/'
log_dir = 'D:/anaconda/vscode-python/log'
lists = ['kou_zhao', 'mian_qian', 'yao_ping','zhu_she_qi']
def get_one_image(img_dir):
# 返回指定的文件夹包含的文件或文件夹的名字的列表
imgs = os.listdir(img_dir)
# 求指定文件夹下列表的长度
img_num = len(imgs)
# print(imgs, img_num)
# 返回一个随机整型数,范围从低(包括)到高(不包括),即[low, high)。
# 如果没有写参数high的值,则返回[0,low)的值。
idn = np.random.randint(0, img_num)
# 取到随机的图片
image = imgs[idn]
# 返回测试图像路径
image_dir = img_dir + image
# print(image_dir)
# open() 函数用于打开一个文件并创建一个file对象
image = Image.open(image_dir)
# plt.imshow(image)
# plt.show()
# 改变图像尺寸(模糊化处理)
image = image.resize([28, 28])
# plt.imshow(image)
# plt.show()
# 将其变为n维数组
image_arr = np.array(image)
return image_arr
def test(image_arr):
# 返回一个上下文管理器,这个上下管理器使用这个图作为默认的图
with tf.Graph().as_default():
# 张量数据类型转换
image = tf.cast(image_arr, tf.float32)
# tf.image.per_image_standardization() 的运算过程是将整幅图片标准化(不是归一化),加速神经网络的训练。
# 主要有如下操作,(x - mean) / adjusted_stddev,其中x为图片的RGB三通道像素值,mean分别为三通道像素的均值,
# adjusted_stddev = max(stddev, 1.0/sqrt(image.NumElements()))。
# stddev为三通道像素的标准差,image.NumElements()计算的是三通道各自的像素个数。
image = tf.image.per_image_standardization(image)
# 改变测试图片大小为网络标准输入
image = tf.reshape(image, [1, 28, 28, 3])
# print(image.shape)
# 将测试图片输入网络
p = deep_CNN(image, 1, N_CLASSES)
# softmax的输入是一个张量,数据类型必须是half, float32, float64
# softmax简单的说就是把一个N*1的向量归一化为(0,1)之间的值,
# 由于其中采用指数运算,使得向量中数值较大的量特征更加明显。
logits = tf.nn.softmax(p)
x = tf.compat.v1.placeholder(tf.float32, shape=[28, 28, 3])
saver = tf.compat.v1.train.Saver()
sess = tf.compat.v1.Session()
sess.run(tf.compat.v1.global_variables_initializer())
# 从保存路径加载模型文件
ckpt = tf.train.get_checkpoint_state(log_dir)
if ckpt and ckpt.model_checkpoint_path:
# print(ckpt.model_checkpoint_path)
# 调用saver.restore()函数,加载训练好的网络模型
saver.restore(sess, ckpt.model_checkpoint_path)
# print('Loading success')
# 获取网络输出
prediction = sess.run(logits, feed_dict={x: image_arr})
# 返回一个numpy数组中最大值的索引值
max_index = np.argmax(prediction)
print('预测的标签为:', max_index, lists[max_index])
print('预测的结果为:', prediction)
index = 1
cap = cv2.VideoCapture(0)
width = 640
height = 480
w = 360
cap.set(cv2.CAP_PROP_FRAME_WIDTH, width)
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, height)
crop_w_start = (width-w)//2
crop_h_start = (height-w)//2
# print(width, height)
while True:
# get a frame
ret, frame = cap.read()
# show a frame
frame = frame[crop_h_start:crop_h_start+w, crop_w_start:crop_w_start+w]
frame = cv2.flip(frame,1,dst=None)
cv2.imshow("capture", frame)
input = cv2.waitKey(1) & 0xFF
if input == ord('x'):
cv2.imwrite("%s/%d.jpeg" % (img_dir, index),
cv2.resize(frame, (224, 224), interpolation=cv2.INTER_AREA))
# print("%s: %d 张图片" % img_dir, index)
index += 1
# 调用模型查看结果
img = get_one_image(img_dir)
test(img)
if input == ord('q'):
break
cap.release()
cv2.destroyAllWindows()
'''
if __name__ == '__main__':
img = get_one_image(img_dir)
test(img)
'''
以上参考自: 完整实现利用tensorflow训练自己的图片数据集
GPIO口调试程序
'''
import sys
sys.path.append('/opt/nvidia/jetson-gpio/lib/python/')
sys.path.append('/opt/nvidia/jetson-gpio/lib/python/Jetson/GPIO')
'''
import Jetson.GPIO as GPIO
import time
read = 33
kouzhao = 35
mianqian = 36
yaoping = 37
zhusheqi = 38
GPIO.setmode(GPIO.BOARD)
GPIO.setup(read, GPIO.IN)
GPIO.setup(kouzhao, GPIO.OUT, initial=GPIO.HIGH)
# GPIO.setup(mianqian, GPIO.OUT, initial=GPIO.HIGH)
# GPIO.setup(yaoping, GPIO.OUT, initial=GPIO.HIGH)
# GPIO.setup(zhusheqi, GPIO.OUT, initial=GPIO.HIGH)
GPIO.setwarnings(False)
while True:
GPIO.setup(read, GPIO.IN)
GPIO.setup(kouzhao, GPIO.OUT, initial=GPIO.HIGH)
print("#######################")
time.sleep(2)
if GPIO.input(read) == GPIO.HIGH:
print("........................................")
GPIO.output(kouzhao,GPIO.LOW)
time.sleep(2)
GPIO.setup(kouzhao, GPIO.HIGH)
GPIO.setup(read, GPIO.HIGH)
GPIO.cleanup()
该程序参考自: https://pypi.org/project/Jetson.GPIO/
调用cv拍摄图片保存到测试集
import cv2
import os
print("=============================================")
print("= 热键(请在摄像头的窗口使用): =")
print("= z: 更改存储目录 =")
print("= x: 拍摄图片 =")
print("= q: 退出 =")
print("=============================================")
print()
class_name = input("请输入存储目录:")
while os.path.exists(class_name):
class_name = input("目录已存在!请输入存储目录:")
os.mkdir(class_name)
index = 1
cap = cv2.VideoCapture(0)
width = 640
height = 480
w = 360
cap.set(cv2.CAP_PROP_FRAME_WIDTH, width)
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, height)
crop_w_start = (width-w)//2
crop_h_start = (height-w)//2
print(width, height)
while True:
# get a frame
ret, frame = cap.read()
# show a frame
frame = frame[crop_h_start:crop_h_start+w, crop_w_start:crop_w_start+w]
frame = cv2.flip(frame,1,dst=None)
cv2.imshow("capture", frame)
input = cv2.waitKey(1) & 0xFF
if input == ord('z'):
class_name = input("请输入存储目录:")
while os.path.exists(class_name):
class_name = input("目录已存在!请输入存储目录:")
os.mkdir(class_name)
elif input == ord('x'):
cv2.imwrite("%s/%d.jpeg" % (class_name, index),
cv2.resize(frame, (224, 224), interpolation=cv2.INTER_AREA))
print("%s: %d 张图片" % (class_name, index))
index += 1
if input == ord('q'):
break
cap.release()
cv2.destroyAllWindows()
来自于某个老哥, 具体链接地址忘记了…
主程序
'''
used
'''
# 导入必要的包
import os
import numpy as np
from PIL import Image
import cv2
import tensorflow as tf
import matplotlib.pyplot as plt
from CNNModel import deep_CNN
import Jetson.GPIO as GPIO
import time
# type
N_CLASSES = 4
lists = ['kou_zhao', 'mian_qian', 'yao_ping','zhu_she_qi']
# path
img_dir = '/home/leisureconfused/Desktop/project/OpenCV_and_TensorFlow/GC/pic_use/'
log_dir = '/home/leisureconfused/Desktop/project/OpenCV_and_TensorFlow/GC/logred'
# GPIO
read = 33
kouzhao = 35
mianqian = 36
yaoping = 37
zhusheqi = 38
GPIO.setmode(GPIO.BOARD)
GPIO.setup(read, GPIO.IN)
GPIO.setup(kouzhao, GPIO.OUT, initial=GPIO.HIGH)
GPIO.setup(mianqian, GPIO.OUT, initial=GPIO.HIGH)
GPIO.setup(yaoping, GPIO.OUT, initial=GPIO.HIGH)
GPIO.setup(zhusheqi, GPIO.OUT, initial=GPIO.HIGH)
GPIO.setwarnings(False)
# cv
index = 1
cap = cv2.VideoCapture(0)
width = 640
height = 480
w = 360
cap.set(cv2.CAP_PROP_FRAME_WIDTH, width)
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, height)
crop_w_start = (width-w)//2
crop_h_start = (height-w)//2
# print(width, height)
def get_one_image(img_dir):
# 返回指定的文件夹包含的文件或文件夹的名字的列表
imgs = os.listdir(img_dir)
# 求指定文件夹下列表的长度
img_num = len(imgs)
# print(imgs, img_num)
# 返回一个随机整型数,范围从低(包括)到高(不包括),即[low, high)。
# 如果没有写参数high的值,则返回[0,low)的值。
idn = np.random.randint(0, img_num)
# 取到随机的图片
image = imgs[idn]
# 返回测试图像路径
image_dir = img_dir + image
# print(image_dir)
# open() 函数用于打开一个文件并创建一个file对象
image = Image.open(image_dir)
# plt.imshow(image)
# plt.show()
# 改变图像尺寸(模糊化处理)
image = image.resize([28, 28])
# plt.imshow(image)
# plt.show()
# 将其变为n维数组
image_arr = np.array(image)
return image_arr
def test(image_arr):
# 返回一个上下文管理器,这个上下管理器使用这个图作为默认的图
with tf.Graph().as_default():
# 张量数据类型转换
image = tf.cast(image_arr, tf.float32)
# tf.image.per_image_standardization() 的运算过程是将整幅图片标准化(不是归一化),加速神经网络的训练。
# 主要有如下操作,(x - mean) / adjusted_stddev,其中x为图片的RGB三通道像素值,mean分别为三通道像素的均值,
# adjusted_stddev = max(stddev, 1.0/sqrt(image.NumElements()))。
# stddev为三通道像素的标准差,image.NumElements()计算的是三通道各自的像素个数。
image = tf.image.per_image_standardization(image)
# 改变测试图片大小为网络标准输入
image = tf.reshape(image, [1, 28, 28, 3])
# print(image.shape)
# 将测试图片输入网络
p = deep_CNN(image, 1, N_CLASSES)
# softmax的输入是一个张量,数据类型必须是half, float32, float64
# softmax简单的说就是把一个N*1的向量归一化为(0,1)之间的值,
# 由于其中采用指数运算,使得向量中数值较大的量特征更加明显。
logits = tf.nn.softmax(p)
x = tf.compat.v1.placeholder(tf.float32, shape=[28, 28, 3])
saver = tf.compat.v1.train.Saver()
sess = tf.compat.v1.Session()
sess.run(tf.compat.v1.global_variables_initializer())
# 从保存路径加载模型文件
ckpt = tf.train.get_checkpoint_state(log_dir)
if ckpt and ckpt.model_checkpoint_path:
# print(ckpt.model_checkpoint_path)
# 调用saver.restore()函数,加载训练好的网络模型
saver.restore(sess, ckpt.model_checkpoint_path)
# print('Loading success')
# 获取网络输出
prediction = sess.run(logits, feed_dict={x: image_arr})
# 返回一个numpy数组中最大值的索引值
max_index = np.argmax(prediction)
print('预测的标签为:', max_index, lists[max_index])
print('预测的结果为:', prediction)
return max_index
# main
while True:
# get gpio
GPIO.setup(read, GPIO.IN)
GPIO.setup(kouzhao, GPIO.OUT, initial=GPIO.HIGH)
GPIO.setup(yaoping, GPIO.OUT, initial=GPIO.HIGH)
GPIO.setup(mianqian, GPIO.OUT, initial=GPIO.HIGH)
GPIO.setup(zhusheqi, GPIO.OUT, initial=GPIO.HIGH)
# print("#######################")
# get a frame
ret, frame = cap.read()
# show a frame
frame = frame[crop_h_start:crop_h_start+w, crop_w_start:crop_w_start+w]
frame = cv2.flip(frame,1,dst=None)
cv2.imshow("capture", frame)
key = cv2.waitKey(1) & 0xFF
if key == ord('q'):
break
cv2.imwrite("%s/%d.jpeg" % (img_dir, index),
cv2.resize(frame, (224, 224), interpolation=cv2.INTER_AREA))
# print("%s: %d 张图片" % img_dir, index)
index += 1
# 调用模型查看结果
img = get_one_image(img_dir)
p = test(img)
if GPIO.input(read) == GPIO.HIGH:
'''
cv2.imwrite("%s/%d.jpeg" % (img_dir, index),
cv2.resize(frame, (224, 224), interpolation=cv2.INTER_AREA))
# print("%s: %d 张图片" % img_dir, index)
index += 1
# 调用模型查看结果
img = get_one_image(img_dir)
p = test(img)
'''
if p == 0:
GPIO.output(kouzhao, GPIO.LOW)
elif p == 1:
GPIO.output(mianqian, GPIO.LOW)
elif p == 2:
GPIO.output(yaoping, GPIO.LOW)
elif p == 3:
GPIO.output(zhusheqi, GPIO.LOW)
# output
# GPIO.output(kouzhao, GPIO.LOW)
# print("####################################")
# 输出长达1s的低电平
time.sleep(1)
'''
GPIO.setup(zhusheqi, GPIO.HIGH)
GPIO.setup(yaoping, GPIO.HIGH)
GPIO.setup(mianqian, GPIO.HIGH)
GPIO.setup(kouzhao, GPIO.HIGH)
# GPIO.setup(read, GPIO.HIGH)
'''
'''
if input == ord('q'):
break
'''
cap.release()
cv2.destroyAllWindows()
GPIO.cleanup()
'''
if __name__ == '__main__':
img = get_one_image(img_dir)
test(img)
'''
PS: 注射器暂时没弄到就用史莱姆代替的人体组织(没改名, 所以名称还是注射器)…
基本识别速度可以达到每秒至少一次(好慢…)
不过这个简单的网络模型带来的准确率属实很低而且只针对于所拍摄的那4个固定的物体…
另外关于文件路径, 因为是在我的win10上测试后移植到nano上的, 所以有点乱七八糟, 后期比赛完成后还会整理的…
以及, nano的性能远没有被开发完…
项目工程文件已上传至百度网盘
链接:https://pan.baidu.com/s/1CDZgTndrygBOWuGfy6VUdg
提取码:enzq