1.SVM理解

SVM按照百度百科的解释,他属于一种监督分类的方法,对数据进行二元分类,分类的标准就是决策边界。

看下面的图片就很容易能够理解。如果说要给红点和蓝点分类的话,以绿线作为分界线,那么找到一个最合适的绿线就是问题的关键。下面图的右边是找到的结果,它刚好在两边点的中间。这个时候,绿线就叫做最优超平面(决策边界),它和两边最近的点的距离叫做最大距离叫做边距。

上面两张图的分类结果很明确,他们很明显可以用一条直线分开,这种叫做线形可分数据,但是现实生活中的点并不一定是刚好摆在一条线两边的。也有的会很乱,例如下面这种,它被称为非线形可分数据,下面分别进行讨论。

1.1线形可分数据

线形可分数据是SVM其他分类方法的基础,因为非线性可分数据也要转化为线形可分数据进行分类。方法如下:

还是拿下面这个图片作为举例:

①为了减轻工作量,我们不需要选择全部的点参与运算,在这个例子种,我们只选取实心点,也就是下图中的一个蓝色圆形和两个红色方形。

②我们把选好的蓝色圆形和两个红色方形称作支持向量。

③我们把选好的蓝色圆形和两个红色方形所在的绿色虚线称为支持平面。

④我们分别给红色和蓝色找一个绿色虚线,并且需要保证这两天虚线中间的距离尽可能大,如果有部分点偏离了直线划分的范围,我们要根据数据的整体情况决定是改变直线位置还是放弃一小部分点,保证两虚线距离足够大,被放弃的点可以理解为偏差。(本身有个公式,但是我确实没怎么理解,就不放了)

1.2非线形可分数据

对于非线形可分数据,例如一组数据是[-2,2],另一组是[-1,1],他们都是在X轴上面的点,按照但缺不能用X轴上的一个点把他们区分开来,但是如果我们把他们都用下(x,x^2)函数变化一下,前面的变成[(-2,4),(2,4)],后面的变成[(-1,1),(1,1)],这组新点却是很容易能被一个二维直线分开的。

该方法可以类比到高维数据,因此低维非线性可分数据在转化为高维数据后,是有可能被线形可分的。

具体计算会依赖一个理论:高维数据的特征可以从低维数据的点积得到,但是这里面的计算方法太复杂了,好在Open-CV里面的函数已经解决了这些问题,这里只是简单的从定性的角度理解了一下。

2.SVN手写字体识别代码

2.1数据准备

使用SVM训练图片样本,最关键的,首先要有训练样本,之后还要有检验样本。他们又分别包含了图片集和对应的结果,下面的示意更便于理解

训练样本:(图片,对应数字)

检验样本:(图片,对应数字)

下面代码使用的数据与上一个文章的数据一样,想要试练的可以直接去下载(也可以右键另存下面的图片)。Open-CV K近邻算法(k-Nearest Neighbour)OCR手写识别_Matrix_CS的博客-CSDN博客

2.2代码解析

首先介绍两个函数:①手写体矫正,②样本HOG生成函数(类似于直方图)

函数一代码如下,输入是一个图片,输出也是图片,但是它的形状被矫正了,例如=>

## 这个函数用来给手写体做一个变形,变成正体
def deskew(img):m = cv.moments(img)if abs(m['mu02']) < 1e-2:return img.copy()skew = m['mu11']/m['mu02']M = np.float32([[1, skew, -0.5*SZ*skew], [0, 1, 0]])img = cv.warpAffine(img,M,(SZ, SZ),flags=affine_flags)return img

函数二代码如下,它生成了图片的HOG图,用来作为SVM的输入。

## 这个函数把图片分成四部分,分别成生成方向直方图,然后返回,用来作为SVM的输入
#这和K近邻算法是不一样的
def hog(img):gx = cv.Sobel(img, cv.CV_32F, 1, 0)gy = cv.Sobel(img, cv.CV_32F, 0, 1)mag, ang = cv.cartToPolar(gx, gy)bins = np.int32(bin_n*ang/(2*np.pi))    # quantizing binvalues in (0...16)bin_cells = bins[:10,:10], bins[10:,:10], bins[:10,10:], bins[10:,10:]mag_cells = mag[:10,:10], mag[10:,:10], mag[:10,10:], mag[10:,10:]hists = [np.bincount(b.ravel(), m.ravel(), bin_n) for b, m in zip(bin_cells, mag_cells)]hist = np.hstack(hists)     # hist is a 64 bit vectorreturn hist

下面进行完成的代码解析:

①读取数据:

#样本读取
img = cv.imread(cv.samples.findFile('digits.png'),0)
if img is None:raise Exception("we need the digits.png image from samples/data here !")

②把上面那个密密麻麻的图片分割成单独数字的小块,之后分成左右两部分,左边作为训练样本,右边作为检验样本

