Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in / Register
Toggle navigation
O
opencv
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Packages
Packages
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
submodule
opencv
Commits
2186ec76
Commit
2186ec76
authored
May 22, 2017
by
Alexander Alekhin
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #8754 from berak:fix_py_hog_svm_tut
parents
aea846ad
2af63c2b
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
81 additions
and
93 deletions
+81
-93
py_svm_opencv.markdown
...torials/py_ml/py_svm/py_svm_opencv/py_svm_opencv.markdown
+10
-93
hogsvm.py
samples/python/tutorial_code/ml/py_svm_opencv/hogsvm.py
+71
-0
No files found.
doc/py_tutorials/py_ml/py_svm/py_svm_opencv/py_svm_opencv.markdown
View file @
2186ec76
...
...
@@ -17,16 +17,9 @@ vectors.
Here, before finding the HOG, we deskew the image using its second order moments. So we first define
a function
**deskew()**
which takes a digit image and deskew it. Below is the deskew() function:
@code{.py}
def deskew(img):
m = cv2.moments(img)
if abs(m
[
'mu02'
]
) < 1e-2:
return img.copy()
skew = m
[
'mu11'
]
/m
[
'mu02'
]
M = np.float32(
[
[1, skew, -0.5*SZ*skew
]
,
[
0, 1, 0
]
])
img = cv2.warpAffine(img,M,(SZ, SZ),flags=affine_flags)
return img
@endcode
@snippet samples/python/tutorial_code/ml/py_svm_opencv/hogsvm.py deskew
Below image shows above deskew function applied to an image of zero. Left image is the original
image and right image is the deskewed image.
...
...
@@ -38,91 +31,15 @@ gradient is quantized to 16 integer values. Divide this image to four sub-square
sub-square, calculate the histogram of direction (16 bins) weighted with their magnitude. So each
sub-square gives you a vector containing 16 values. Four such vectors (of four sub-squares) together
gives us a feature vector containing 64 values. This is the feature vector we use to train our data.
@code{.py}
def hog(img):
gx = cv2.Sobel(img, cv2.CV_32F, 1, 0)
gy = cv2.Sobel(img, cv2.CV_32F, 0, 1)
mag, ang = cv2.cartToPolar(gx, gy)
# quantizing binvalues in (0...16)
bins = np.int32(bin_n*ang/(2*np.pi))
# Divide to 4 sub-squares
bin_cells = bins[:10,:10], bins[10:,:10], bins[:10,10:], bins[10:,10:]
mag_cells = mag[:10,:10], mag[10:,:10], mag[:10,10:], mag[10:,10:]
hists = [np.bincount(b.ravel(), m.ravel(), bin_n) for b, m in zip(bin_cells, mag_cells)]
hist = np.hstack(hists)
return hist
@endcode
@snippet samples/python/tutorial_code/ml/py_svm_opencv/hogsvm.py hog
Finally, as in the previous case, we start by splitting our big dataset into individual cells. For
every digit, 250 cells are reserved for training data and remaining 250 data is reserved for
testing. Full code is given below:
@code{.py}
import cv2
import numpy as np
SZ=20
bin_n = 16 # Number of bins
affine_flags = cv2.WARP_INVERSE_MAP|cv2.INTER_LINEAR
def deskew(img):
m = cv2.moments(img)
if abs(m
[
'mu02'
]
) < 1e-2:
return img.copy()
skew = m
[
'mu11'
]
/m
[
'mu02'
]
M = np.float32(
[
[1, skew, -0.5*SZ*skew
]
,
[
0, 1, 0
]
])
img = cv2.warpAffine(img,M,(SZ, SZ),flags=affine_flags)
return img
def hog(img):
gx = cv2.Sobel(img, cv2.CV_32F, 1, 0)
gy = cv2.Sobel(img, cv2.CV_32F, 0, 1)
mag, ang = cv2.cartToPolar(gx, gy)
bins = np.int32(bin_n
*ang/(2*
np.pi)) # quantizing binvalues in (0...16)
bin_cells = bins
[
:10,:10
]
, bins
[
10:,:10
]
, bins
[
:10,10:
]
, bins
[
10:,10:
]
mag_cells = mag
[
:10,:10
]
, mag
[
10:,:10
]
, mag
[
:10,10:
]
, mag
[
10:,10:
]
hists =
[
np.bincount(b.ravel(), m.ravel(), bin_n) for b, m in zip(bin_cells, mag_cells)
]
hist = np.hstack(hists) # hist is a 64 bit vector
return hist
img = cv2.imread('digits.png',0)
cells =
[
np.hsplit(row,100) for row in np.vsplit(img,50)
]
# First half is trainData, remaining is testData
train_cells =
[
i[:50
]
for i in cells ]
test_cells =
[
i[50:
]
for i in cells]
###### Now training ########################
deskewed =
[
map(deskew,row) for row in train_cells
]
hogdata =
[
map(hog,row) for row in deskewed
]
trainData = np.float32(hogdata).reshape(-1,64)
responses = np.float32(np.repeat(np.arange(10),250)
[
:,np.newaxis
]
)
svm = cv2.ml.SVM_create()
svm.setKernel(cv2.ml.SVM_LINEAR)
svm.setType(cv2.ml.SVM_C_SVC)
svm.setC(2.67)
svm.setGamma(5.383)
svm.train(trainData, cv2.ml.ROW_SAMPLE, responses)
svm.save('svm_data.dat')
###### Now testing ########################
deskewed =
[
map(deskew,row) for row in test_cells
]
hogdata =
[
map(hog,row) for row in deskewed
]
testData = np.float32(hogdata).reshape(-1,bin_n
*
4)
result = svm.predict(testData)
####### Check Accuracy ########################
mask = result==responses
correct = np.count_nonzero(mask)
print correct
*
100.0/result.size
@endcode
testing. Full code is given below, you also can download it from
[
here
](
https://github.com/opencv/opencv/tree/master/samples/python/tutorial_code/ml/py_svm_opencv/hogsvm.py
)
:
@include samples/python/tutorial_code/ml/py_svm_opencv/hogsvm.py
This particular technique gave me nearly 94% accuracy. You can try different values for various
parameters of SVM to check if higher accuracy is possible. Or you can read technical papers on this
area and try to implement them.
...
...
samples/python/tutorial_code/ml/py_svm_opencv/hogsvm.py
0 → 100644
View file @
2186ec76
import
cv2
import
numpy
as
np
SZ
=
20
bin_n
=
16
# Number of bins
affine_flags
=
cv2
.
WARP_INVERSE_MAP
|
cv2
.
INTER_LINEAR
## [deskew]
def
deskew
(
img
):
m
=
cv2
.
moments
(
img
)
if
abs
(
m
[
'mu02'
])
<
1e-2
:
return
img
.
copy
()
skew
=
m
[
'mu11'
]
/
m
[
'mu02'
]
M
=
np
.
float32
([[
1
,
skew
,
-
0.5
*
SZ
*
skew
],
[
0
,
1
,
0
]])
img
=
cv2
.
warpAffine
(
img
,
M
,(
SZ
,
SZ
),
flags
=
affine_flags
)
return
img
## [deskew]
## [hog]
def
hog
(
img
):
gx
=
cv2
.
Sobel
(
img
,
cv2
.
CV_32F
,
1
,
0
)
gy
=
cv2
.
Sobel
(
img
,
cv2
.
CV_32F
,
0
,
1
)
mag
,
ang
=
cv2
.
cartToPolar
(
gx
,
gy
)
bins
=
np
.
int32
(
bin_n
*
ang
/
(
2
*
np
.
pi
))
# quantizing binvalues in (0...16)
bin_cells
=
bins
[:
10
,:
10
],
bins
[
10
:,:
10
],
bins
[:
10
,
10
:],
bins
[
10
:,
10
:]
mag_cells
=
mag
[:
10
,:
10
],
mag
[
10
:,:
10
],
mag
[:
10
,
10
:],
mag
[
10
:,
10
:]
hists
=
[
np
.
bincount
(
b
.
ravel
(),
m
.
ravel
(),
bin_n
)
for
b
,
m
in
zip
(
bin_cells
,
mag_cells
)]
hist
=
np
.
hstack
(
hists
)
# hist is a 64 bit vector
return
hist
## [hog]
img
=
cv2
.
imread
(
'digits.png'
,
0
)
if
img
is
None
:
raise
Exception
(
"we need the digits.png image from samples/data here !"
)
cells
=
[
np
.
hsplit
(
row
,
100
)
for
row
in
np
.
vsplit
(
img
,
50
)]
# First half is trainData, remaining is testData
train_cells
=
[
i
[:
50
]
for
i
in
cells
]
test_cells
=
[
i
[
50
:]
for
i
in
cells
]
###### Now training ########################
deskewed
=
[
map
(
deskew
,
row
)
for
row
in
train_cells
]
hogdata
=
[
map
(
hog
,
row
)
for
row
in
deskewed
]
trainData
=
np
.
float32
(
hogdata
)
.
reshape
(
-
1
,
64
)
responses
=
np
.
repeat
(
np
.
arange
(
10
),
250
)[:,
np
.
newaxis
]
svm
=
cv2
.
ml
.
SVM_create
()
svm
.
setKernel
(
cv2
.
ml
.
SVM_LINEAR
)
svm
.
setType
(
cv2
.
ml
.
SVM_C_SVC
)
svm
.
setC
(
2.67
)
svm
.
setGamma
(
5.383
)
svm
.
train
(
trainData
,
cv2
.
ml
.
ROW_SAMPLE
,
responses
)
svm
.
save
(
'svm_data.dat'
)
###### Now testing ########################
deskewed
=
[
map
(
deskew
,
row
)
for
row
in
test_cells
]
hogdata
=
[
map
(
hog
,
row
)
for
row
in
deskewed
]
testData
=
np
.
float32
(
hogdata
)
.
reshape
(
-
1
,
bin_n
*
4
)
result
=
svm
.
predict
(
testData
)[
1
]
####### Check Accuracy ########################
mask
=
result
==
responses
correct
=
np
.
count_nonzero
(
mask
)
print
correct
*
100.0
/
result
.
size
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment