利用神经网络识别骰子点数
前言小叙
机器学习,Machine Learning走进我的视野范围,过程还挺有意思。第一次听到这个词还是在Blacksburg的公寓,王俊鹏向我介绍了计算机研究领域的几大方向,其中就有机器学习,人工智能。给我举得例子就是语义识别,不断给计算机喂书,然后拿出来一本计算机从来没有见过的书,计算机便可以知道这句话的意思,表达出来。这个月初,在Prof. Jin 的推荐之下,开始了MachineLeanring的学习.前几天打电话给深圳的陈佳,他电话中特意问道,你知道不知道机器学习,我最近在研究,真是无巧不成书,想来最近很火爆,我自然不能落后,要迎头赶上。
这里给大家介绍一下我入门的资料,其实不多,一个是Coursera上面Andrew的课程,不过我觉得课程太拖沓,所以找到了Rachel Zhang的csdn博客,她记下来的课程笔记还是比较实用,因为之前重新复习了线性代数和微积分,所以看笔记琢磨一下还是可以懂80%。
然后是cnblogs的subconscious,用白话解释一些概念,读起来会有一个大致的把握。然后在YouTube上看了MorvanZhou的视频介绍,视频精简短小,适合我这种碎片化的学习。
然后,今天我要介绍的是我设计的一个识别骰子点数识别的算法。我们一款游戏开奖需要用到投掷骰子根据点数决定结果,但是我们的工作人员有时候会输错骰子的点数,导致错误,所以我们需要找到一种可以识别骰子点数的程序,来及时纠正我们工作人员的输入错误,在适当的时间给出提示。那么,如何寻找到这样一种识别算法呢?在我看完ML神经网络模型的时候,我恍然大悟,我要找的就是他。
这里给大家介绍一下我入门的资料,其实不多,一个是Coursera上面Andrew的课程,不过我觉得课程太拖沓,所以找到了Rachel Zhang的csdn博客,她记下来的课程笔记还是比较实用,因为之前重新复习了线性代数和微积分,所以看笔记琢磨一下还是可以懂80%。
然后是cnblogs的subconscious,用白话解释一些概念,读起来会有一个大致的把握。然后在YouTube上看了MorvanZhou的视频介绍,视频精简短小,适合我这种碎片化的学习。
然后,今天我要介绍的是我设计的一个识别骰子点数识别的算法。我们一款游戏开奖需要用到投掷骰子根据点数决定结果,但是我们的工作人员有时候会输错骰子的点数,导致错误,所以我们需要找到一种可以识别骰子点数的程序,来及时纠正我们工作人员的输入错误,在适当的时间给出提示。那么,如何寻找到这样一种识别算法呢?在我看完ML神经网络模型的时候,我恍然大悟,我要找的就是他。
什么是神经网络?
首先介绍神经网络,这一步的详细可看cnblog的subconscious的博客:http://www.cnblogs.com/subconscious/p/5058741.html 有详细的解释,也可参考Andrew的课程或者很多博客的笔记
简要介绍下。神经网络的每个单元如下:
![logistic]()

其对应的公式如下:W是权重值,b是bais 说白了,如果你之前了解过逻辑回归模型的话,神经网络其实就是一种复杂的逻辑回归,如果你使用了sigmoid函数的话。

其中,该单元也可以被称作是Logistic回归模型。当将多个单元组合起来并具有分层结构时,就形成了神经网络模型。下图展示了一个具有一个隐含层的神经网络。

其对应的公式如下:

