文章目录

  • 安装mahotas库智能提取阈值
  • 一、加载必要的库和一些基本函数
  • 二、定义hog算子来描述图片的特征
  • 三、根据已有数字类别标注的数据集来训练模型
  • 四、利用训练好的模型进行数字识别
  • 数据集下载和完整代码附录

安装mahotas库智能提取阈值

默认的conda环境是没有mahotas的,需要自己手动安装mahotas,注意不要使用pip install这种方式,可能会导致电脑死机!!!

conda config --add channels conda-forge
conda install mahotas
# 查看一下是否已经安装好
conda list

一、加载必要的库和一些基本函数

import cv2
# from sklearn.externals import joblib
import joblib
import mahotas
import numpy as np
from sklearn.svm import LinearSVC
from skimage import feature# 定义一个缩放函数
def resize(image, width = None, height = None, inter = cv2.INTER_AREA):dim = None(h, w) = image.shape[:2]if width is None and height is None:return image# 高度模式if width is None:r = height / float(h)dim = (int(w * r), height)# 宽度模式else:r = width / float(w)dim = (width, int(h * r))resized = cv2.resize(image, dim, interpolation = inter)return resized# 从excel加载数字,把特征和标注分开
def load_digits(datasetPath):data = np.genfromtxt(datasetPath, delimiter = ",", dtype = "uint8")target = data[:, 0]data = data[:, 1:].reshape(data.shape[0], 28, 28)return (data,target)# 进行旋转变换
def deskew(image, width):(h, w) = image.shape[:2]moments = cv2.moments(image)skew = moments["mu11"] / moments["mu02"]M = np.float32([[1, skew, -0.5 * w * skew],[0, 1, 0]])image = cv2.warpAffine(image, M, (w, h),flags = cv2.WARP_INVERSE_MAP | cv2.INTER_LINEAR)image = resize(image, width = width)return image# 把数字缩放到图片中心
def center_extent(image, size):(eW, eH) = size# 如果宽度》高度if image.shape[1] > image.shape[0]:image = resize(image, width = eW)else:image = resize(image, height = eH)extent = np.zeros((eH, eW), dtype = "uint8")offsetX = (eW - image.shape[1]) // 2offsetY = (eH - image.shape[0]) // 2extent[offsetY:offsetY + image.shape[0], offsetX:offsetX + image.shape[1]] = image# 计算图片的质量中心(cY, cX) = np.round(mahotas.center_of_mass(extent)).astype("int32")(dX, dY) = ((size[0] // 2) - cX, (size[1] // 2) - cY)M = np.float32([[1, 0, dX], [0, 1, dY]])# 把质量中心移动到图片的中心extent = cv2.warpAffine(extent, M, size)# return the extent of the imagereturn extent

二、定义hog算子来描述图片的特征

class HOG:def __init__(self, orientations = 9, pixelsPerCell = (8, 8),cellsPerBlock = (3, 3), transform = False):self.orienations = orientationsself.pixelsPerCell = pixelsPerCellself.cellsPerBlock = cellsPerBlockself.transform = transformdef describe(self, image):hist = feature.hog(image, orientations = self.orienations,pixels_per_cell = self.pixelsPerCell,cells_per_block = self.cellsPerBlock,transform_sqrt = self.transform)return hist

三、根据已有数字类别标注的数据集来训练模型

# 首先加载需要训练的数据
datasetPath = "data/digits.csv"
(digits, target) = load_digits(datasetPath)
data = []# 初始化hog因子
hog = HOG(orientations = 18, pixelsPerCell = (10, 10),
cellsPerBlock = (1, 1), transform = True)# 数据预处理
for image in digits:# 旋转和中心化image = deskew(image,20)image = center_extent(image,(20,20))# 使用hog算子描述图像特征hist = hog.describe(image)data.append(hist)# 开始训练
model = LinearSVC(random_state=42)
model.fit(data,target)
myModel = "mysvm.cpickle"
joblib.dump(model,myModel)

四、利用训练好的模型进行数字识别