#把整张图片分成单独的图片,原数据是50行,100列
cells = [np.hsplit(row,100) for row in np.vsplit(img,50)]
# 左边为训练样本,右边为检验样本
train_cells = [ i[:50] for i in cells ]
test_cells = [ i[50:] for i in cells]

③对训练样本进行一些处理,生成训练输入数据

#使用deskew函数,把倾斜的字体矫正
deskewed = [list(map(deskew,row)) for row in train_cells]
#生成图像的HOG图
hogdata = [list(map(hog,row)) for row in deskewed]
#序列化,变成输入数据
trainData = np.float32(hogdata).reshape(-1,64)
#把与图片对应的数字生成出来
responses = np.repeat(np.arange(10),250)[:,np.newaxis]

④初始化SVM,设置训练参数

#实例化对象
svm = cv.ml.SVM_create()
#设置核函数
svm.setKernel(cv.ml.SVM_LINEAR)
#设置训练类型
svm.setType(cv.ml.SVM_C_SVC)
svm.setC(2.67)
svm.setGamma(5.383)

⑤输入样本,开始训练

#输入样本,进行训练
svm.train(trainData, cv.ml.ROW_SAMPLE, responses)
#存储训练结果
svm.save('svm_data.dat')

到这里,训练工作就结束了,下面开始检验训练精度,这里用到了svm.predict()函数

#对检验样本的手写体进行矫正
deskewed = [list(map(deskew,row)) for row in test_cells]
#生成检验样本的HOG图
hogdata = [list(map(hog,row)) for row in deskewed]
#检验样本序列化
testData = np.float32(hogdata).reshape(-1,bin_n*4)
#生成识别结果
result = svm.predict(testData)[1]

下面计算匹配度:

mask = result==responses
correct = np.count_nonzero(mask)
print(correct*100.0/result.size)

最终运行可以得到下面的结果,精度为93.8:

完整代码如下:

import cv2 as cv
import numpy as npSZ=20
bin_n = 16 # Number of binsaffine_flags = cv.WARP_INVERSE_MAP|cv.INTER_LINEAR## 这个函数用来给手写体做一个变形,变成正体
def deskew(img):m = cv.moments(img)if abs(m['mu02']) < 1e-2:return img.copy()skew = m['mu11']/m['mu02']M = np.float32([[1, skew, -0.5*SZ*skew], [0, 1, 0]])img = cv.warpAffine(img,M,(SZ, SZ),flags=affine_flags)return img
## [deskew]## 这个函数把图片分成四部分,分别成生成方向直方图,然后返回,用来作为SVM的输入,这点可K近邻算法是不一样的
def hog(img):gx = cv.Sobel(img, cv.CV_32F, 1, 0)gy = cv.Sobel(img, cv.CV_32F, 0, 1)mag, ang = cv.cartToPolar(gx, gy)bins = np.int32(bin_n*ang/(2*np.pi))    # quantizing binvalues in (0...16)bin_cells = bins[:10,:10], bins[10:,:10], bins[:10,10:], bins[10:,10:]mag_cells = mag[:10,:10], mag[10:,:10], mag[:10,10:], mag[10:,10:]hists = [np.bincount(b.ravel(), m.ravel(), bin_n) for b, m in zip(bin_cells, mag_cells)]hist = np.hstack(hists)     # hist is a 64 bit vectorreturn hist
## [hog]#样本读取
img = cv.imread(cv.samples.findFile('digits.png'),0)
if img is None:raise Exception("we need the digits.png image from samples/data here !")#把整张图片分成单独的图片,原数据是50行,100列
cells = [np.hsplit(row,100) for row in np.vsplit(img,50)]
# First half is trainData, remaining is testData
train_cells = [ i[:50] for i in cells ]
test_cells = [ i[50:] for i in cells]######     Now training      #########################使用deskew函数,把倾斜的字体矫正
deskewed = [list(map(deskew,row)) for row in train_cells]
#生成图像的HOG图
hogdata = [list(map(hog,row)) for row in deskewed]
#序列化,变成输入数据
trainData = np.float32(hogdata).reshape(-1,64)
#把与图片对应的数字生成出来
responses = np.repeat(np.arange(10),250)[:,np.newaxis]#实例化对象
svm = cv.ml.SVM_create()
#设置核函数
svm.setKernel(cv.ml.SVM_LINEAR)
#设置训练类型
svm.setType(cv.ml.SVM_C_SVC)
svm.setC(2.67)
svm.setGamma(5.383)#输入样本,进行训练
svm.train(trainData, cv.ml.ROW_SAMPLE, responses)
#存储训练结果
svm.save('svm_data.dat')######     Now testing      #########################对检验样本的手写体进行矫正
deskewed = [list(map(deskew,row)) for row in test_cells]
#生成检验样本的HOG图
hogdata = [list(map(hog,row)) for row in deskewed]
#检验样本序列化
testData = np.float32(hogdata).reshape(-1,bin_n*4)
#生成识别结果
result = svm.predict(testData)[1]#######   Check Accuracy   ########################
mask = result==responses
correct = np.count_nonzero(mask)
print(correct*100.0/result.size)

