OpenCV使用KNN完成OCR手寫體識(shí)別
目標(biāo)
在本章中,將學(xué)習(xí)
- 使用kNN來構(gòu)建基本的OCR應(yīng)用程
- 使用OpenCV自帶的數(shù)字和字母數(shù)據(jù)集
手寫數(shù)字的OCR
目標(biāo)是構(gòu)建一個(gè)可以讀取手寫數(shù)字的應(yīng)用程序。為此,需要一些 train_data
和test_data
。OpenCV git項(xiàng)目中有一個(gè)圖片 digits.png
(opencv/samples/data/ 中),其中包含 5000 個(gè)手寫數(shù)字(每個(gè)數(shù)字500個(gè)),每個(gè)數(shù)字都是尺寸大小為 20x20
的圖像。
因此,第一步是將上面這張圖像分割成 5000 (500*10)個(gè)不同的數(shù)字。對(duì)于每個(gè)數(shù)字,將其展平為 400 像素的一行,這就是訓(xùn)練集,即所有像素的強(qiáng)度值。這個(gè)是可以創(chuàng)建的最簡單的特征集合。將每個(gè)數(shù)字的前 250個(gè)樣本用作訓(xùn)練集train_data
,然后將 250 個(gè)樣本用作 測試集test_data
。
import cv2 import numpy as np img = cv2.imread('digits.png') gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # Now we split the image to 5000 cells, each 20x20 size cells = [np.hsplit(row, 100) for row in np.vsplit(gray, 50)] # Make it into a numpy array: its size will be (50, 100, 20, 20) x = np.array(cells) # Now we prepare the training data and test data train = x[:,:50].reshape(-1,400).astype(np.float32) # Size = (2500,400) test = x[:,50:100].reshape(-1,400).astype(np.float32) # Size = (2500,400) # Create labels for train and test data k = np.arange(10) train_labels = np.repeat(k, 250)[:, np.newaxis] test_labels = train_labels.copy() # Initiate kNN, train it on the training data, then test it with the test data with k=1 knn = cv2.ml.KNearest_create() knn.train(train, cv2.ml.ROW_SAMPLE, train_labels) ret, result, neighbours, dist = knn.findNearest(test, k=5) # Now we check the accuracy of classification # For that, compare the result with test_labels and check which are wrong matches = result==test_labels correct = np.count_nonzero(matches) accuracy = correct * 100.0/result.size print( accuracy ) # 91.76
可以看到,上述構(gòu)建了一個(gè)基礎(chǔ)的數(shù)字手寫體OCR應(yīng)用程序已準(zhǔn)備就緒。在這個(gè)特定的例子中的準(zhǔn)確度是91.76%。
提高準(zhǔn)確度方法:
一種提高準(zhǔn)確性的選擇是添加更多數(shù)據(jù)進(jìn)行訓(xùn)練,尤其是錯(cuò)誤的數(shù)據(jù)。
另外一種是更換更優(yōu)的算法
本文中,每次啟動(dòng)應(yīng)用程序時(shí)都找不到該訓(xùn)練數(shù)據(jù),不如將其保存,以便下次直接從文件中讀取此數(shù)據(jù)并開始分類??梢越柚恍㎞umpy函數(shù)(例如np.savetxt
,np.savez
,np.load
等)來完成此操作。
# Save the data np.savez('knn_dight_data.npz', train=train, train_labels=train_labels) # Now load the data whit np.load('knn_data.npz') as data: print(data.files) train = data['train'] train_labels = data['train_labels']
在windows系統(tǒng)下,大約需要大約 3.82 MB 的內(nèi)存。由于僅使用強(qiáng)度值(uint8數(shù)據(jù))作為特征,如果需要考慮內(nèi)存的問題時(shí)候,可以先將數(shù)據(jù)轉(zhuǎn)換為 np.uint8
,然后再將其保存。在這種情況下,僅占用 0.98MB 。然后在加載時(shí),可以轉(zhuǎn)換回 float32
。
train_uint8 = train.astype(np.uint8) train_labels_uint8 = train_labels.astype(np.uint8) np.savez('knn_dight_data_int8.npz', train=train_uint8, train_labels=train_labels_uint8)
也可以用來預(yù)測單個(gè)數(shù)字
# 取測試集中的一個(gè)元素 single_data = testData[0].reshape(-1, 400) single_label = labels[0] ret, result, neighbours, dist = knn.findNearest(data, k=5) print(result) # [[0]] print(label) # [[0.]] print(result==label) # True
英文字母的OCR
接下來,對(duì)英語字母執(zhí)行相同的操作,但是數(shù)據(jù)和特征集會(huì)稍有變化。OpenCV使用文件letter-recognition.data
( /data/samples/data/letter-recognition.data)代替圖像 。如果打開它,將看到20000行,乍一看可能看起來像垃圾數(shù)字。
實(shí)際上,在每一行中,第一列是字母,這是標(biāo)簽。接下來的16個(gè)數(shù)字是它的不同特征,這些特征是從UCI機(jī)器學(xué)習(xí)存儲(chǔ)庫獲得的??梢栽?a rel="external nofollow" target="_blank">此頁面中找到這些功能的詳細(xì)信息。
現(xiàn)有20000個(gè)樣本,將前10000個(gè)數(shù)據(jù)作為訓(xùn)練樣本,剩余的10000個(gè)作為測試樣本。字母應(yīng)該更改為ASCII字符,因?yàn)椴荒苤苯邮褂米帜浮?/p>
import numpy as np import cv2 # Load the data and convert the letters to numbers data = np.loadtxt('letter-recognition.data', dtype='float32', delimiter=',', converters={0: lambda ch: ord(ch)-ord('A')}) # Split the dataset in two, with 10000 samples each for training and test sets train, test = np.vsplit(data, 2) # Split trainData and testData into features and responses responses, trainData = np.hsplit(train, [1]) labels, testData = np.hsplit(test, [1]) # Initiate the kNN, classify, measure accuracy knn = cv2.ml.KNearest_create() knn.train(trainData, cv2.ml.ROW_SAMPLE, responses) ret, result, neighbours, dist = knn.findNearest(testData, k=5) correct = np.count_nonzero(result==labels) accuracy = correct * 100 / result.size print(accuracy) # 93.06
它給我的準(zhǔn)確性為 93.06% 。同樣,如果要提高準(zhǔn)確性,則可以迭代地在每個(gè)類別中添加錯(cuò)誤數(shù)據(jù)。
附加資源
以上就是OpenCV使用KNN完成OCR手寫體識(shí)別的詳細(xì)內(nèi)容,更多關(guān)于OpenCV KNN識(shí)別OCR手寫體的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
keras實(shí)現(xiàn)theano和tensorflow訓(xùn)練的模型相互轉(zhuǎn)換
這篇文章主要介紹了keras實(shí)現(xiàn)theano和tensorflow訓(xùn)練的模型相互轉(zhuǎn)換,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2020-06-06如何將你的應(yīng)用遷移到Python3的三個(gè)步驟
這篇文章主要介紹了如何將你的應(yīng)用遷移到Python3的三個(gè)步驟,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-12-12Python中json.dumps()函數(shù)使用和示例
這篇文章主要介紹了Python中json.dumps()函數(shù)使用和示例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-03-03使用Rasterio讀取柵格數(shù)據(jù)的實(shí)例講解
今天小編就為大家分享一篇使用Rasterio讀取柵格數(shù)據(jù)的實(shí)例講解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2019-11-11