I got an SVM for Handwritten Digit Recognition from the OpenCV Docs website. The utilization part I got from this link: How to implement .dat file for handwritten recognition using SVM in Python. I edited it to fit the code that I got from the website. Here is the code that I am using:
import cv2 as cv
import numpy as np
SZ=20
bin_n = 16 # Number of bins
affine_flags = cv.WARP_INVERSE_MAP|cv.INTER_LINEAR
def deskew(img):
m = cv.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 = cv.warpAffine(img,M,(SZ, SZ),flags=affine_flags)
return img
def hog(img):
gx = cv.Sobel(img, cv.CV_32F, 1, 0)
gy = cv.Sobel(img, cv.CV_32F, 0, 1)
mag, ang = cv.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 = cv.imread('digits2.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]
deskewed = [list(map(deskew,row)) for row in train_cells]
hogdata = [list(map(hog,row)) for row in deskewed]
trainData = np.float32(hogdata).reshape(-1,64)
responses = np.repeat(np.arange(10),250)[:,np.newaxis]
svm = cv.ml.SVM_create()
svm.setKernel(cv.ml.SVM_LINEAR)
svm.setType(cv.ml.SVM_C_SVC)
svm.setC(2.67)
svm.setGamma(5.383)
svm.train(trainData, cv.ml.ROW_SAMPLE, responses)
svm.save('svm_data.dat')
deskewed = [list(map(deskew,row)) for row in test_cells]
hogdata = [list(map(hog,row)) for row in deskewed]
testData = np.float32(hogdata).reshape(-1,bin_n*4)
result = svm.predict(testData)[1]
mask = result==responses
correct = np.count_nonzero(mask)
img_predict1 = cv.imread('predict2.png', 0)
img_predict2 = np.invert(img_predict1)
img_predict3 = cv.resize(img_predict2, (20, 20), interpolation=cv.INTER_CUBIC)
img_predict_ready = np.float32(hog(deskew(img_predict3)))
svm = cv.ml.SVM_load("svm_data.dat")
prediction = svm.predict(img_predict_ready)
print(int(prediction))
When I run it, the program is able to train a .dat file, but when trying to use that .dat file, it gives me this error:
Traceback (most recent call last):
File "C:\Users\Austin\source\repos\SVMTEST2\SVMTEST2\SVMTRAIN.py", line 54, in <module>
prediction = svm.predict(img_predict_ready)
cv2.error: OpenCV(4.2.0) C:\projects\opencv-python\opencv\modules\ml\src\svm.cpp:2013: error: (-215:Assertion failed) samples.cols == var_count && samples.type() == CV_32F in function 'cv::ml::SVMImpl::predict'
I am still very new to Python and wanted to try this out, so any help would be greatly appreciated, thank you! (please). (On Windows 10 using Visual Studio Community 2017).
The Utilization/Test Image, Image Used For Training
And here is the .dat file that comes out of the training part (hosted on GDrive): https://drive.google.com/file/d/1U9z0FGQ0FJ_3MV_p_5et6Lsebjl9e3DE/view?usp=sharing