OpenCV-Python 使用OCR手寫數據集運行KNN

目標

在本章中

  • 我們將使用我們在kNN上的知識來構建基本的OCR應用程序。
  • 我們將嘗試使用OpenCV自帶的數字和字母數據集。

手寫數字的OCR

我們的目標是構建一個可以讀取手寫數字的應用程序。為此,我們需要一些train_data和test_data。OpenCV帶有一個圖片digits.png(在文件夾opencv/samples/data/中),其中包含5000個手寫數字(每個數字500個)。每個數字都是20x20的圖像。因此,我們的第一步是將圖像分割成5000個不同的數字。對於每個數字,我們將其展平為400像素的一行。那就是我們的訓練集,即所有像素的強度值。這是我們可以創建的最簡單的功能集。我們將每個數字的前250個樣本用作train_data,然後將250個樣本用作test_data。因此,讓我們先準備它們。

<code>import numpy as np
import cv2 as cv
img = cv.imread('digits.png')
gray = cv.cvtColor(img,cv.COLOR_BGR2GRAY)
# 現在我們將圖像分割為5000個單元格,每個單元格為20x20
cells = [np.hsplit(row,100) for row in np.vsplit(gray,50)]
# 使其成為一個Numpy數組。它的大小將是(50,100,20,20)
x = np.array(cells)
# 現在我們準備train_data和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)
# 為訓練和測試數據創建標籤

k = np.arange(10)
train_labels = np.repeat(k,250)[:,np.newaxis]
test_labels = train_labels.copy()
# 初始化kNN,訓練數據,然後使用k = 1的測試數據對其進行測試
knn = cv.ml.KNearest_create()
knn.train(train, cv.ml.ROW_SAMPLE, train_labels)
ret,result,neighbours,dist = knn.findNearest(test,k=5)
# 現在,我們檢查分類的準確性
#為此,將結果與test_labels進行比較,並檢查哪個錯誤
matches = result==test_labels
correct = np.count_nonzero(matches)
accuracy = correct*100.0/result.size
print( accuracy )/<code>

因此,我們的基本OCR應用程序已準備就緒。這個特定的例子給我的準確性是91%。一種提高準確性的選擇是添加更多數據進行訓練,尤其是錯誤的數據。因此,與其每次啟動應用程序時都找不到該培訓數據,不如將其保存,以便下次我直接從文件中讀取此數據並開始分類。您可以藉助一些Numpy函數(例如np.savetxt,np.savez,np.load等)來完成此操作。請查看其文檔以獲取更多詳細信息。

<code># 保存數據
np.savez('knn_data.npz',train=train, train_labels=train_labels)
# 現在加載數據
with np.load('knn_data.npz') as data:
print( data.files )
train = data['train']
train_labels = data['train_labels']/<code>

在我的系統中,它需要大約4.4 MB的內存。由於我們使用強度值(uint8數據)作為特徵,因此最好先將數據轉換為np.uint8,然後再將其保存。在這種情況下,僅佔用1.1 MB。然後在加載時,您可以轉換回float32。

英文字母的OCR

接下來,我們將對英語字母執行相同的操作,但是數據和功能集會稍有變化。在這裡,OpenCV代替了圖像,而在opencv/samples/cpp/文件夾中附帶了一個數據文件letter-recognitiontion.data。如果打開它,您將看到20000行,乍一看可能看起來像垃圾。實際上,在每一行中,第一列是一個字母,這是我們的標籤。接下來的16個數字是它的不同功能。這些功能是從UCI機器學習存儲庫獲得的。您可以在此頁面中找到這些功能的詳細信息。 現有20000個樣本,因此我們將前10000個數據作為訓練樣本,其餘10000個作為測試樣本。我們應該將字母更改為ASCII字符,因為我們不能直接使用字母。

<code>import cv2 as cv
import numpy as np
# 加載數據,轉換器將字母轉換為數字
data= np.loadtxt('letter-recognition.data', dtype= 'float32', delimiter = ',',
converters= {0: lambda ch: ord(ch)-ord('A')})
# 將數據分為兩個,每個10000個以進行訓練和測試
train, test = np.vsplit(data,2)
# 將火車數據和測試數據拆分為特徵和響應
responses, trainData = np.hsplit(train,[1])
labels, testData = np.hsplit(test,[1])
# 初始化kNN, 分類, 測量準確性
knn = cv.ml.KNearest_create()
knn.train(trainData, cv.ml.ROW_SAMPLE, responses)
ret, result, neighbours, dist = knn.findNearest(testData, k=5)
correct = np.count_nonzero(result == labels)
accuracy = correct*100.0/10000
print( accuracy )/<code>

它給我的準確性為93.22%。同樣,如果要提高準確性,則可以迭代地在每個級別中添加錯誤數據。


分享到:


相關文章: