在之前一篇文章——石头剪刀布之卷积神经网络,我已经定义了网络模型,当时在每类200张图片的情况下可以达到89%左右的精度。在本项目中,获取数据的成本并不是很高,利用摄像头就可以获得足够多的数据。因此,我又收集了一些数据,使得每类的图片大概是3000张左右。按照之前的训练方法,验证精度可以达到98.9%,识别一张图片的时间在25ms左右。这样的网络模型就可以满足要求。
有了训练好的模型(相当于一个大脑),有了摄像头(相当于眼睛),有了舵机(相当于手)。就可以把这些集成,来完成“石头剪刀布”这个游戏了。
以下是整个系统的连接图:
摄像头正对着背景板,放的位置和角度要尽可能和获取数据时的位置一样,这样识别精度更高。舵机和指针用来输出树莓派的计算结果。石头剪刀布的图片可以从网上下载,打印出来,粘贴上去。
通过在树莓派上运行以下代码,就可以实现石头剪刀布的功能了(rps.py)。
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
import tensorflow as tf
import numpy as np
import PIL.Image as Image
from pylab import *
import time
import cv2
import RPi.GPIO as GPIO
import signal
import atexit
# 舵机旋转的角度
def rotate(p, angle):
p.ChangeDutyCycle(7.5+10*angle/180)
time.sleep(1)
p.ChangeDutyCycle(0)
# 石头剪刀布主程序
def rps(model_dir, classes, p):
clicked = False
def onMouse(event, x, y, flags, param):
global clicked
if event == cv2.EVENT_LBUTTONUP:
clicked = True
cameraCapture = cv2.VideoCapture(0)
cameraCapture.set(3, 100) # 帧宽度
cameraCapture.set(4, 100) # 帧高度
cv2.namedWindow('MyWindow')
cv2.setMouseCallback('MyWindow', onMouse)
print('showing camera feed. Click window or press and key to stop.')
success, frame = cameraCapture.read()
print(success)
count = 0
flag = 0
saver = tf.train.import_meta_graph(model_dir+".meta")
with tf.Session() as sess:
saver.restore(sess, model_dir)
x = tf.get_default_graph().get_tensor_by_name("images:0")
keep_prob = tf.get_default_graph().get_tensor_by_name("keep_prob:0")
y = tf.get_default_graph().get_tensor_by_name("fc2/output:0")
count=0
while success and cv2.waitKey(1)==-1 and not clicked:
time1 = time.time()
cv2.imshow('MyWindow', frame)
success, frame = cameraCapture.read()
img = Image.fromarray(frame)
# 将图片转化成灰度并缩小尺寸
img = array(img.convert('L').resize((28, 28)),dtype=float32)
img = img.reshape((1,28*28))
img = img/255.0 # 图像前处理
prediction = sess.run(y, feed_dict={x:img,keep_prob: 1.0})
index = np.argmax(prediction)
probability = prediction[0][index]
# 设置probability为0.8是为了提高识别稳定性
if index==1 and flag!=1 and probability>0.8:
rotate(p, 30)
flag=1
elif index==2 and flag!=2 and probability>0.8:
rotate(p, 0)
flag = 2
elif index==3 and flag!=3 and probability>0.8:
rotate(p, -30)
flag = 3
time2 = time.time()
if count%30==0:
print(classes[index])
print('using time: ', time2-time1)
print('probability: %.3g' % probability)
count+=1
cv2.destroyWindow('MyWindow')
cameraCapture.release()
if __name__=="__main__":
classes = ['others','paper','rock','scissors']
model_dir="model/model.ckpt"
atexit.register(GPIO.cleanup)
servopin = 21
GPIO.setmode(GPIO.BCM)
GPIO.setup(servopin, GPIO.OUT, initial=False)
p = GPIO.PWM(servopin,50) #50HZ
p.start(0)
time.sleep(2)
rps(model_dir, classes, p)
运行以上代码,效果如下动画所示:
从效果上看,还是不错的。几乎看不到有延迟的现象,而且识别得很稳定。
终于从头到尾完成一个项目了,还是蛮有成就感的。春节过后,把这些整理成一个单一的文章。
版权声明:本文为Lauyeed原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。