OpenCV 3.0中的SVM训练 mnist 手写字体识别

SVM(支持向量机)一种训练分类器的学习方法

mnist 是一个手写字体图像数据库,训练样本有60000个,测试样本有10000个

LibSVM 一个常用的SVM框架

OpenCV3.0 中的ml包含了很多的ML框架接口,就试试了。

详细的OpenCV文档:

mnist数据下载:

LibSVM下载:~cjlin/libsvm/

========================我是分割线=============================

训练的过程大致如下:

1. 读取mnist训练集数据

2. 训练

3. 读取mnist测试数据,对比预测结果,得到错误率

具体实现:

1. mnist给出的数据文件是二进制文件

四个文件,解压后如下

  

OpenCV 3.0中的SVM训练 mnist 手写字体识别

 

  "train-images.idx3-ubyte" 二进制文件,存储了头文件信息以及60000张28*28图像pixel信息(用于训练)
  "train-labels.idx1-ubyte" 二进制文件,存储了头文件信息以及60000张图像label信息
  "t10k-images.idx3-ubyte"二进制文件,存储了头文件信息以及10000张28*28图像pixel信息(用于测试)
  "t10k-labels.idx1-ubyte"二进制文件,存储了头文件信息以及10000张图像label信息

  因为OpenCV中没有直接导入MINST数据的文件,所以需要自己写函数来读取

  首先要知道,MNIST数据的数据格式

  

OpenCV 3.0中的SVM训练 mnist 手写字体识别

   IMAGE FILE包含四个int型的头部数据(magic number,number_of_images, number_of_rows, number_of_columns)

余下的每一个byte表示一个pixel的数据,范围是0-255(可以在读入的时候scale到0~1的区间

LABEL FILE包含两个int型的头部数据(magic number, number of items)

余下的每一个byte表示一个label数据,范围是0-9

   注意(第一个坑):MNIST是大端存储,然而大部分的Intel处理器都是小端存储,所以对于int、long、float这些多字节的数据类型,就要一个一个byte地翻转过来,才能正确显示。

1 //翻转 2 int reverseInt(int i) { 3 unsigned char c1, c2, c3, c4; 4 5 c1 = i & 255; 6 c2 = (i >> 8) & 255; 7 c3 = (i >> 16) & 255; 8 c4 = (i >> 24) & 255; 9 10 return ((int)c1 << 24) + ((int)c2 << 16) + ((int)c3 << 8) + c4; 11 }

View Code

  然后读取MNIST文件,但是它是二进制文件,打开方式

  所以不能用

  ifstream file(fileName);

  而要改成

  ifstream file(fileName, ios::binary);

  注意(第二个坑):如果用第一条指令来打开文件,不会报错,但是数据会出现错误,头部数据仍然正确,但是后面的pixel数据大部分都是0,我刚开始没注意,开始training的时候发现等了很久...真的是很久...(7+ hours)...估计是达到迭代终止的最大次数了,才停下来的

  嗯,stack overflow上也有类似的提问:

  

OpenCV 3.0中的SVM训练 mnist 手写字体识别

  注意(第三个坑):

  training时,IMAGE和LABEL的数据分别都放进一个MAT中存储,但是只能是CV32_F或者CV32_S的格式,不然会assertion报错

  OPENCV给出的文档中,例子是这样的:(但是predict的时候又会要求label的格式是unsigned int)所以...可以设置data的Mat格式为CV_32FC1,label的Mat格式为CV_32SC1

  

OpenCV 3.0中的SVM训练 mnist 手写字体识别

  顺便地,图像训练数据的转换存储格式(?rq=1)

  

OpenCV 3.0中的SVM训练 mnist 手写字体识别

  最后,为了验证读取数据的正确性,一个有效的办法就是输出第一个和最后一个数据(可以输出答应第一个/最后一个image以及label)

2. 训练

  (此处我是直接对原图像训练,并没有提取任何的特征)

  也有人建议这里应该对图像做HOG特征提取,再配合label训练(我还没试过...不知道效果如何...)

  

OpenCV 3.0中的SVM训练 mnist 手写字体识别

  opencv3.0和2.4的SVM接口有不同,基本可以按照以下的格式来执行:

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/546444a28c3e5e56e941a035d61e2712.html