Python实现基于KNN算法的笔迹识别功能详解
作者:Kedi 发布时间:2021-06-18 13:15:08
本文实例讲述了Python实现基于KNN算法的笔迹识别功能。分享给大家供大家参考,具体如下:
需要用到:
Numpy库
Pandas库
手写识别数据 点击此处本站下载。
数据说明:
数据共有785列,第一列为label,剩下的784列数据存储的是灰度图像(0~255)的像素值 28*28=784
KNN(K近邻算法):
从训练集中找到和新数据最接近的K条记录,根据他们的主要分类来决定新数据的类型。
这里的主要分类,可以有不同的判别依据,比如“最多”,“最近邻”,或者是“距离加权”。
整个程序的几个部分:
1.数据的归一化处理(normalization)
2.(重要)找出与test数据最接近的train数据的编号,根据编号查找到对应的label,将label赋给test数据的预测值
3.统计知道的test的label值与test的预测label值得正确率
Step 1
导入Numpy与Pandas库
import numpy as np
import pandas as pd
Step 2
对数据进行归一化
对数据归一化的方法很多,比如:
一、max-Min标准化
max - Min标准化方法是对原始数据进行线性变换。设minA和maxA分别为属性A的最小值和最大值,将A的一个原始值x通过max-Min标准化映射成在区间[0,1]中的值x',其公式为:
新数据=(原数据-极小值)/(极大值-极小值)
二、
新数据=原数据/(原数据的平方和开根号)
三、
y = ( x - min )/( max - min ) 其中min为x的最小值,max为x的最大值,输入向量为x,归一化后的输出向量为y 。上式将数据归一化到 [ 0 , 1 ]区间,当激活函数采用S形函数时(值域为(0,1))时这条式子适用
在这里采用方法二
def normalize(x):
norms = np.apply_along_axis(np.linalg.norm,1,x)
return x / np.expand_dims(norms,-1)
调用np中的linalg.norm(x)
和 apply_along_axis(func, axis, x)
函数
linalg.norm(x)
函数的作用是 return sum(abs(xi)**2)**0.5
,
apply_along_axis(func, axis, x)
函数的作用是将x按axis方向执行func函数,axis=0表示做列方向上的运算,axis=1表示做行方向上的运算
step 3
找出与test数据最接近的train数据,这步是最关键的一步。
在这里,test数据与train数据就是空间的两个向量,问题就变成了如何计算这两个向量的相似程度。
我们可以把它们想象成空间中的两条线段,都是从原点([0, 0, ...])出发,指向不同的方向。两条线段之间形成一个夹角,如果夹角为0度,意味着方向相同、线段重合;如果夹角为90度,意味着形成直角,方向完全不相似;如果夹角为180度,意味着方向正好相反。因此,我们可以通过夹角的大小,来判断向量的相似程度。夹角越小,就代表越相似。
假定a向量是[x1, y1],b向量是[x2, y2],那么可以将余弦定理改写成下面的形式:
余玄定理
def nearest_neighbor(norm_func,train_data,train_label,test_data):
train_data = norm_func(train_data)
test_data = norm_func(test_data)
cos = np.dot(train_data,np.transpose(test_data))#np.transpose为求转置,dot为矩阵的乘积,结果为cos的一列值为test与train的相似度
max_cos = np.argmax(cos,axis=0)#np.argmax为cos中一列上方的最大值
test_pred = train_label[max_cos]#train_label为一列,max_cos为一个数组,train_label[max_cos]会读出train_label中max_cos数组编号的元素
return test_pred#返回test的预测值
step 4
统计预测值的正确率
def validate(test_pred,test_label):
c=len(test_pred)#在数组里面套数组的时候,len得到的是大数组里数组的个数,在只有一层数组的时候,得到的是数组中元素的个数
correct=(test_pred == test_label).sum()#统计两个数组中有多少个元素相同
return float(correct)/c#必须转变成浮点数再做除法,之前使用correct/c得到0
测试代码:
if __name__ == '__main__':
train_num = 200
test_num = 300#测试数据起始是test_num-train_num
x = pd.read_csv('train.csv')
x_train = x.values[0:train_num,1:]#读取pandas中读取出来的数据,需要用data.values[]
x_train_label = x.values[0:train_num,0]#第一列是label,每幅图的数据是一行
x_test = x.values[train_num:test_num,1:]
x_test_label = x.values[train_num:test_num,0]
test_pred=nearest_neighbor(normalize,x_train,x_train_label,x_test)
prec=validate(test_pred,x_test_label)
print u"正确率为%.2f"%(prec)#浮点数是%f
完整代码点击此处本站下载。
注解:
上面部分主要是讲解KNN算法,运用到的是现成的28*28的数据,而在实际做笔迹分析的时候,首先需要将图像转化成矩阵数据。
现在介绍一下,图像转化成矩阵与矩阵转化成图像的方法
矩阵转化成图像
需要用到的库是图像处理库Python Imaging Library (PIL)
在Windows下使用pip install PIL安装失败,采取了下载PIL.exe双击安装的方法
下载地址:
PIL官方下载地址
import pandas as pd
import numpy as np
from PIL import Image
# load data
train = pd.read_csv('train.csv')
# now draw the numbers
for ind, row in train.iloc[0:3].iterrows():#iloc方法(介绍见后)来获得前3行数据
i = row[0]#[0]为标签项
arr = np.array(row[1:], dtype=np.uint8)#1-784列组成一幅图,,uint8为8位无符号整数
#arr = np.array(255 - row[1:], dtype=np.uint8)#如果需要颜色取反,用255减去当前每个像素点的值
arr.resize((28, 28))#把它变成28*28的矩阵
#save to file
im = Image.fromarray(arr)
im.save("./train_pics/%s-%s.png" % (ind, i))#第一个%s(ind)表示它是第几幅图像,第二个%s表示这个图像里面数字是几 ,注意该语句不能产生文件夹,需要现在指定目录建一个文件夹
.iloc()方法
iloc[行位置,列位置]
df.iloc[1,1]#选取第二行,第二列的值,返回的为单个值
df.iloc[0,2],:]#选取第一行及第三行的数据
图像转化成矩阵
需要用到的库是opencv(open source computer vision)
,下载安装方式请参照附录:python_OpenCV安装
这里主要讲它的几个简单功能
1.静态图像的输入,输出
cv2.imread('xxx.png')#输入,#这里输入image的维度image.shape = (w,h,3),w*h是图片的长宽,3是BGR等三种颜色的channel值,每个值为0~255
cv2.imwrite('xxx.jpg', image)#输出
2.将图片转化为灰度图片
#灰度图片的颜色channel只有一个,0~255表示灰度值
grayImage = cv2.imread('xxx.png',cv2.CV_LOAD_IMAGE_GRAYSCALE)
3.改变图像的大小
print grayImage.shape#查看图像的shape,shape为(137,301),如果查看的是图像的size,则为42137(41237=137*301)
res=cv2.resize(grayImage,(28,28),interpolation=cv2.INTER_CUBIC)#将图片grayImage以cv2.INTER_CUBIC方式变化为(28,28)大小的图片
变换的方法:
CV_INTER_NN - 最近邻插值,
CV_INTER_LINEAR - 双线性插值 (缺省使用)
CV_INTER_AREA - 使用象素关系重采样。当图像缩小时候,该方法可以避免波纹出现。当图像放大时,类似于 CV_INTER_NN 方法..
CV_INTER_CUBIC -立方插值.
下面是有关输入,输出,改变成灰度图,改变图像大小,显示的完整程序,注意图像在窗口中的显示
import cv2
image = cv2.imread('111.png')#读
cv2.imwrite('111.jpg', image)#写
grayImage = cv2.imread('111.png',cv2.CV_LOAD_IMAGE_GRAYSCALE)
print grayImage.shape
res=cv2.resize(grayImage,(28,28),interpolation=cv2.INTER_CUBIC)
#显示图像
cv2.imshow('test',grayImage)#显示灰度图
cv2.imshow('change',res)#显示改变了大小的图
#捕获键盘输入
k=cv2.waitKey(0)
if k==27:#27表示ESC键
cv2.destroyWindow()
cv2.imshow()
用于将图片显示在窗口中,后面必须跟个cv2.waitKey()
函数,才能让显示持续,不然显示出来程序就中止了,窗口就会被关闭。cv2.waitKey()
函数是捕获键盘的输入,cv2.destroyWindow()
是释放窗口。
在学习了如果读取,输出图片后,我们就可以用写好的KNN算法识别我们的笔迹了。
问题:
我使用了很多手写的数据去验证识别是否准确,发现准确率还不够高。主要存在的问题是
1.图片大小问题,大小的调节不应该把整张图片变为28*28的图,而应该识别出写有数字的中心图片,把旁边的白边去掉
2.手写的数字照片,不能保证写字的地方为黑(像素值为255)
解决方式:需要使用一个滤波器,把因纸张,拍摄问题出现的像素值降。再没有使用滤波器的条件下,我把照片换成了在画图板上写的数字。
3.写字的粗细会影响判断
解决办法:这个可能是训练样本不够多,整体训练样本的字迹偏粗,在输入很细的笔迹时,不能识别出来。还有就是应该监测输入字体的粗细,对输入的很细的笔迹做膨胀处理,对很粗的笔迹做腐蚀处理
附:python_OpenCV安装
看到网上好多教程的是在VS环境下OpenCV的安装,而我一直都是在windows7,32位,sublime+cmd环境下,进行python的编程,所以琢磨了下这种条件下的OpenCV安装
使用pip install numpy语句安装numpy
(如果出现错误:Microsoft Visual C++ 9.0 is required <unable to find vcvarsall.bat>,使用管理员身份安装 Microsoft Visual C++ 9.0,重新启动计算机,再使用使用pip install numpy语句安装numpy
opencv2.4.10下载
下载之后解压(随便解压到哪里),将解压目录opencv文件夹中,build->python->2.7->x86下的文件cv2.pyd 复制到python2.7\Lib\site-packages 中
测试是否安装成功,执行解压目录下的sources\samples\python\drawing.py或者进入python环境,使用
import cv2
希望本文所述对大家Python程序设计有所帮助。
来源:https://www.jianshu.com/p/4afc39897b3e
猜你喜欢
- 讲这个方法之前,我们应该先了解下插入节点时浏览器会做什么。在浏览器中,我们一旦把节点添加到document.body(或者其他节点)中,页面
- 为了得到更加清晰的图像我们需要通过技术对图像进行处理,比如使用对比度增强的方法来处理图像,对比度增强就是对图像输出的灰度级放大到指定的程度,
- 一:队列配置队列的配置文件放置在config/queue.php文件中,laravel框架中支持的队列驱动有:sync, database,
- 本文实例讲述了python处理图片之PIL模块简单使用方法。分享给大家供大家参考。具体实现方法如下:#!/usr/bin/env pytho
- 守来说,AJAX在现在是热得不能再热的技术。没有人能否认,它拥有大批的支持者。在CNN上,它从二月份的一个不被看好的词语到十月份成长成一个初
- python中的列表和元组# 1.列表的格式# [数据1,数据2,数据3,···]# 列表 可变数据类型# 列表可以存储多个数据,数据之间的
- 今天在调试项目的时候出现下面的错误信息:SoapFaultlooks like we got no XML document (D:\php
- 我们可以利用 Cookie collection 来刪除客户端的Cookies: <%
- 它在Lynx里也会运行得很好:<%@ Language=VBScript %><HTML><
- 从codered到nimda等,一大堆蠕虫把原来需要人工利用的漏洞都变成了程序自动利用了,大家还想去手工操作这些IIS漏洞么?让我们调整重心
- 我就废话不多说了,大家还是直接看代码吧!# coding=utf-8import loggingimport yamlimport osim
- 可以实现,下面我们就来做一个检测一个字符串在另一个字符串当中出现几次的函数:入口参数:TheChar="要检测的字符串"
- 查看某一列中有多少中取值:数据集名.drop_duplicates(['列名'])#实际为删除重复项,删除后对原数据集不修改
- 本文实例讲述了PHP抓取及分析网页的方法。分享给大家供大家参考,具体如下:抓取和分析一个文件是非常简单的事。这个教程将通过一个例子带领你一步
- 操作步骤1.下载BeautifulReport文件,本例文件下载地址 最新文件下载地址2.复制文件BeautifulReport,至pyth
- 1、出现错误train_df = pd.read_csv( 'C:\Users\lenovo\Desktop\train.csv
- 自 PHP 5.4.0 起,PHP 实现了代码复用的一个方法,称为 traits。Traits 是一种为类似 PHP 的单继承语言而准备的代
- 例如:将日期格式为2009-6-8的转换为2009-06-08,给小于10的数字补上一个0方法一:year(now)
- 代码如下: <% '屏蔽主流的下载工具 Dimxurl,xtool '获取浏览器AGENT xurl=lcase(Re
- Opera, 作为 A-Grade 浏览器,在现在的前端开发中务必支持。它很优秀,很不幸,bug是每个浏览器都不可避免的问题,Opera亦难