OpenCV使用KNN完成OCR手寫體識別
目標(biāo)
在本章中,將學(xué)習(xí)
- 使用kNN來構(gòu)建基本的OCR應(yīng)用程
- 使用OpenCV自帶的數(shù)字和字母數(shù)據(jù)集
手寫數(shù)字的OCR
目標(biāo)是構(gòu)建一個可以讀取手寫數(shù)字的應(yīng)用程序。為此,需要一些 train_data
和test_data
。OpenCV git項(xiàng)目中有一個圖片 digits.png
(opencv/samples/data/ 中),其中包含 5000 個手寫數(shù)字(每個數(shù)字500個),每個數(shù)字都是尺寸大小為 20x20
的圖像。
因此,第一步是將上面這張圖像分割成 5000 (500*10)個不同的數(shù)字。對于每個數(shù)字,將其展平為 400 像素的一行,這就是訓(xùn)練集,即所有像素的強(qiáng)度值。這個是可以創(chuàng)建的最簡單的特征集合。將每個數(shù)字的前 250個樣本用作訓(xùn)練集train_data
,然后將 250 個樣本用作 測試集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)建了一個基礎(chǔ)的數(shù)字手寫體OCR應(yīng)用程序已準(zhǔn)備就緒。在這個特定的例子中的準(zhǔn)確度是91.76%。
提高準(zhǔn)確度方法:
一種提高準(zhǔn)確性的選擇是添加更多數(shù)據(jù)進(jìn)行訓(xùn)練,尤其是錯誤的數(shù)據(jù)。
另外一種是更換更優(yōu)的算法
本文中,每次啟動應(yīng)用程序時都找不到該訓(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ù)據(jù)轉(zhuǎn)換為 np.uint8
,然后再將其保存。在這種情況下,僅占用 0.98MB 。然后在加載時,可以轉(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ù)測單個數(shù)字
# 取測試集中的一個元素 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
接下來,對英語字母執(zhí)行相同的操作,但是數(shù)據(jù)和特征集會稍有變化。OpenCV使用文件letter-recognition.data
( /data/samples/data/letter-recognition.data)代替圖像 。如果打開它,將看到20000行,乍一看可能看起來像垃圾數(shù)字。
實(shí)際上,在每一行中,第一列是字母,這是標(biāo)簽。接下來的16個數(shù)字是它的不同特征,這些特征是從UCI機(jī)器學(xué)習(xí)存儲庫獲得的??梢栽?a rel="external nofollow" target="_blank">此頁面中找到這些功能的詳細(xì)信息。
現(xiàn)有20000個樣本,將前10000個數(shù)據(jù)作為訓(xùn)練樣本,剩余的10000個作為測試樣本。字母應(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)確性,則可以迭代地在每個類別中添加錯誤數(shù)據(jù)。
附加資源
以上就是OpenCV使用KNN完成OCR手寫體識別的詳細(xì)內(nèi)容,更多關(guān)于OpenCV KNN識別OCR手寫體的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Python+unittest+DDT實(shí)現(xiàn)數(shù)據(jù)驅(qū)動測試
這篇文章主要介紹了Python+unittest+DDT實(shí)現(xiàn)數(shù)據(jù)驅(qū)動測試,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2020-11-11Python使用jsonpath-rw模塊處理Json對象操作示例
這篇文章主要介紹了Python使用jsonpath-rw模塊處理Json對象操作,結(jié)合實(shí)例形式分析了Python使用requests與response處理json的方法,并給出了jsonpath_rw模塊操作json對象的基本示例,需要的朋友可以參考下2018-07-07Python調(diào)用OpenCV實(shí)現(xiàn)圖像平滑代碼實(shí)例
這篇文章主要介紹了Python調(diào)用OpenCV實(shí)現(xiàn)圖像平滑代碼實(shí)例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2020-06-06Python超有趣實(shí)例通過冒泡排序來實(shí)現(xiàn)LOL厄斐琉斯控槍
冒泡排序是一種簡單的排序算法,它也是一種穩(wěn)定排序算法。其實(shí)現(xiàn)原理是重復(fù)掃描待排序序列,并比較每一對相鄰的元素,當(dāng)該對元素順序不正確時進(jìn)行交換。一直重復(fù)這個過程,直到?jīng)]有任何兩個相鄰元素可以交換,就表明完成了排序2022-05-05詳解Python調(diào)用系統(tǒng)命令的六種方法
這篇文章主要介紹了詳解Python調(diào)用系統(tǒng)命令的六種方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-01-01python正則表達(dá)式re之compile函數(shù)解析
這篇文章主要介紹了python正則表達(dá)式re之compile函數(shù)解析,介紹了其定義,匹配模式等相關(guān)內(nèi)容,具有一定參考價值,需要的朋友可以了解下。2017-10-10對python中數(shù)據(jù)集劃分函數(shù)StratifiedShuffleSplit的使用詳解
今天小編就為大家分享一篇對python中數(shù)據(jù)集劃分函數(shù)StratifiedShuffleSplit的使用詳解,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-12-12