~paparazzi-uav/paparazzi/v5.0-manual

« back to all changes in this revision

Viewing changes to sw/ext/opencv_bebop/opencv/doc/py_tutorials/py_ml/py_knn/py_knn_opencv/py_knn_opencv.markdown

  • Committer: Paparazzi buildbot
  • Date: 2016-05-18 15:00:29 UTC
  • Revision ID: felix.ruess+docbot@gmail.com-20160518150029-e8lgzi5kvb4p7un9
Manual import commit 4b8bbb730080dac23cf816b98908dacfabe2a8ec from v5.0 branch.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
OCR of Hand-written Data using kNN {#tutorial_py_knn_opencv}
 
2
==================================
 
3
 
 
4
Goal
 
5
----
 
6
 
 
7
In this chapter
 
8
    -   We will use our knowledge on kNN to build a basic OCR application.
 
9
    -   We will try with Digits and Alphabets data available that comes with OpenCV.
 
10
 
 
11
OCR of Hand-written Digits
 
12
--------------------------
 
13
 
 
14
Our goal is to build an application which can read the handwritten digits. For this we need some
 
15
train_data and test_data. OpenCV comes with an image digits.png (in the folder
 
16
opencv/samples/data/) which has 5000 handwritten digits (500 for each digit). Each digit is
 
17
a 20x20 image. So our first step is to split this image into 5000 different digits. For each digit,
 
18
we flatten it into a single row with 400 pixels. That is our feature set, ie intensity values of all
 
19
pixels. It is the simplest feature set we can create. We use first 250 samples of each digit as
 
20
train_data, and next 250 samples as test_data. So let's prepare them first.
 
21
@code{.py}
 
22
import numpy as np
 
23
import cv2
 
24
from matplotlib import pyplot as plt
 
25
 
 
26
img = cv2.imread('digits.png')
 
27
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
 
28
 
 
29
# Now we split the image to 5000 cells, each 20x20 size
 
30
cells = [np.hsplit(row,100) for row in np.vsplit(gray,50)]
 
31
 
 
32
# Make it into a Numpy array. It size will be (50,100,20,20)
 
33
x = np.array(cells)
 
34
 
 
35
# Now we prepare train_data and test_data.
 
36
train = x[:,:50].reshape(-1,400).astype(np.float32) # Size = (2500,400)
 
37
test = x[:,50:100].reshape(-1,400).astype(np.float32) # Size = (2500,400)
 
38
 
 
39
# Create labels for train and test data
 
40
k = np.arange(10)
 
41
train_labels = np.repeat(k,250)[:,np.newaxis]
 
42
test_labels = train_labels.copy()
 
43
 
 
44
# Initiate kNN, train the data, then test it with test data for k=1
 
45
knn = cv2.KNearest()
 
46
knn.train(train,train_labels)
 
47
ret,result,neighbours,dist = knn.find_nearest(test,k=5)
 
48
 
 
49
# Now we check the accuracy of classification
 
50
# For that, compare the result with test_labels and check which are wrong
 
51
matches = result==test_labels
 
52
correct = np.count_nonzero(matches)
 
53
accuracy = correct*100.0/result.size
 
54
print accuracy
 
55
@endcode
 
56
So our basic OCR app is ready. This particular example gave me an accuracy of 91%. One option
 
57
improve accuracy is to add more data for training, especially the wrong ones. So instead of finding
 
58
this training data everytime I start application, I better save it, so that next time, I directly
 
59
read this data from a file and start classification. You can do it with the help of some Numpy
 
60
functions like np.savetxt, np.savez, np.load etc. Please check their docs for more details.
 
61
@code{.py}
 
62
# save the data
 
63
np.savez('knn_data.npz',train=train, train_labels=train_labels)
 
64
 
 
65
# Now load the data
 
66
with np.load('knn_data.npz') as data:
 
67
    print data.files
 
68
    train = data['train']
 
69
    train_labels = data['train_labels']
 
70
@endcode
 
71
In my system, it takes around 4.4 MB of memory. Since we are using intensity values (uint8 data) as
 
72
features, it would be better to convert the data to np.uint8 first and then save it. It takes only
 
73
1.1 MB in this case. Then while loading, you can convert back into float32.
 
74
 
 
75
OCR of English Alphabets
 
76
------------------------
 
77
 
 
78
Next we will do the same for English alphabets, but there is a slight change in data and feature
 
79
set. Here, instead of images, OpenCV comes with a data file, letter-recognition.data in
 
80
opencv/samples/cpp/ folder. If you open it, you will see 20000 lines which may, on first sight, look
 
81
like garbage. Actually, in each row, first column is an alphabet which is our label. Next 16 numbers
 
82
following it are its different features. These features are obtained from [UCI Machine Learning
 
83
Repository](http://archive.ics.uci.edu/ml/). You can find the details of these features in [this
 
84
page](http://archive.ics.uci.edu/ml/datasets/Letter+Recognition).
 
85
 
 
86
There are 20000 samples available, so we take first 10000 data as training samples and remaining
 
87
10000 as test samples. We should change the alphabets to ascii characters because we can't work with
 
88
alphabets directly.
 
89
@code{.py}
 
90
import cv2
 
91
import numpy as np
 
92
import matplotlib.pyplot as plt
 
93
 
 
94
# Load the data, converters convert the letter to a number
 
95
data= np.loadtxt('letter-recognition.data', dtype= 'float32', delimiter = ',',
 
96
                    converters= {0: lambda ch: ord(ch)-ord('A')})
 
97
 
 
98
# split the data to two, 10000 each for train and test
 
99
train, test = np.vsplit(data,2)
 
100
 
 
101
# split trainData and testData to features and responses
 
102
responses, trainData = np.hsplit(train,[1])
 
103
labels, testData = np.hsplit(test,[1])
 
104
 
 
105
# Initiate the kNN, classify, measure accuracy.
 
106
knn = cv2.KNearest()
 
107
knn.train(trainData, responses)
 
108
ret, result, neighbours, dist = knn.find_nearest(testData, k=5)
 
109
 
 
110
correct = np.count_nonzero(result == labels)
 
111
accuracy = correct*100.0/10000
 
112
print accuracy
 
113
@endcode
 
114
It gives me an accuracy of 93.22%. Again, if you want to increase accuracy, you can iteratively add
 
115
error data in each level.
 
116
 
 
117
Additional Resources
 
118
--------------------
 
119
 
 
120
Exercises
 
121
---------