2016-07-22 2 views
5

Я хочу сделать программу до узнать цифру на картинке. Я следую учебнику в scikit learn.Scikit-learn распознавание цифр SVM

Я могу поезд и посадка классификатора svm как показано ниже.

Во-первых, я импортировать библиотеки и набор данных

from sklearn import datasets, svm, metrics 

digits = datasets.load_digits() 
n_samples = len(digits.images) 
data = digits.images.reshape((n_samples, -1)) 

Во-вторых, создать модель SVM и обучать его с набором данных.

classifier = svm.SVC(gamma = 0.001) 
classifier.fit(data[:n_samples], digits.target[:n_samples]) 

И потом, я стараюсь читать свое собственное изображение и использовать функцию predict() распознавать цифры.

Вот мое изображение: enter image description here

Я перекроить изображение в (8, 8), а затем преобразовать его в 1D массив.

img = misc.imread("w1.jpg") 
img = misc.imresize(img, (8, 8)) 
img = img[:, :, 0] 

Наконец, когда я распечатать предсказание, он возвращает [1]

predicted = classifier.predict(img.reshape((1,img.shape[0]*img.shape[1]))) 
print predicted 

Независимо от пользователя я другие изображения, она по-прежнему возвращает [1]

enter image description here enter image description here

Когда я распечатываю «по умолчанию»набор данных числа„9“, это выглядит следующим образом: enter image description here

Мои изображения номер„9“:

enter image description here

Вы можете увидеть ненулевое число достаточно велико для мое изображение.

Я не знаю почему. Я ищу помощь для решения моей проблемы. Благодаря

ответ

5

Моя лучшая ставка будет заключаться в том, что существует проблема с вашими типами данных и формами массива.

Похоже, что вы тренируетесь на Numpy массивов, типа np.float64 (или, возможно, np.float32 на 32-битные системы, я не помню), и где каждое изображение имеет форму (64,).

Между тем ваше входное изображение для прогнозирования, после операции изменения размера в вашем коде, имеет тип uint8 и форму (1, 64).

Я бы сначала попытался изменить форму вашего входного изображения, так как преобразования dtype часто работают так, как вы ожидали. Так измените эту строку:

predicted = classifier.predict(img.reshape((1,img.shape[0]*img.shape[1])))

к этому:

predicted = classifier.predict(img.reshape(img.shape[0]*img.shape[1]))

Если это не исправить, вы всегда можете попробовать переделывая тип данных, а также с

img = img.astype(digits.images.dtype) ,

Я надеюсь, что это поможет. Отладка с помощью прокси-сервера намного сложнее, чем на самом деле сидеть перед вашим компьютером :)

Редактировать: согласно документации SciPy данные обучения содержат целочисленные значения от 0 до 16. Значения в исходном изображении должны быть масштабированы до соответствуют одному и тому же интервалу. (http://scikit-learn.org/stable/modules/generated/sklearn.datasets.load_digits.html#sklearn.datasets.load_digits))

+0

Спасибо, что ответили. Я попробовал ваш метод, и он не работает. Я узнал, что элементы массива моего изображения намного больше, чем набор учебных материалов. Я обновил вопрос – VICTOR

+1

Ну, похоже, вам нужно масштабировать их до диапазона 0-16: http://scikit-learn.org/stable/modules/generated/sklearn.datasets.load_digits.html#sklearn. datasets.load_digits –

+0

@CLWONG - Это решило вашу проблему? –

1

Это только предположение, но ... Учебный набор из Sk-Learn являются черные цифры на белом фоне. И вы пытаетесь предсказать числа, которые являются белыми на черном фоне ...

Думаю, вам нужно либо тренироваться на тренировочном наборе, либо тренироваться на негативной версии ваших фотографий.

Я надеюсь, что эта помощь!

+0

Спасибо за ваш ответ. Я попробовал черный фон, белый номер, он все равно возвращает 1. – VICTOR

3

1) Вам необходимо создать свой собственный набор для обучения, основанный на данных, похожих на то, что вы будете делать прогнозы. Вызов datasets.load_digits() в scikit-learn загружает предварительно обработанную версию набора данных MNIST Digits, которая, насколько нам известно, может иметь очень разные изображения для тех, которые вы пытаетесь распознать.

2) Вам необходимо правильно установить параметры вашего классификатора. Вызов svm.SVC(gamma = 0.001) - это просто выбор произвольного значения параметра гамма в SVC, что может быть не лучшим вариантом. Кроме того, вы не настраиваете параметр C, что очень важно для SVM. Я бы сказал, что это одна из причин, почему ваш вывод «всегда 1».

3) Независимо от окончательных настроек вы выбираете для вашей модели, вы должны будете использовать схему кросс-проверки, чтобы гарантировать, что алгоритм эффективно обучения

Там много машины теории за это обучение, но, как хорошее начало, я бы порекомендовал взглянуть на SVM - scikit-learn для более подробного описания того, как работает реализация SVC при работе с нарушениями слуха, и GridSearchCV для простой методики настройки параметров.

1

Если вы посмотрите на: http://scikit-learn.org/stable/modules/generated/sklearn.datasets.load_digits.html#sklearn.datasets.load_digits

вы можете увидеть, что каждая точка в матрице в качестве значения между 0-16.

Вы можете попытаться преобразовать значения изображения между 0-16. Я сделал это, и теперь прогноз хорошо подходит для цифры 9, но не для 8 и 6. Это больше не дает 1.

from sklearn import datasets, svm, metrics 
import cv2 
import numpy as np 

# Load digit database 
digits = datasets.load_digits() 
n_samples = len(digits.images) 
data = digits.images.reshape((n_samples, -1)) 

# Train SVM classifier 
classifier = svm.SVC(gamma = 0.001) 
classifier.fit(data[:n_samples], digits.target[:n_samples]) 

# Read image "9" 
img = cv2.imread("w1.jpg") 
img = img[:,:,0]; 
img = cv2.resize(img, (8, 8)) 

# Normalize the values in the image to 0-16 
minValueInImage = np.min(img) 
maxValueInImage = np.max(img) 
normaliizeImg = np.floor(np.divide((img - minValueInImage).astype(np.float),(maxValueInImage-minValueInImage).astype(np.float))*16) 

# Predict 
predicted = classifier.predict(normaliizeImg.reshape((1,normaliizeImg.shape[0]*normaliizeImg.shape[1]))) 
print predicted 
0

Привет в дополнение к @carrdelling реагировать, я добавлю, что вы можете использовать один и тот же набор обучения, если вы нормализовать изображения, чтобы иметь один и тот же диапазон значений. Например, вы можете использовать ваши данные (1, если> 0, 0 else), или вы можете разделить на максимальную интенсивность изображения, чтобы иметь произвольный интервал [0; 1].

0

Возможно, вам захочется извлечь функции, соответствующие вашему набору данных, из изображений и подготовить для них вашу модель. Один пример, который я скопировал из here.

surf = cv2.SURF(400) kp, des = surf.detectAndCompute(img,None)

Но особенности SURF не могут быть наиболее полезными или уместными для набора данных и учебной задачи. Вы должны попробовать другие, например, HOG или другие.

Помните, что на более высоком уровне функции, которые вы извлекаете из более общей/устойчивой к ошибкам, вашей модели, будут отображаться невидимыми. Тем не менее, вы можете жертвовать точностью в своих известных образцах и тестовых случаях.

1

Я решил эту проблему с помощью ниже способов:

  1. проверки количество атрибутов, слишком большой или слишком маленький.

  2. проверить масштаб вашего серого значения, изменить на [0,16].

  3. проверить тип данных, я меняю его на uint8.

  4. проверить количество учебных данных, слишком мало или нет.

Надеюсь, это поможет. ^.^

Смежные вопросы