利用卷积神经网络识别骰子点数.docx
- 文档编号:10779889
- 上传时间:2023-02-22
- 格式:DOCX
- 页数:16
- 大小:704.67KB
利用卷积神经网络识别骰子点数.docx
《利用卷积神经网络识别骰子点数.docx》由会员分享,可在线阅读,更多相关《利用卷积神经网络识别骰子点数.docx(16页珍藏版)》请在冰豆网上搜索。
利用卷积神经网络识别骰子点数
利用卷积神经网络识别骰子点数
线性滤波和卷积的基本概念
线性滤波可以说是图像处理最基本的方法,它可以允许我们对图像进行处理,产生很多不同的效果。
做法很简单。
首先,我们有一个二维的滤波器矩阵(有个高大上的名字叫卷积核)和一个要处理的二维图像。
然后,对于图像的每一个像素点,计算它的邻域像素和滤波器矩阵的对应元素的乘积,然后加起来,作为该像素位置的值。
这样就完成了滤波过程。
对图像和滤波矩阵进行逐个元素相乘再求和的操作就相当于将一个二维的函数移动到另一个二维函数的所有位置,这个操作就叫卷积或者协相关。
卷积和协相关的差别是,卷积需要先对滤波矩阵进行180的翻转,但如果矩阵是对称的,那么两者就没有什么差别了。
上面这张图和这段话如果你还是想象不出怎么在一张图片上做卷积操作的话,我有下面的动态图:
下面是一个3×3的卷积核在5×5的图像上做卷积的过程。
每个卷积都是一种特征提取方式,就像一个筛子,将图像中符合条件(激活值越大越符合条件)的部分筛选出来。
所以,由4个通道卷积得到2个通道的过程中,参数的数目为4×2×2×2个,其中4表示4个通道,第一个2表示生成2个通道,最后的2×2表示卷积核大小。
如果初看此图,可能不一定能立马理解啥意思,但结合上文的内容后,理解这个动图已经不是很困难的事情:
左边是输入(7*7*3中,7*7代表图像的像素/长宽,3代表R、G、B三个颜色通道)
中间部分是两个不同的滤波器Filterw0、Filterw1
最右边则是两个不同的输出
随着左边数据窗口的平移滑动,滤波器Filterw0/Filterw1对不同的局部数据进行卷积计算。
值得一提的是:
左边数据在变化,每次滤波器都是针对某一局部的数据窗口进行卷积,这就是所谓的CNN中的局部感知机制。
打个比方,滤波器就像一双眼睛,人类视角有限,一眼望去,只能看到这世界的局部。
如果一眼就看到全世界,你会累死,而且一下子接受全世界所有信息,你大脑接收不过来。
当然,即便是看局部,针对局部里的信息人类双眼也是有偏重、偏好的。
比如看美女,对脸、胸、腿是重点关注,所以这3个输入的权重相对较大。
与此同时,数据窗口滑动,导致输入在变化,但中间滤波器Filterw0的权重(即每个神经元连接数据窗口的权重)是固定不变的,这个权重不变即所谓的CNN中的参数(权重)共享机制。
再打个比方,某人环游全世界,所看到的信息在变,但采集信息的双眼不变。
btw,不同人的双眼看同一个局部信息所感受到的不同,即一千个读者有一千个哈姆雷特,所以不同的滤波器就像不同的双眼,不同的人有着不同的反馈结果。
我第一次看到上面这个动态图的时候,只觉得很炫,另外就是据说计算过程是“相乘后相加”,但到底具体是个怎么相乘后相加的计算过程则无法一眼看出,网上也没有一目了然的计算过程。
本文来细究下。
首先,我们来分解下上述动图,如下图
扯了这么多,来点实际的,卷积对于神经网络究竟有什么好处呢?
如果你看了上面所有的计算过程,我们可以发现至少两个好处,一个是卷积降低了数据数量,可以说是抽提了数据,数据变得少,如果不使用卷积,我们普通的bpnn需要处理的数据将是非常巨大的。
stdcoutzyx在博客中有过计算,你可以仔细看一下。
卷积神经网络的另一个核心思想是:
局部感受野(localfield),权值共享以及时间或空间亚采样这三种思想结合起来,获得了某种程度的位移、尺度、形变不变性。
说起来很炫吧,但是我也不知道如何解释,你可以参看此处。
Talkischeap,showmethecode.话不多说,直接上代码。
trainCNN.m
[java]viewplaincopy在CODE上查看代码片派生到我的代码片
Arial;color: #333333;">%%CNN closeall;clearall; train_dir=dir('train/*.jpg');%训练的文件夹下面获取训练的文件列表 fori=1: length(train_dir) imgs_name{i}=train_dir(i).name; end imgs_sample=cell(6);%样本分组我们六个点数分成六组一组多少个样品就有多少数组按照最多的那一组确定最大维度 imgs_sample_num=zeros(1,6);%6组数据,保存每一组数据最多多少个样本例如[79,79,79,79,79,79]表示第一组79样本第二组79.... max_size=[00];%这些样本中最大的长和宽 %%将数字分类放置 fori=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));%读取点数 imgs_sample_num(tmp_num)=imgs_sample_num(tmp_num)+1;%在这一组里面样本的下标加1 imgs_sample{tmp_num,imgs_sample_num(tmp_num)}=imgs;%将这个样本保存到imgs_sample第一维是点数第二维是样本的下标 tmp_size=size(imgs);%样本图片的大小下面两行分别获取图片的最大长和宽 ifmax_size(1,1) ifmax_size(1,2) end max_size=[2440];%这些样本中最大的长和宽 %%归一化所有样本,使其等大小 fori=1: 6%对于这6类图像对象例如数字0 forj=1: imgs_sample_num(i)%取其中一类然后遍历这一类里面多有的对象 temp=zeros(max_size);%[00]例如max_size是[32,30] imgs_size=e(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; %imshow(temp); end end %cnn网络 runcnn(imgs_sample,imgs_sample_num,max_size); runcnn.m [java]viewplaincopy在CODE上查看代码片派生到我的代码片 Arial;color: #333333;"> %%CNN训练的主要步骤 functiony=runcnn(imgs_sample,imgs_sample_num,max_size) path(path,'DeepLearnToolbox-master/CNN/') path(path,'DeepLearnToolbox-master/util/') %网络训练集构造 [a,b]=buildtrainset_cnn(imgs_sample,imgs_sample_num); %24×40的原图片 cnn.layers={ struct('type','i')%inputlayer struct('type','c','outputmaps',6,'kernelsize',5)%convolutionlayeroutputmaps6个特征图输出卷积大小是5*5 struct('type','s','scale',2)%subsamplinglayermaxpooling层2*2 struct('type','c','outputmaps',12,'kernelsize',5)%convolutionlayer struct('type','s','scale',2)%subsamplinglayer }; cnn=cnnsetup(cnn,a,b); %学习率 opts.alpha=2; %每次挑出一个batchsize的batch来训练,也就是每用batchsize个样本就调整一次权值,而不是 %把所有样本都输入了,计算所有样本的误差了才调整一次权值 opts.batchsize=size(a,3); %训练次数,用同样的样本集。 我训练的时候: %1002005002000都没有效果错误率834000的时候效果明显错误率7 opts.numepochs=4000; %训练模型 cnn=cnntrain(cnn,a,b,opts); %保存模型,为以后识别程序 savecnn; %测试 image_dir=dir('test/*.jpg'); fori=1: length(image_dir) str_name=image_dir(i).name; imgs_test{i}=str_name; end rightnum=0;%正确个数 sumnum=0;%总共样本 fori=1: length(imgs_test) sumnum=sumnum+1; 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=size(temp); testInput(: : 1)=reshape(temp',input_size(1,1),input_size(1,2)); testInput(: : 2)=reshape(temp',input_size(1,1),input_size(1,2)); %然后就用测试样本来测试 cnn=cnnff(cnn,testInput); cnn.o [~,mans]=max(cnn.o); ifmans(1,1)==tmp_num rightnum=rightnum+1; end %img_name %mans=mans end rightdata=[rightnum,sumnum-rightnum] rightnum/sumnum figure(88) pie(rightdata,{'right','wrong'}); %plotmeansquarederror figure(89) plot(cnn.rL); end buildtrainset_cnn.m [html]viewplaincopy在CODE上查看代码片派生到我的代码片 Arial;color: #333333;">%创建数据集 function[inputsoutputs]=buildtrainset_cnn(imgs,number) i=1; fork=1: 6 forj=1: number(k) input=imgs{k,j}; input_size=size(input); inputs(: : i)=reshape(input',input_size(1,1),input_size(1,2));%这里的操作转置矩阵作为输入 outputs(: i)=zeros(6,1); outputs(k,i)=1; i=i+1; end end end 值得指出的是,cnn训练的时间比较久,而且最开始被他欺骗了,请看我上面代码的注释,如果只是训练100次或者500次,甚至2000次都不能够让我的模型有作用,我也是一直怀疑是不是我哪里的数据处理错了,或者哪个矩阵弄反了,又回过头仔细琢磨验证码识别的那个代码,以及DeepLearnToolbox的范例代码,还是觉得没有问题啊,果断决定将训练次数提升到4000次,这时候奇迹出现了,误差曲线在3500的时候下降到差不多3的样子,应该是我的数据比较大的问题吧。 4000次训练在我机器上需要1个多小时,还是比较耗时的。 验证 RecognizeDiceCnn.m [html]viewplaincopy在CODE上查看代码片派生到我的代码片 load('cnn.mat'); max_size=[2440];%这些样本中最大的长和宽 filepath=input('请输入要识别的文件','s'); i=imread(filepath); figure(9) imshow(i); I=rgb2gray(i); BW=im2bw(I); I2=imcrop(BW,[4002103001000]);%大部分图像布局固定 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');%用途是gettheesofregion,即用来度量图像区域属性的函数。 mean=zeros(6: 3); imgs={}; fori=1: n Image=k(i).Image; figure(i) imshow(Image); end ifn==3 load('cnn.mat'); %测试 image_dir=dir('test/*.jpg'); fori=1: length(image_dir) str_name=image_dir(i).name; imgs_test{i}=str_name; end fori=1: 3 imgs=k(i).Image;%读取图片 %%等大小化 temp=zeros(max_size); imgs_size=size(imgs); temp(1: imgs_size(1,1),1: imgs_size(1,2))=imgs; imgs=temp; input_size=size(temp); testInputs(: : i)=reshape(temp',input_size(1,1),input_size(1,2)); %然后就用测试样本来测试 %[~,a]=max(y); %bad=find(mans~=a); end cnn=cnnff(cnn,testInputs); cnn.o [~,mans]=max(cnn.o); fprintf('----------TheDicePointis-------------------') mans else fprintf('----------TheImageCannotSplitinto3-------------------') return end 总结 cnn貌似比bpnn正确率高那么一点点,也许是我调整了数据样本的缘故,总之可以通过此种方式实现识别这种功能,更新了我的世界观。
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 利用 卷积 神经网络 识别 骰子 点数
![提示](https://static.bdocx.com/images/bang_tan.gif)