I'm working with this data set, which Is slightly unbalanced across the letter classes: https://github.com/tuptaker/uppercase...
I've tried to adapt the examples described in this tutorial: https://docs.opencv.org/trunk/d8/d4b/...
Specifically, I'm focused on adapting the first example for digits since I don't have a *.data file for handwritten letters but, rather, a sample of ~12K handwritten letters represented as *.png files.
As I load in my samples, I bucket them roughly evenly into training and testing data (and labels), respectively, after which I do the requisite resizing, reshaping, etc.
Unfortunately, I'm getting 0 matches during the testing step and am having a tough time trying to find where I went wrong. Can someone have a look at my code below?
import cv2
import numpy as np import matplotlib.pyplot as plt import time import glob from random import shuffle import os
class LetterRecognizer: __debugging_data_path = "./debugging_data" __letter_images_dir = "./letters_upper" __letters_for_training = [] __letters_for_testing = []
def __init__(self):
self.knn_model = cv2.ml.KNearest_create()
print("HWR-ICR-ENG: LetterRecognizer: initialized.")
def create_trained_knn_model(self):
#letter_arr = self.__load_uppercase_data()
training_labels_raw, \
training_data_raw, \
testing_labels_raw, \
testing_data_raw = self.__load_uppercase_data_and_labels()
gray_training_data = [cv2.cvtColor(letter, cv2.COLOR_BGR2GRAY)
for letter in training_data_raw]
gray_testing_data = [cv2.cvtColor(letter, cv2.COLOR_BGR2GRAY)
for letter in testing_data_raw]
gray_training_data_20_by_20 = [cv2.resize(letter, (20, 20))
for letter in gray_training_data]
gray_testing_data_20_by_20 = [cv2.resize(letter, (20, 20))
for letter in gray_testing_data]
# shape is (6245, 20, 20)
training_data_np = np.array(gray_training_data_20_by_20)
training_data = training_data_np[:,:6245].reshape(-1,400).astype(np.float32)
# shape is (6234, 20, 20)
testing_data_np = np.array(gray_testing_data_20_by_20)
testing_data = training_data_np[:,:6234].reshape(-1,400).astype(np.float32)
training_label_np = np.array(training_labels_raw)
testing_label_np = np.array(testing_labels_raw)
training_labels = np.repeat(training_labels_raw, 1)[:, np.newaxis]
testing_labels = np.repeat(testing_labels_raw, 1)[:, np.newaxis]
# Initiate kNN, train the data, then test it with test data for k=1
self.knn_model = cv2.ml.KNearest_create()
training_start_time = time.clock()
self.knn_model.train(training_data, cv2.ml.ROW_SAMPLE, training_labels)
print("HWR-ICR-ENG: Letter Recognizer: Training duration: ", time.clock() - training_start_time)
testing_start_time = time.clock()
ret,result,neighbours,dist = self.knn_model.findNearest(testing_data, k = 5)
print("HWR-ICR-ENG: Letter Recognizer: Testing duration: ", time.clock() - testing_start_time)
# Now we check the accuracy of classification
# For that, compare the result with test_labels and check which are wrong
matches = result == testing_labels
correct = np.count_nonzero(matches)
accuracy = correct*100.0/result.size
return self.knn_model, accuracy
def __load_uppercase_data_and_labels(self):
training_labels = []
training_data = []
testing_labels = []
testing_data = []
for letter_label, (subdir, dirs, files) in enumerate(os.walk(self.__letter_images_dir)):
for letter_index, (file) in enumerate(files):
if file.endswith('.png'):
if letter_index % 2 is 0:
training_labels.append(letter_label)
training_data.append(cv2.imread(os.path.join(subdir, file)))
else:
testing_labels.append(letter_label)
testing_data.append(cv2.imread(os.path.join(subdir, file)))
return training_labels, training_data, testing_labels, testing_data