学长要求做一个可视化的与数据分析的程序,就想到了这个,用了最简单的方法,其实识别效率不是很高,基本上书写要与训练数据比较相似才能识别出来,正在想办法去优化,先把目前的成果分享出来,本人是用python+opencv做的。
draw.py
相当于一个写字板,将写完字后的图片保存转为32*32
#encoding:utf-8
import cv2
import numpy as np #mouse callback function
from knn import *
ix,iy=-1,-1
#创建图像与窗口并将窗口与回调函数绑定
def in_img():
for i in range(512):
img[i,:]=255
cv2.namedWindow('image')
cv2.setMouseCallback('image',draw_circle)
while(1):
cv2.imshow('image',img)
if cv2.waitKey(20)& 0xFF == ord('q'):
cv2.imwrite( '1.jpg',img)
break
cv2.destroyAllWindows()
def draw_circle(event,x,y,flags,param):
global ix,iy,drawing
if event==cv2.EVENT_LBUTTONDOWN:
drawing=True
ix,iy=x,y
elif event==cv2.EVENT_MOUSEMOVE and flags==cv2.EVENT_FLAG_LBUTTON:
if drawing==True:
cv2.circle(img,(x,y),30,(0,0,0),-1)
elif event==cv2.EVENT_LBUTTONUP:
drawing==False
def read_image():
img1 = cv2.imread('1.jpg', cv2.IMREAD_GRAYSCALE)
res=cv2.resize(img1,(32,32),interpolation=cv2.INTER_CUBIC)
pic=[]
for i in range(32):
for j in range(32):
if res[i][j]<=200:
res[i][j]=1
else:
res[i][j]=0
pic.append(int(res[i][j]))
hwLabels,trainingMat = trainingDataSet()
classifierResult = classify(pic, trainingMat, hwLabels, 3)
print classifierResult
def main():
global img
img=np.zeros((512,512,3),np.uint8)
in_img()
read_image()
if __name__=="__main__":
main()
knn.py
利用KNN算法找到离测试数据最近的10个点(程序中可以调),然后在这10个数据中选取出现次数最多的,即为测试数据代表的数据。
#encoding: utf-8
from numpy import *
import operator
import time
from os import listdir
def classify(inputPoint,dataSet,labels,k):
dataSetSize = dataSet.shape[0] #已知分类的数据集(训练集)的行数
#先tile函数将输入点拓展成与训练集相同维数的矩阵,再计算欧氏距离
diffMat = tile(inputPoint,(dataSetSize,1))-dataSet #样本与训练集的差值矩阵
sqDiffMat = diffMat ** 2 #差值矩阵平方
sqDistances = sqDiffMat.sum(axis=1) #计算每一行上元素的和
distances = sqDistances ** 0.5 #开方得到欧拉距离矩阵
sortedDistIndicies = distances.argsort() #按distances中元素进行升序排序后得到的对应下标的列表
#选择距离最小的k个点
classCount = {}
for i in range(k):
voteIlabel = labels[ sortedDistIndicies[i] ]
classCount[voteIlabel] = classCount.get(voteIlabel,0)+1
#按classCount字典的第2个元素(即类别出现的次数)从大到小排序
sortedClassCount = sorted(classCount.items(), key = operator.itemgetter(1), reverse = True)
return sortedClassCount[0][0]
def img2vector(filename):
returnVect = []
fr = open(filename)
for i in range(32):
lineStr = fr.readline()
for j in range(32):
returnVect.append(int(lineStr[j]))
return returnVect
def classnumCut(fileName):
fileStr = fileName.split('.')[0]
classNumStr = int(fileStr.split('_')[0])
return classNumStr
#构建训练集数据向量,及对应分类标签向量
def trainingDataSet():
hwLabels = []
trainingFileList = listdir('trainingDigits1') #获取目录内容
m = len(trainingFileList)
trainingMat = zeros((m,1024)) #m维向量的训练集
for i in range(m):
fileNameStr = trainingFileList[i]
hwLabels.append(classnumCut(fileNameStr))
trainingMat[i,:] = img2vector('trainingDigits1/%s' % fileNameStr)
#print type(trainingMat)
return hwLabels,trainingMat
我个人还写了个数据,可以自己建立一些测试数据,对于书写有着特殊风格的人可以尝试,当然如果你非常感兴趣的话,还可以用这个程序建立关于英文字母的测试数据,然后用上面的KNN识别英文字母
train_data.py
#encoding:utf-8
import cv2
import numpy as np #mouse callback function
from knn import *
ix,iy=-1,-1
#创建图像与窗口并将窗口与回调函数绑定
def in_img():
for i in range(512):
img[i,:]=255
cv2.namedWindow('image')
cv2.setMouseCallback('image',draw_circle)
while(1):
cv2.imshow('image',img)
if cv2.waitKey(20)& 0xFF == ord('q'):
cv2.imwrite( '1.jpg',img)
break
cv2.destroyAllWindows()
def draw_circle(event,x,y,flags,param):
global ix,iy,drawing
if event==cv2.EVENT_LBUTTONDOWN:
drawing=True
ix,iy=x,y
elif event==cv2.EVENT_MOUSEMOVE and flags==cv2.EVENT_FLAG_LBUTTON:
if drawing==True:
cv2.circle(img,(x,y),20,(0,0,0),-1)
elif event==cv2.EVENT_LBUTTONUP:
drawing==False
def read_image():
img1 = cv2.imread('1.jpg', cv2.IMREAD_GRAYSCALE)
res=cv2.resize(img1,(32,32),interpolation=cv2.INTER_CUBIC)
pic=[]
for i in range(32):
for j in range(32):
if res[i][j]<=200:
res[i][j]=1
else:
res[i][j]=0
pic.append(int(res[i][j]))
f=open('trainingDigits/6_9.txt','w')
for i in range(32):
for j in range(32):
f.write(str(res[i][j]))
f.write("\n")
f.close()
def main():
global img
img=np.zeros((512,512,3),np.uint8)
in_img()
read_image()
if __name__=="__main__":
main()
结语:个人有一个想法,因为原先的测试数据太多,再加上KNN本身只属于一种算法,并不是一种可建立的模型,每一次识别的时间花费非常长,利用KNN+Adaboost算法尝试尝试,感兴趣的话可以尝试一下
数据来源:http://pan.baidu.com/s/1eQIM4Lk?errno=0&errmsg=Auth%20Login%20Sucess&stoken=9002846861134dfc8b364739cf183e78edcb825ba47e18b1fcfca477d2863a584d122304c8a8739cdcea6bdc3729b78c16da28d4fde8764a0e6b93faf67a6af4d40a3b562d36&bduss=7a7eb001d8d08e2603aaf1732e36c0aa6d77a46d41a907ceb00444543799daedca40105c7c29c9ad32852f293a6013324a71513422ba2cb7cb6b48b3c7679e28c47126a05d0266522fa40883397d046b45914a76628db9b3faefe0e76c5ef6ca53477ffd4a80f84c0d070ff26f672d6c1f00d2aad9b4d034924b1cea44720b551f522bd7160652a38e6b4a851640396f9e93d02424b8674f7c55035c9d5fb8499098a7624e3aa82470a2df78f8585583a1a00f163046b736c36f4ab03ab08269923fcdbb4bfa&ssnerror=0
最后贴一张效果图: