Python,OpenCV基于支持向量机SVM的手写数字OCR

  • 1. 效果图
  • 2. SVM及原理
  • 2. 源码
    • 2.1 SVM的手写数字OCR
    • 2.2 非线性SVM
  • 参考

上一节介绍了基于KNN的手写数字OCR+字母OCR,这一节将介绍基于支持向量机SVM的手写数字OCR。

1. 效果图

简单线性向量机训练效果图如下:
图中有4个点,3个趋于白色点,一个灰黑色点,可以看到分割线的决策边界很明显。

非线性向量机训练数据效果图如下:

下图中绿色、蓝色点杂糅在一起,中间的决策边界是非线性的,但可以近似为线性。边界有灰色圆圈的点是 支持向量,依赖这些少量的数据就可以找到 决策边界

2. SVM及原理

支持向量机SVM(Supported Vector Machines)

要了解SVM,首先需要了解线性可分数据及线性不可分数据,简单来说,就是在平面或多维有一堆点进行分类,能否用一根线分隔以分类彼此。

  • 线性可分数据

    KNN需要计算测试数据到所有点的距离,当数据量比较大的时候,需要较大的内存来存储。 可以有另一种思路:找到一条线 f(x)=ax_1+bx_2+c ,它将数据分为两个区域。当得到一个新的 test_data X 时,只需将其替换为 f(x)。如果 f(X) > 0,则属于蓝色组,否则属于红色组。

    称这条线为 决策边界,它非常简单且节省内存。 这种可以用直线(或更高维的超平面)一分为二的数据称为 线性可分数据

  • 低维空间中的非线性可分离数据在高维空间中变为线性可分离的可能性更大。

    在上图中可以看到很多这样的线条是可能的。要拿哪一个?非常直观,可以说这条线应该尽可能远离所有点。

走最远的线路将提供更多的抗噪能力。所以SVM所做的就是找到一条到训练样本最小距离最大的直线(或超平面)。

  • 要找到这个决策边界,并不需要所有数据,只需要那些靠近相反群体的数据。


在该图像中,它们是一个蓝色实心圆圈和两个红色实心方块。我们可以称它们为支持向量,穿过它们的线称为支持平面。它们足以找到决策边界

  • 权重向量决定决策边界的方向,而偏置点决定其位置。

2. 源码

2.1 SVM的手写数字OCR

# 使用SVM进行手写数据OCR# 在KNN中直接使用像素强度作为特征向量。
# 在SVM中使用方向梯度直方图(HOG Histogram of Oriented Gradients)作为特征向量。
# 在这里,使用二阶矩对图像进行反扭曲。
import cv2
import numpy as npSZ = 20
bin_n = 16  # Number of binssvm_params = dict(kernel_type=cv2.ml.SVM_LINEAR,svm_type=cv2.ml.SVM_C_SVC,C=2.67, gamma=5.383)affine_flags = cv2.WARP_INVERSE_MAP | cv2.INTER_LINEAR# 左图像是原始图像,右图像是倾斜图像。
def deskew(img):m = cv2.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 = cv2.warpAffine(img, M, (SZ, SZ), flags=affine_flags)return img# (HOG Histogram of Oriented Gradients)方向梯度直方图
def hog(img):gx = cv2.Sobel(img, cv2.CV_32F, 1, 0)gy = cv2.Sobel(img, cv2.CV_32F, 0, 1)mag, ang = cv2.cartToPolar(gx, gy)# 量化 (0...16)的binvaluesbins = np.int32(bin_n * ang / (2 * np.pi))# 分成四个子块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)return histimg = cv2.imread('images/digits.png', 0)
print(img.shape)  # (1000,2000)cells = [np.hsplit(row, 100) for row in np.vsplit(img, 50)]
print(len(cells))  # 50*100# 一半数据用于训练,一半用于测试(前50列,后50列)
train_cells = [i[:50] for i in cells]
test_cells = [i[50:] for i in cells]# cv2.imshow("img", train_cells[0][0])
# cv2.imshow("deskew", deskew(train_cells[0][0]))
# cv2.waitKey(0)# 训练数据
deskewed = [list(map(deskew, row)) for row in train_cells]
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]
print('trainData: ', type(trainData), len(trainData))
print('responses: ', type(responses), responses.shape, len(responses))print(responses[0])svm = cv2.ml.SVM_create()
svm.setGamma(svm_params['gamma'])
svm.setC(svm_params['C'])
svm.setKernel(cv2.ml.SVM_LINEAR)
svm.setType(cv2.ml.SVM_C_SVC)
svm.train(trainData, cv2.ml.ROW_SAMPLE, responses)# 把训练的数据及模型保存下来
svm.save('images/svm_data.dat')# 测试数据
deskewed = [list(map(deskew, row)) for row in test_cells]
hogdata = [list(map(hog, row)) for row in deskewed]
testData = np.float32(hogdata).reshape(-1, bin_n * 4)
result = svm.predict(testData)[1]print('result: ', type(result))
print('responses: ', type(responses))# 检查准确度
mask = result == responses
correct = np.count_nonzero(mask)
print('correct: ', correct)# SVM得到93.8%的准确度,比KNN的91.76%要高一些
print(correct * 100.0 / len(list(result)))