# 加载训练好的模型
model = joblib.load(myModel)
hog = HOG(orientations = 18, pixelsPerCell = (10, 10),cellsPerBlock = (1, 1), transform = True)
# 加载被分类的图片
imagePath = "images/cellphone.png"
image = cv2.imread(imagePath)
# 图片预处理
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
blurred = cv2.GaussianBlur(gray, (5, 5), 0)
edged = cv2.Canny(blurred, 30, 150)
# 根据轮廓对数字进行切分
(cnts, _) = cv2.findContours(edged.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = sorted([(c, cv2.boundingRect(c)[0]) for c in cnts], key = lambda x: x[1])
for (c, _) in cnts:(x, y, w, h) = cv2.boundingRect(c)# 对于一定大小的数字才进行识别if w >= 7 and h >= 20:# 提取ROI区域roi = gray[y:y + h, x:x + w]thresh = roi.copy()# 智能识别阈值T = mahotas.thresholding.otsu(roi)thresh[thresh > T] = 255# 过滤掉颜色更亮的背景thresh = cv2.bitwise_not(thresh)# 图片旋转校正,并把数字放到中心thresh = deskew(thresh, 20)thresh = center_extent(thresh, (20, 20))# 测试预处理效果cv2.imshow("thresh", thresh)# 计算hog算子hist = hog.describe(thresh)# 根据模型来预测输出digit = model.predict([hist])[0]print("I think that number is: {}".format(digit))# 把识别出的数字用绿色框显示出来cv2.rectangle(image, (x, y), (x + w, y + h), (0, 255, 0), 1)# 在识别出来的框左上角标注数字cv2.putText(image, str(digit), (x - 10, y - 10),cv2.FONT_HERSHEY_SIMPLEX, 1.2, (0, 255, 0), 2)cv2.imshow("image", image)cv2.waitKey(0)
cv2.destroyAllWindows()

下面是几个识别的示例

结论:这种方法只能在特定的情况下才好用

  1. 首先背景必须要干净,而且是颜色比较亮,纹理分布均匀,数字不能被其他物体框起来
  2. 数字书写相对规范,并且类似于用水彩笔书写,线条需要有一定的宽度

数据集下载和完整代码附录

数据集下载:Digit Recognizer | Kaggle
https://www.kaggle.com/c/digit-recognizer

或者点击我下载:等待审核中

import cv2
# from sklearn.externals import joblib
import joblib
import mahotas
import numpy as np
from sklearn.svm import LinearSVC
from skimage import feature# 定义一个缩放函数
def resize(image, width = None, height = None, inter = cv2.INTER_AREA):dim = None(h, w) = image.shape[:2]if width is None and height is None:return image# 高度模式if width is None:r = height / float(h)dim = (int(w * r), height)# 宽度模式else:r = width / float(w)dim = (width, int(h * r))resized = cv2.resize(image, dim, interpolation = inter)return resized# 从excel加载数字,把特征和标注分开
def load_digits(datasetPath):data = np.genfromtxt(datasetPath, delimiter = ",", dtype = "uint8")target = data[:, 0]data = data[:, 1:].reshape(data.shape[0], 28, 28)return (data,target)# 进行旋转变换
def deskew(image, width):(h, w) = image.shape[:2]moments = cv2.moments(image)skew = moments["mu11"] / moments["mu02"]M = np.float32([[1, skew, -0.5 * w * skew],[0, 1, 0]])image = cv2.warpAffine(image, M, (w, h),flags = cv2.WARP_INVERSE_MAP | cv2.INTER_LINEAR)image = resize(image, width = width)return image# 把数字缩放到图片中心
def center_extent(image, size):(eW, eH) = size# 如果宽度》高度if image.shape[1] > image.shape[0]:image = resize(image, width = eW)else:image = resize(image, height = eH)extent = np.zeros((eH, eW), dtype = "uint8")offsetX = (eW - image.shape[1]) // 2offsetY = (eH - image.shape[0]) // 2extent[offsetY:offsetY + image.shape[0], offsetX:offsetX + image.shape[1]] = image# 计算图片的质量中心(cY, cX) = np.round(mahotas.center_of_mass(extent)).astype("int32")(dX, dY) = ((size[0] // 2) - cX, (size[1] // 2) - cY)M = np.float32([[1, 0, dX], [0, 1, dY]])# 把质量中心移动到图片的中心extent = cv2.warpAffine(extent, M, size)# return the extent of the imagereturn extentclass HOG:def __init__(self, orientations = 9, pixelsPerCell = (8, 8),cellsPerBlock = (3, 3), transform = False):self.orienations = orientationsself.pixelsPerCell = pixelsPerCellself.cellsPerBlock = cellsPerBlockself.transform = transformdef describe(self, image):hist = feature.hog(image, orientations = self.orienations,pixels_per_cell = self.pixelsPerCell,cells_per_block = self.cellsPerBlock,transform_sqrt = self.transform)return hist# 首先加载需要训练的数据
datasetPath = "data/digits.csv"
(digits, target) = load_digits(datasetPath)
data = []# 初始化hog因子
hog = HOG(orientations = 18, pixelsPerCell = (10, 10),
cellsPerBlock = (1, 1), transform = True)# 数据预处理
for image in digits:# 旋转和中心化image = deskew(image,20)image = center_extent(image,(20,20))# 使用hog算子描述图像特征hist = hog.describe(image)data.append(hist)# 开始训练
model = LinearSVC(random_state=42)
model.fit(data,target)
myModel = "mysvm.cpickle"
joblib.dump(model,myModel)    # 加载训练好的模型
model = joblib.load(myModel)
hog = HOG(orientations = 18, pixelsPerCell = (10, 10),cellsPerBlock = (1, 1), transform = True)
# 加载被分类的图片
imagePath = "images/cellphone.png"
image = cv2.imread(imagePath)
# 图片预处理
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
blurred = cv2.GaussianBlur(gray, (5, 5), 0)
edged = cv2.Canny(blurred, 30, 150)
# 根据轮廓对数字进行切分
(cnts, _) = cv2.findContours(edged.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = sorted([(c, cv2.boundingRect(c)[0]) for c in cnts], key = lambda x: x[1])
for (c, _) in cnts:(x, y, w, h) = cv2.boundingRect(c)# 对于一定大小的数字才进行识别if w >= 7 and h >= 20:# 提取ROI区域roi = gray[y:y + h, x:x + w]thresh = roi.copy()# 智能识别阈值T = mahotas.thresholding.otsu(roi)thresh[thresh > T] = 255# 过滤掉颜色更亮的背景thresh = cv2.bitwise_not(thresh)# 图片旋转校正,并把数字放到中心thresh = deskew(thresh, 20)thresh = center_extent(thresh, (20, 20))# 测试预处理效果cv2.imshow("thresh", thresh)# 计算hog算子hist = hog.describe(thresh)# 根据模型来预测输出digit = model.predict([hist])[0]print("I think that number is: {}".format(digit))# 把识别出的数字用绿色框显示出来cv2.rectangle(image, (x, y), (x + w, y + h), (0, 255, 0), 1)# 在识别出来的框左上角标注数字cv2.putText(image, str(digit), (x - 10, y - 10),cv2.FONT_HERSHEY_SIMPLEX, 1.2, (0, 255, 0), 2)cv2.imshow("image", image)cv2.waitKey(0)
cv2.destroyAllWindows()

使用OpenCV-python实现手写数字识别相关推荐

  1. 手把手教你使用LabVIEW OpenCV DNN实现手写数字识别(含源码)

    文章目录 前言 一.OpenCV DNN模块 1.OpenCV DNN简介 2.LabVIEW中DNN模块函数 二.TensorFlow pb文件的生成和调用 1.TensorFlow2 Keras模 ...

  2. python手写汉字识别_用python实现手写数字识别

    前言 在之前的学习中,已经对神经网络的算法具体进行了学习和了解.现在,我们可以用python通过两种方法来实现手写数字的识别.这两种方法分别是多元逻辑回归和神经网络方法. 用多元逻辑回归手写数字识别 ...

  3. 基于python的手写数字识别实验报告_联机手写数字识别实验报告

    1 联机手写数字识别设计 一.设计论述 模式识别是六十年代初迅速发展起来的一门学科. 由于它研究的是如何用机 器来实现人 ( 及某些动物 ) 对事物的学习. 识别和判断能力, 因而受到了很多科技 领域 ...

  4. python实现手写数字识别(小白入门)

    手写数字识别(小白入门) 今早刚刚上了节实验课,关于逻辑回归,所以手有点刺挠就想发个博客,作为刚刚入门的小白,看到代码运行成功就有点小激动,这个实验没啥含金量,所以路过的大牛不要停留,我怕你们吐槽哈哈 ...

  5. 利用python卷积神经网络手写数字识别_卷积神经网络使用Python的手写数字识别

    为了使机器更智能,开发人员正在研究机器学习和深度学习技术.人类通过反复练习和重复执行任务来学习执行任务,从而记住了如何执行任务.然后,他大脑中的神经元会自动触发,它们可以快速执行所学的任务.深度学习与 ...

  6. OpenCV+TensorFlow图片手写数字识别(附源码)

    初次接触TensorFlow,而手写数字训练识别是其最基本的入门教程,网上关于训练的教程很多,但是模型的测试大多都是官方提供的一些素材,能不能自己随便写一串数字让机器识别出来呢?纸上得来终觉浅,带着这 ...

  7. 基于python的手写数字识别knn_KNN分类算法实现手写数字识别

    需求: 利用一个手写数字"先验数据"集,使用knn算法来实现对手写数字的自动识别: 先验数据(训练数据)集: ♦数据维度比较大,样本数比较多. ♦ 数据集包括数字0-9的手写体. ...

  8. 基于opencv实现的手写数字识别

    一.使用模板匹配算法 match.py: import os import Function root_dir = "digits/train2" file7_7 = open(& ...

  9. Python神经网络手写数字识别代码解释

    使用了数据集MNIST中的部分数据. 1.读取数据集内容 #打开文件并获取其中的内容 data_file=open("mnist_train.csv",'r') #open()函数 ...

  10. python数字的鲁棒输入_请教关于python的手写数字识别神经网络问题~~~~

    该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 """network.py~~~~~~~~~~ A module to implement the stochastic g ...

最新文章

  1. python123期末测验答案程序题_python期末题库(2)带答案
  2. php自定义函数格式化,PHP自定义函数格式化json数据实例
  3. 在html中横坐标是纵坐标,excel 作图中次横坐标及次纵坐标的调试,以及excel自定义轴标签的步骤方法...
  4. linux 系统将某目录下的可执行文件添加环境变量,jenkins创建shell长链接却找不到
  5. SAP UI5 数据绑定中的工厂函数
  6. bettertouchtool闪退_BetterTouchTool for Mac 3.238 无闪退 触控板增强工具
  7. .net 代码混淆原理性实践
  8. DSAPI多功能组件编程应用-HTTP监听服务端与客户端
  9. Qemu之CPU mode介绍
  10. htmlunit抓取js执行后的网页源码
  11. MySQL多线程备份工具mydumper
  12. spring整合kaptcha验证码
  13. 傅里叶级数与变换(二)
  14. CAN网络基础知识_20220727
  15. Ubuntu16.04:GTX1650的显卡驱动安装
  16. 什么是JTAG和SWD接口协议,和各类仿真器
  17. listen监听队列刨析
  18. Eclipse红叉报错
  19. 联想lenovo thinkserver RD640 安装windows2003erver
  20. Android G711(PCMA/PCMU)、G726、PCM音频转码到AAC

热门文章

  1. 2015workshop-age 的txt 生成过程
  2. 杭电1286找新朋友
  3. 如何解决linux下编译出现的multiple definition of错误
  4. mysql的数据备份问题_mysql数据库备份的问题
  5. php 判断json包含key,php判断json对象是否存在的方法
  6. python编程(再述rpc)
  7. python编程(python开发的三种运行模式)
  8. 用汇编的眼光看C++ (之x86汇编)
  9. java单例模式 三种_三种java单例模式概述
  10. mysql服务器处理查询的模型_mysql02---客户端与服务器模型