比较类似的,可以拓展到有2,3,4,5,…个隐含层。
神经网络的训练方法也同Logistic类似,不过由于其多层性,还需要利用链式求导法则对隐含层的节点进行求导,即梯度下降+链式求导法则,专业名称为反向传播(bpnn 正是本设计使用的方法)。
算法背景
本程序实现的就是类似上图的神经网络,只不过我的只有两层隐藏层,输出是6个节点,输入其实是888左右个一维数据
不得不提的是,我今年拖同事从过来买过来的吴军写的数学之美里面也有提到神经网络,这本书我反复看了两遍,神经网络这一章节总是没有看出所以来,但是我系统的从头了解了ML之后,再去看数学之美,基本上就秒懂。
既然神经网络可以用来分类,我遇到的问题其实就是一个分类问题,每一个骰子只有六个面,一共只有六中点数,从一到六。任务就是将截图中的骰子分为六类,每一类对应一个点数。神经网络具备这个功能之后,再次输入新的截图,它能够准确识别这张图片属于哪一类,从而给出骰子的点数。话不多说,我们细看代码实现。
Code实现
图像处理:
原图像都是这个样子的:
我们训练的图是这个样子的:
第一步,就是图像处理,生产我们的训练数据集。我们需要抽取三个骰子的图像,然后将每一个源文件转化为三个骰子图片文件。这一部分很重要。
大致流程应该是,读取文件夹所有文件列表,依次读取每一个文件,截取骰钟部分的图片,将文件转换为灰度图,转换为黑白图,去除环境噪点,分别获取三个骰子图,保存。
matlab代码如下,详细请看注解,我写的很详细的。
%% 原始图片生成训练数据
filepath='E:\charrrrrles\diceRecogniation\S01\'; %%原始图片文件的文件夹路径
dirOutput=dir(fullfile(filepath,'*.jpg'));%%读取文件夹
num_temp1=length(dirOutput);%%我们有多少个文件呢?
for i1=1:num_temp1%%遍历每一个文件 进行处理 保存到'E:\charrrrrles\diceRecogniation\S01ext\'
%% 三个参数 第一个是原始文件名字 第二个是文件夹路径 第三个是输出文件夹
imageExtAndSave(dirOutput(i1).name,filepath,'E:\charrrrrles\diceRecogniation\S01ext\')
end imageExtAndSave 函数里面有具体的图片处理流程,如下:
%%图片处理函数
function yes = imageExtAndSave(filename,path,savePath)
i=imread([path,filename]);%%读取这个图片文件
I=rgb2gray(i);%%转换为灰度图
BW=im2bw(I);% 转换为二值黑白图
I2 = imcrop(BW,[500 210 300 1000]);%大部分图像布局固定,图像大小一致 所以我们只需要大概500,210 300,1000这个区域的数据
I2 = bwareaopen(I2,200,8);%P=200删除二值图像BW中面积小于P的对象,默认情况下使用8邻域。 这个函数很重要,他在我们上面的二值图中找到面积小于200的信号,删除,剩下的就是我们要的骰子的数据了
cc = bwconncomp(I2,8);%bwconnecomp()是找出二值图像中连通的区域, CC返回结果,比如这样一幅图(简化便于理解):
n=cc.NumObjects;%有多少个对象 如果处理的好,我们一定有三个对象,因为我们有三个骰子
Area =zeros(n,1);%我们有n个对象 的区域
Perimeter = zeros(n,1);
MajorAxis = zeros(n,1);
MinorAxis = zeros(n,1);
k = regionprops(cc,'Area','Perimeter','MajorAxisLength','MinorAxisLength','Image');%用途是get the properties of region,即用来度量图像区域属性的函数。
for i =1:n
Image = k(i).Image;%获取到第i个骰子的数据
imwrite(Image,[savePath,filename,'-',num2str(i),'.jpg']);%保存到输出文件夹
end
yes=true;
至此,我们的图片就处理好了。
有了处理之后的数据,我们需要对这些数据进行命名,我的规则是文件名为点数(第几个样本).jpg 我每个点数准备100个数据,一共600个数据。然后1-50 给训练使用,剩下的给测试使用,其实应该是622分配,但是简单起见,就55分。
然后是再次均一化数据,训练神经网络
%% 本软件是用来学习神经网络的
close all;clear all;
train_dir=dir('train/*.jpg');%训练的文件夹 下面获取训练的文件列表
for i = 1: length(train_dir)
imgs_name{i} = train_dir(i).name;
end
imgs_sample = cell(299);%样本100个 100*100
imgs_sample_num = zeros(1,6);%10长度的向量 因为只有10个数字
max_size = [0 0];% 这些样本中最大的长和宽
%% 将数字分类放置
for i = 1 : length(imgs_name)%每一张图
img_name = imgs_name{i};%取出名字img_name 例如1(2)
imgs = im2bw(imread(['train/',img_name]));%读取图片
tmp_num = str2num(img_name(1)) ;%2
imgs_sample_num(tmp_num) = imgs_sample_num(tmp_num) + 1;
imgs_sample{tmp_num, imgs_sample_num(tmp_num)} = imgs;
tmp_size = size(imgs);
if max_size(1,1) < tmp_size(1,1); max_size(1,1) = tmp_size(1,1); end%找最大的 宽度
if max_size(1,2) < tmp_size(1,2); max_size(1,2) = tmp_size(1,2); end%找最大的 长度
end
%% 归一化所有样本,使其等大小
for i = 1 : 6% 对于这10类图像对象 例如数字0
for j = 1 : imgs_sample_num(i) %取其中一类 然后 便利这一类里面多有的对象
temp = zeros(max_size);%[0 0] 例如max_size 是[32,30]
imgs_size = size(imgs_sample{i, j});% 0 这一类的一张图
temp(1:imgs_size(1,1), 1:imgs_size(1,2)) = imgs_sample{i, j};%映射到最大的
imgs_sample{i, j} = temp;
% figure;
% imshow(temp);
end
end
%bp网络
runbp(imgs_sample, imgs_sample_num, max_size);runbp函数中运行了两个重要的函数,一个是buildtrainset 建立训练数据,一个是bpann 建立神经网络模型
buildtrainset如下:
% 创建数据集
%% buildtrainset: 用来创建神经网络适合的训练集
%% 传入的参数是 均一化之后的图像 就是十组数组,一组里面又有很多图像对象
%% 以及imgs_sample_num 每一类图片里面的数据的数量
function [inputs outputs] = buildtrainset(imgs, number)
i = 1;
for k = 1 : 6%1到10 这是个数字 依次取出来 例如1 其实就是数字0
for j = 1 : number(k)% 取到0 这个数字的对象 然后遍历所有的图像对象
input = imgs{k, j};%取到一个 是一个二维矩阵图像
input_size = numel(input);%有多少size
%% reshape 这里很重要,二维矩阵被转化为一维的向量
inputs(i, 1:input_size) = reshape(input', [input_size, 1]);
outputs(i, :) = zeros(6, 1);%%输出就是10个位数 也就是这个图片的输出 初始化为0
outputs(i, k) = 1;%% 然后因为这个图片是多少?是k所以在k位置标记为1
i = i + 1;
end
end
endbpann如下:
%% 首先使用bp神经网络,输入是图片,中间隐藏节点两层40个 20 节点,输出节点6个 对于6个点数
%% 利用BP网络识别验证码, 自适应学习率bp算法
function y = bpann(input, output)
%创建神经网络模型 第一个是输入 第二个是神经元的数量 然后分别是每层的激活函数 一个是逻辑 一个是普林
net = newff( minmax(input) , [40 20 6] , { 'logsig' 'logsig' 'logsig' } , 'traingdx' );
%训练的参数
net.trainparam.show = 50 ;
net.trainparam.epochs = 2000 ;
net.trainparam.goal = 0.01 ;
net.trainParam.lr = 0.01 ;
fprintf('----------train size-------------------')
size(input)
size(output)
fprintf('-----------------------------')
%训练 得到模型
y = train( net, input , output ) ;
end
runbp如下:
function y = runbp(imgs_sample, imgs_sample_num, max_size)
% bp 网络训练 输入图像对象 以及大小数据
% 输出的是a input b output 用于接下来的训练
[a, b] = buildtrainset(imgs_sample, imgs_sample_num);
%创建网络模型 训练
net = bpann(a', b');
save net;
% bp 测试 读取测试数据文件夹
image_dir=dir('test/*.jpg');
for i = 1: length(image_dir)
imgs_test{i} = image_dir(i).name;%文件名
end
rightnum = 0;%正确个数
sumnum = 0;%总共样本
%% 均一化,测试样本还是要和训练样本一样 有相同的大小和size
for i = 1 : length(imgs_test)
img_name = imgs_test{i};
imgs = im2bw(imread(['test/',img_name]));%读取文件 并且拆分处理
tmp_num = str2num(img_name(1)) ;%
%% 等大小化
temp = zeros(max_size);
imgs_size = size(imgs);
temp(1:imgs_size(1,1), 1:imgs_size(1,2)) = imgs;%文件的拉伸压缩,等大小
imgs = temp;
input_size = numel(temp);%有多少数据?
testInput(1, 1:input_size) = reshape(temp', input_size, 1);%按照这个数据的大小转化为一维向量
%第二步 仿真
Y = sim( net , testInput' );%仿真测试输入的是一张图片的四个数字对象 输出的是矩阵 10*4 识别的结果
%第三部 计算误差
mans = 0;%存放结果
ymax = 0;
yans = NaN;
for k = 1 : 6% 找到最大的是哪一个k 这个数字就是那个
if (ymax < Y(k, 1))
ymax = Y(k, 1);
yans = k;
end
end
mans = yans;% 还原的时候要减一 因为之前是假意加一
sumnum = sumnum + 1;
if (mans == str2num(img_name(1)))% 如果是正确的 计数
rightnum = rightnum + 1;
end
img_name
mans
end
rightdata = [rightnum, sumnum-rightnum]
rightnum/sumnum
pie(rightdata, {'right', 'wrong'});
end
仿真测试
runbp后半部分是模型仿真测试。需要指出的是,测试数据也要和训练数据维度大小一致。最后我们得到识别率,大致都是80%左右的样子,可以看出,我设计的这个流程和算法还是比较可以的。
在最后,我们利用训练出来的模型,输入原始的图片,经过图片处理,模型识别,得到点数,快来验证一下吧,感受一下快感:
RecognizeDice.m
load('net.mat');
filepath=input('请输入要识别的文件','s');
i=imread(filepath);
figure(9)
imshow(i);
I=rgb2gray(i);
BW=im2bw(I);
I2 = imcrop(BW,[500 210 300 1000]);%大部分图像布局固定
I2 = bwareaopen(I2,200,8);%删除二值图像BW中面积小于P的对象,默认情况下使用8邻域。
cc = bwconncomp(I2,8);%bwconnecomp()是找出二值图像中连通的区域, CC返回结果,比如这样一幅图(简化便于理解):
n=cc.NumObjects;%有多少个对象
Area =zeros(n,1);%我们有n个对象 的区域
Perimeter = zeros(n,1);
MajorAxis = zeros(n,1);
MinorAxis = zeros(n,1);
k = regionprops(cc,'Area','Perimeter','MajorAxisLength','MinorAxisLength','Image');%用途是get the properties of region,即用来度量图像区域属性的函数。
mean =zeros(3:1);
for i =1:n
Image = k(i).Image;
figure(i)
imshow(Image);
end
if n==3
for i =1:n
Image = k(i).Image;
mean(i)= mySim(Image,max_size,net);
end
else
fprintf('----------The Image Can not Split into 3 -------------------')
return
end
fprintf('----------The Dice Point is -------------------')
mean
输入原始图片的路径,我们看到控制台输出了点数,哦,是对的哦,神经网络就是这么牛。
总结
由此可见,神经网络的识别率和效率,以及能力。他可以在文字识别,语音识别,情感识别等起到很重要的作用,特别是大数据情况下,训练数据丰富,而且可以反馈,必定可以不断提高他的识别率。
Charles 于P.P 2016-12-25
今日考研结束,祝小迪考上心仪的大学研究院。
posted on 2016-12-25 23:03 MrCharles在cnblogs 阅读(863) 评论(0) 收藏 举报
浙公网安备 33010602011771号