我正在尝试在OpenCV-Python(cv2)中实现“数字识别OCR”。它仅用于学习目的。我想学习OpenCV中的KNearest和SVM功能。
我每个数字有100个样本(即图像)。我想和他们一起训练。
letter_recog.pyOpenCV示例附带一个示例。但是我仍然不知道如何使用它。我不了解样本,回复等。此外,它首先会加载txt文件,而我首先并不了解。
letter_recog.pyOpenCV
稍后进行搜索时,我可以在cpp样本中找到letter_recognitiontion.data。我用它并在letter_recog.py模型中为cv2.KNearest编写了一个代码(仅用于测试):
import numpy as np import cv2 fn = 'letter-recognition.data' a = np.loadtxt(fn, np.float32, delimiter=',', converters={ 0 : lambda ch : ord(ch)-ord('A') }) samples, responses = a[:,1:], a[:,0] model = cv2.KNearest() retval = model.train(samples,responses) retval, results, neigh_resp, dists = model.find_nearest(samples, k = 10) print results.ravel()
它给了我一个大小为20000的数组,我不知道它是什么。
问题:
1)什么是letter_recognition.data文件?如何从我自己的数据集中构建该文件?
letter_recognition.data
2)results.reval()代表什么?
results.reval()
3)我们如何使用letter_recognition.data文件(KNearest或SVM)编写一个简单的数字识别工具?
好吧,我决定对我的问题进行锻炼以解决上述问题。我想要的是使用OpenCV中的KNearest或SVM功能实现简单的OCR。以下是我的工作方式。(这只是为了学习如何将KNearest用于简单的OCR目的)。
1)我的第一个问题是有关OpenCV示例随附的letter_recognition.data文件的信息。我想知道该文件中的内容。
它包含一个字母以及该字母的16个功能。
并this SOF帮助我找到了它。本文介绍了这16个功能Letter Recognition Using Holland-Style Adaptive Classifiers。(尽管我不了解最后的一些功能)
2)由于我知道,如果不了解所有这些功能,就很难做到这一点。我尝试了其他一些论文,但是对于初学者来说都有些困难。
So I just decided to take all the pixel values as my features. (我并不担心准确性或性能,我只是希望它能够工作,至少以最低的准确性)
So I just decided to take all the pixel values as my features.
我为训练数据拍摄了下图:
(我知道训练数据的数量较少。但是,由于所有字母的字体和大小都相同,所以我决定尝试一下)。
为了准备训练数据,我在OpenCV中编写了一个小代码。它执行以下操作:
以下是我用于上述目的的代码(当然,不是很干净):
import sys import numpy as np import cv2 im = cv2.imread('pitrain.png') im3 = im.copy() gray = cv2.cvtColor(im,cv2.COLOR_BGR2GRAY) blur = cv2.GaussianBlur(gray,(5,5),0) thresh = cv2.adaptiveThreshold(blur,255,1,1,11,2) ################# Now finding Contours ################### contours,hierarchy = cv2.findContours(thresh,cv2.RETR_LIST,cv2.CHAIN_APPROX_SIMPLE) samples = np.empty((0,100)) responses = [] keys = [i for i in range(48,58)] for cnt in contours: if cv2.contourArea(cnt)>50: [x,y,w,h] = cv2.boundingRect(cnt) if h>28: cv2.rectangle(im,(x,y),(x+w,y+h),(0,0,255),2) roi = thresh[y:y+h,x:x+w] roismall = cv2.resize(roi,(10,10)) cv2.imshow('norm',im) key = cv2.waitKey(0) if key == 27: # (escape to quit) sys.exit() elif key in keys: responses.append(int(chr(key))) sample = roismall.reshape((1,100)) samples = np.append(samples,sample,0) responses = np.array(responses,np.float32) responses = responses.reshape((responses.size,1)) print "training complete" np.savetxt('generalsamples.data',samples) np.savetxt('generalresponses.data',responses)
现在我们进入培训和测试部分。
为了测试零件,我使用了下面的图片,该图片与我训练过的字母具有相同的类型。
对于培训,我们执行以下操作:
出于测试目的,我们执行以下操作:
我在下面的单个代码中包括了最后两个步骤(培训和测试):
import cv2 import numpy as np ####### training part ############### samples = np.loadtxt('generalsamples.data',np.float32) responses = np.loadtxt('generalresponses.data',np.float32) responses = responses.reshape((responses.size,1)) model = cv2.KNearest() model.train(samples,responses) ############################# testing part ######################### im = cv2.imread('pi.png') out = np.zeros(im.shape,np.uint8) gray = cv2.cvtColor(im,cv2.COLOR_BGR2GRAY) thresh = cv2.adaptiveThreshold(gray,255,1,1,11,2) contours,hierarchy = cv2.findContours(thresh,cv2.RETR_LIST,cv2.CHAIN_APPROX_SIMPLE) for cnt in contours: if cv2.contourArea(cnt)>50: [x,y,w,h] = cv2.boundingRect(cnt) if h>28: cv2.rectangle(im,(x,y),(x+w,y+h),(0,255,0),2) roi = thresh[y:y+h,x:x+w] roismall = cv2.resize(roi,(10,10)) roismall = roismall.reshape((1,100)) roismall = np.float32(roismall) retval, results, neigh_resp, dists = model.find_nearest(roismall, k = 1) string = str(int((results[0][0]))) cv2.putText(out,string,(x,y+h),0,1,(0,255,0)) cv2.imshow('im',im) cv2.imshow('out',out) cv2.waitKey(0)
它起作用了,下面是我得到的结果:
在这里,它以100%的精度工作。我认为这是因为所有数字都是相同的种类和大小。
但是无论如何,对于初学者来说这是一个不错的开始(我希望如此)。