OpenCV-python:SVM(支持向量机)OCR手写识别相关推荐

  1. python手写板,机器语言之手写识别_源码时代Python公开课|Python培训

    课程介绍 当我们在手写设备(例如我们输入法中的手写模式),使用手写的文字,我们计算机是如何快速准确的识别出来的?每个人,甚至是同一个人,每次手写的字都不是完全一样,计算机不是人,它是怎么做到的呢?难道 ...

  2. OpenCV系列之使用OCR手写数据集运行SVM | 五十六

    目标 在本章中,我们将重新识别手写数据集,但是使用SVM而不是kNN. 识别手写数字 在kNN中,我们直接使用像素强度作为特征向量.这次我们将使用定向梯度直方图(HOG)作为特征向量. 在这里,在找到 ...

  3. OpenCV系列之使用OCR手写数据集运行KNN | 五十四

    目标 在本章中 我们将使用我们在kNN上的知识来构建基本的OCR应用程序. 我们将尝试使用OpenCV自带的数字和字母数据集. 手写数字的OCR 我们的目标是构建一个可以读取手写数字的应用程序.为此, ...

  4. 机器学习实战(6):SVM-SMO-核函数 手写识别

    SVM判断模型只与支持向量有关: # coding=utf-8 #Created on Nov 4, 2010 #Chapter 5 source file for Machine Learing i ...

  5. Python,OpenCV使用KNN来构建手写数字及字母识别OCR

    Python,OpenCV使用KNN来构建手写数字及字母识别OCR 1. 原理 1.1 手写数字识别 1.2 字母识别 2. 源码 2.1 手写数字OCR 2.2 字母OCR 参考 这篇博客将介绍如何 ...

  6. 前馈神经网络与支持向量机实战 --- 手写数字识别

    前馈神经网络与支持向量机实战 - 手写数字识别 文章目录 前馈神经网络与支持向量机实战 --- 手写数字识别 一.前馈神经网络介绍 二.支持向量机介绍 三.数据集说明 四.环境准备 五.实验要求 六. ...

  7. 基于SVM技术的手写数字识别

    老师常说,在人工智能未发展起来之前,SVM技术是一统江湖的,SVM常常听到,但究竟是什么呢?最近研究了一下基于SVM技术的手写数字识别.你没有看错,又是手写数字识别,就是喜欢这个手写数字识别,没办法( ...

  8. OpenCV SVM支持向量机和KNearest数字识别的实例(附完整代码)

    OpenCV SVM支持向量机和KNearest数字识别的实例 OpenCV SVM支持向量机和KNearest数字识别的实例 OpenCV SVM支持向量机和KNearest数字识别的实例 #inc ...

  9. python与机械教育初探_Python公开课-机械学习之手写识别

    授课讲师 讲师尹强 职务高级讲师.项目经理 多年互联网开发经验与授课经验,曾参与某知名家具电商网站.车友商城.物流系统的开发设计,善于使用多种技术解决技术问题和优化网站的性能和提高网站速度,开发经验丰 ...

最新文章

  1. 建设公司的技术+企业客户的沟通=极致运行的网站
  2. java 装配_Spring 通过Java代码装配bean
  3. MATLAB图像生成函数Plot()总结
  4. 利用正则表达式 替换字符串中多个 URL
  5. 使用javascript的“委托”实现attachEvent
  6. win10 Python3安装pysqlcipher3的问题总结
  7. 锐捷云教室 服务器型号,锐捷智慧云课堂方案(云教室+简单)优秀课件
  8. c语言.jpg图片转成数组_JPG图片怎么转换成PDF?可以试试这些转换方法!
  9. 几何造型问题(转载)
  10. 520 钻石争霸赛 7-2 真的恭喜你 (10分)
  11. OpenGL(十四)——Qt OpenGL纹理
  12. css3 3d头像,Three.js 3D头像
  13. Python实现BOA蝴蝶优化算法优化支持向量机分类模型(SVC算法)项目实战
  14. 每个程序员都应该了解的 CPU 高速缓存
  15. c语言入门:比较三个数的大小
  16. Introduction to Python(2)
  17. 威廉指标WR计算公式
  18. Linux 批量修改文件名(前缀或后缀)
  19. [小说]魔王冢(17)鬼金羊
  20. oracle 去摸_Suphx论文翻译(一)

热门文章

  1. 物盟安防监控解决方案
  2. 【调剂】其它计算机/软件调剂信息 21.3.1
  3. VeryCD倒下还有千千万万个“VeryCD”站起来
  4. linux云计算基础(云计算的介绍)
  5. mysql+jdbc连接数据库简单实现登录功能 --java
  6. 从4D到成像 | 4D毫米波雷达技术的发展
  7. Docker安装、加速器
  8. PhotoShop 2023 ai beta下载安装教程
  9. 菜鸟[1]_链表(C语言)
  10. “10类”电子劳动合同签署工具:节约时间、高效签署