2.2 非线性SVM

from __future__ import print_functionimport random as rngimport cv2 as cv
import numpy as npNTRAINING_SAMPLES = 100  # Number of training samples per class
FRAC_LINEAR_SEP = 0.9  # Fraction of samples which compose the linear separable part# 可视化窗口大小
WIDTH = 512
HEIGHT = 512
I = np.zeros((HEIGHT, WIDTH, 3), dtype=np.uint8)# 随机生成训练数据
trainData = np.empty((2 * NTRAINING_SAMPLES, 2), dtype=np.float32)
labels = np.empty((2 * NTRAINING_SAMPLES, 1), dtype=np.int32)rng.seed(100)  # 随机生成分类标签# 为训练数据设置线性分离区
# Set up the linearly separable part of the training data
nLinearSamples = int(FRAC_LINEAR_SEP * NTRAINING_SAMPLES)# 为分类1生成随机点
trainClass = trainData[0:nLinearSamples, :]
# x在[0,0.4]
c = trainClass[:, 0:1]
c[:] = np.random.uniform(0.0, 0.4 * WIDTH, c.shape)
# y在[0, 1)
c = trainClass[:, 1:2]
c[:] = np.random.uniform(0.0, HEIGHT, c.shape)# 为分类2生成随机点
trainClass = trainData[2 * NTRAINING_SAMPLES - nLinearSamples:2 * NTRAINING_SAMPLES, :]
# x在 [0.6, 1]
c = trainClass[:, 0:1]
c[:] = np.random.uniform(0.6 * WIDTH, WIDTH, c.shape)
# y在 [0, 1)
c = trainClass[:, 1:2]
c[:] = np.random.uniform(0.0, HEIGHT, c.shape)# 为测试数据集的分类1,2分别生成随机点
trainClass = trainData[nLinearSamples:2 * NTRAINING_SAMPLES - nLinearSamples, :]
# x在[0.4,0.6]
c = trainClass[:, 0:1]
c[:] = np.random.uniform(0.4 * WIDTH, 0.6 * WIDTH, c.shape)
# y在[0,1]
c = trainClass[:, 1:2]
c[:] = np.random.uniform(0.0, HEIGHT, c.shape)# 设置分类标签1及2
labels[0:NTRAINING_SAMPLES, :] = 1  # 分类1
labels[NTRAINING_SAMPLES:2 * NTRAINING_SAMPLES, :] = 2  # 分类2# 开始训练,首先设置支持向量机SVM参数
print('Starting training process')
# 初始化
svm = cv.ml.SVM_create()
svm.setType(cv.ml.SVM_C_SVC)
svm.setC(0.1)
svm.setKernel(cv.ml.SVM_LINEAR)
svm.setTermCriteria((cv.TERM_CRITERIA_MAX_ITER, int(1e7), 1e-6))# 训练SVM
svm.train(trainData, cv.ml.ROW_SAMPLE, labels)# 结束训练
print('Finished training process')# 展示决策区域(绘制蓝色,绿色) 分类1为绿色,分类2为蓝色
green = (0, 100, 0)
blue = (100, 0, 0)
for i in range(I.shape[0]):for j in range(I.shape[1]):sampleMat = np.matrix([[j, i]], dtype=np.float32)response = svm.predict(sampleMat)[1]if response == 1:I[i, j] = greenelif response == 2:I[i, j] = blue# 展示测试数据
thick = -1# 分类1 绿色
for i in range(NTRAINING_SAMPLES):px = trainData[i, 0]py = trainData[i, 1]cv.circle(I, (px, py), 3, (0, 255, 0), thick)# 分类2 蓝色
for i in range(NTRAINING_SAMPLES, 2 * NTRAINING_SAMPLES):px = trainData[i, 0]py = trainData[i, 1]cv.circle(I, (px, py), 3, (255, 0, 0), thick)# 展示支持向量
thick = 2
sv = svm.getUncompressedSupportVectors()for i in range(sv.shape[0]):cv.circle(I, (sv[i, 0], sv[i, 1]), 6, (128, 128, 128), thick)cv.imwrite('non_linear_svms_result.png', I)  # 保存图片
cv.imshow('SVM for Non-Linear Training Data', I)  # 展示图片结果
cv.waitKey()

