Ask Your Question

Revision history [back]

click to hide/show revision 1
initial version

K-Nearest for handwritten letters

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

K-Nearest for handwritten letters

I'm working with this data set, which Is slightly unbalanced across the letter classes: https://github.com/tuptaker/uppercase...link text

I've tried to adapt the examples described in this tutorial: https://docs.opencv.org/trunk/d8/d4b/...link text

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