参考

  • https://docs.opencv.org/3.0-beta/doc/py_tutorials/py_ml/py_svm/py_svm_basics/py_svm_basics.html#svm-understanding

Python,OpenCV基于支持向量机SVM的手写数字OCR相关推荐

  1. 基于支持向量机的Digits手写数字识别

    基于支持向量机的Digits手写数字识别 描述 支持向量机(Support Vector Machine,简称SVM)模型既可以用于分类也可以用于回归.手写数字识别是一个多分类问题(判断一张手写数字图 ...

  2. 在OpenCV里使用SVM识别手写数字

    前面使用了kNN算法来识别手写数字,我们是直接把数字的灰度值大小作为特征值来学习.而这里要使用SVM算法,是否也可以使用灰度值来做呢?对于SVM算法来说,可能要采用另外一个特征方式,叫做梯度方向直方图 ...

  3. python实现基于KNN算法的手写数字识别系统 非常详细!!!!

    一家懂得用细节留住客户的3年潮牌老店我必须支持!➕

  4. python opencv数字识别_基于模板匹配的手写数字识别(python+opencv)

    智能计算课第一周的实验是做基于模板匹配的手写数字识别,光听见就很感兴趣,于是决定认真做做这个实验,本实验基于python3+opencv的python版本,所用到的知识都比较简单,基本上边学边做,技术 ...

  5. 基于深度学习的手写数字识别算法Python实现

    摘 要 深度学习是传统机器学习下的一个分支,得益于近些年来计算机硬件计算能力质的飞跃,使得深度学习成为了当下热门之一.手写数字识别更是深度学习入门的经典案例,学习和理解其背后的原理对于深度学习的理解有 ...

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

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

  7. 基于深度学习的手写数字识别、python实现

    基于深度学习的手写数字识别.python实现 一.what is 深度学习 二.加深层可以减少网络的参数数量 三.深度学习的手写数字识别 一.what is 深度学习 深度学习是加深了层的深度神经网络 ...

  8. python svm实现手写数字识别——直接可用

    python svm实现手写数字识别--直接可用 1.训练 1.1.训练数据集下载--已转化成csv文件 1.2 .训练源码 2.预测单张图片 2.1.待预测图像 2.2.预测源码 2.3.预测结果 ...

  9. Python基于深度学习的手写数字识别

    Python基于深度学习的手写数字识别 1.代码的功能和运行方法 2. 网络设计 3.训练方法 4.实验结果分析 5.结论 1.代码的功能和运行方法 代码可以实现任意数字0-9的识别,只需要将图片载入 ...

最新文章

  1. Oracle11g_同义词
  2. WEB前后端分离开发中的验证与安全问题
  3. Linux Shell常用技巧(三)
  4. 看人家如何拿到腾讯阿里的offer
  5. pythoncharm下载cpython失败_pycharm虚拟环境下安装mysqlclient失败
  6. Linux什么时候在pc机上有一席之地
  7. python工业自动化仿真_ABAQUS 中基于 Python 脚本语言开发实现仿真自动化操作
  8. java从键盘上录入任何整数,输出该整数的阶乘
  9. poj 1611 TheSuspects 并查集 连通图
  10. frameset的一些操作
  11. [USACO06JAN]牛的舞会---洛谷P2863
  12. python获取上周周一日期_python python日期算法 本周,上周,本月,上月,本季,上季,今年, 去年...
  13. win10文件后缀名怎么显示_Win10显示隐藏文件后系统根目录( C盘)文件及文件夹的作用...
  14. Spring AOP 的术语
  15. 关于运行Unity(一些游戏)出现0xc000007b的问题
  16. 微信端权限控制java,微信支付:特约子商户商户号未授权服务商的产品权限 的解决方案...
  17. C++在屏幕中输出数字d0...while
  18. VAS授权接入开发者文档,全民共创VAS生态
  19. Spring Cloud 系列之 Alibaba Nacos 注册中心(一)
  20. [汇编语言][bx]和loop指令

热门文章

  1. 电脑识别指令和代码的原理
  2. 视觉SLAM技术应用
  3. 2021年大数据Spark(一):框架概述
  4. 【注意事项】Markdown遇到的小问题
  5. C++ 获取内存地址(取值运算符)
  6. AttributeError: ‘NoneType‘ object has no attribute ‘span‘
  7. Error:The SDK Build Tools revision (23.0.3) is too low for project ':app'. Minimum required is 25.0.
  8. 【转】qt-vs-addin:Qt4和Qt5之VS插件如何共存与使用
  9. Linux Centos 7 安装配置nginx
  10. bzoj 1211 [HNOI2004]树的计数