Машинное обучение в компьютерном зрении Филимонов Алексей Катаев Александр Singularis Lab, LLC Найди кота! 22 - 24 октября, Москва 2 Что это? 22 - 24 октября, Москва 3 Как мы видим Классификация Локализация Детектирование Сегментация 22 - 24 октября, Москва 4 Признаки объектов Цвет Текстура Форма *Динамика ***Структура объекта *****Контекст (сцена) 22 - 24 октября, Москва 5 Дерево решений Желтое? Гладкий и блестящий? Круглое? Земля! Монотонная текстура? Гамбургер! 22 - 24 октября, Москва Лимон! Теннисный мяч! Лайм! 6 Пространство признаков Многоцветность Гамбургеры Лимоны Лаймы Желтизна 22 - 24 октября, Москва 7 Пространство признаков 22 - 24 октября, Москва 8 Классификация ? 22 - 24 октября, Москва 9 Ближайший сосед 22 - 24 октября, Москва 10 K ближайших соседей 22 - 24 октября, Москва 11 K ближайших соседей 22 - 24 октября, Москва 12 Линейное разделение 22 - 24 октября, Москва 13 Оптимальная гиперплоскость 22 - 24 октября, Москва 14 Опорные вектора 22 - 24 октября, Москва 15 Нелинейное разделение признак 22 - 24 октября, Москва 16 признак^2 Нелинейное разделение признак 22 - 24 октября, Москва 17 Простой пример: распознавание символов 22 - 24 октября, Москва 18 Распознавание символов: простой пример? 22 - 24 октября, Москва 19 THE MNIST DATABASE of handwritten digits 22 - 24 октября, Москва 20 Растр 22 - 24 октября, Москва 21 Загрузка данных images_with_labels = [] path = 'd:/_databases/digits/' # Загрузка большого количества картинок - затратный процесс, # для оптимизации сохраняем загруженные массивы данных в файл, UseFiles = False #True для загрузки из заранее подготовленных файлов if UseFiles: images_with_labels = np.load(path+"digits1000.npy") else: for num in range(0,10): k = 0 for (dirpath, dirnames, filenames) in walk(path+str(num)): for filename in filenames: image = cv2.imread(dirpath+'/'+filename,0) images_with_labels.append( (image, num) ); k+=1 if k >= 1000: break np.save(path+"digits1000.npy", images_with_labels) # размеры изображения W = images_with_labels[0][0].shape[1] H = images_with_labels[0][0].shape[0] 22 - 24 октября, Москва 23 Подготовка выборок NTrain = 70 NTest = 100 - NTrain # 70% в обучающую выборку # Остальные в тестовую выборку train = [] test = [] for i in range(0, len(images_with_labels)-len(images_with_labels) % 100, 1 00): train.extend(images_with_labels[i:i+NTrain]) test.extend(images_with_labels[i+NTrain:i+100]) # разбиваем каждую выборку на на 2 массива: данные и метки train, train_labels = zip(*train) test, test_labels = zip(*test) # преобразуем списки в Numpy массивы train = np.array(train) test = np.array(test) train_labels = np.array(train_labels).reshape(-1, 1) test_labels = np.array(test_labels).reshape(-1, 1) print 'Размер обучающей выборки: ', train.shape[0] print 'Размер тестовой выборки: ', test.shape[0] 22 - 24 октября, Москва 24 Загрузка картинок # Выбираем по одному изображению каждой цифры для визуализации test_subset = [next(index for index in range(1,len(test)) if test_labels[inde x] == num) for num in range(0,10)] #рисуем выбранные цифры plt.figure(1) f, axarr = plt.subplots(1,10,figsize=(5,5)) for i in range (0,10): axarr[i].imshow(test[test_subset[i]],cmap = cm.Greys_r) axarr[i].axis('off') plt.show() 22 - 24 октября, Москва 25 Обучение kNN # вытягиваем все картинку в линию train_data = train.reshape(-1,W*H).astype(np.float32) # Создаем и обучаем классификатор knn = cv2.KNearest() tstart = dt.datetime.now() knn.train(train_data,train_labels) telapsed = dt.datetime.now() - tstart print "Время обучения: ", telapsed.total_seconds() Время обучения: 0.011 22 - 24 октября, Москва 26 Тестирование kNN test_data = test.reshape(-1,W*H).astype(np.float32) # Классификация тестовой выборки и оценка ошибки tstart = dt.datetime.now() ret,result,neighbours,dist = knn.find_nearest(test_data,k=3) telapsed = dt.datetime.now() - tstart correct = np.count_nonzero(result==test_labels) print "kNN accuracy = ", correct*100.0/result.size print "Время тестирования: ", telapsed.total_seconds() kNN accuracy = 93.8333333333 Время тестирования: 20.932 22 - 24 октября, Москва 27 Тестирование kNN #Визуализация части результата plt.figure(1) f, axarr = plt.subplots(1,10,figsize=(5,5)) for i in range (0,10): axarr[i].imshow(test[test_subset[i]],cmap = cm.Greys_r) axarr[i].axis('off') axarr[i].set_title(result[test_subset[i]]) plt.show() 22 - 24 октября, Москва 28 Обучение SVM svm_params = dict( kernel_type = cv2.SVM_POLY, svm_type = cv2.SVM_C_SVC, degree=2, C=1, gamma=1 ) svm = cv2.SVM() tstart = dt.datetime.now() svm.train(train_data,train_labels, params=svm_params) telapsed = dt.datetime.now() - tstart print "Время обучения: ", telapsed.total_seconds() Время обучения: 6.516 22 - 24 октября, Москва 29 Тестирование SVM test_data = test.reshape(-1,W*H).astype(np.float32) tstart = dt.datetime.now() result_svm = svm.predict_all(test_data) telapsed = dt.datetime.now() - tstart correct = np.count_nonzero(result_svm==test_labels) print "SVM accuracy = ", correct*100.0/result.size print "Время тестирования: ", telapsed.total_seconds() SVM accuracy = 95.1333333333 Время тестирования: 3.686 22 - 24 октября, Москва 30 Пример с распознаванием маркеров Реализовать обучение системы по фотографиям маркеров Подготовка: 0. Загрузить базу фотографий маркеров и обучить классификатор на ней Для каждого кадра: 1. Найти координаты маркера 2. Вычислить трансформацию маркера и восстановить его форму 3. Классифицировать маркер с помощью обученного классификатора 4. Вычислить трансформацию изображения для совмещения с маркером 5. Вывести изображение поверх маркера 6. Отобразить результат на экране 22 - 24 октября, Москва 31 Создание базы маркеров 1. Сохраняем изображения, получаемые с камеры: static int counter = 0; counter ++; char name[100]; sprintf(name, "data\\m\\%04.png", counter); imwrite(name, markerImage); 2. Сортируем вручную 22 - 24 октября, Москва 32 Загрузка изображений маркеров char *classes[] = { "cat", "apple", "rob" }; Mat data, labels; Size markerSize; // Загружаем файлы, вытягиваем их в строку и вставляем в матрицу data for ( int c = 0; c < 3; ++ c ) { for ( int i = 0; i < 150; ++ i ) { char name[100]; sprintf(name, "data\\m\\%s-%04i.png", classes[c],i+1); Mat im = imread( name ); if ( !im.empty() ) { if ( data.empty() ) { data = im.reshape(1, 1); labels = Mat::zeros(1,1,CV_32F); } else { vconcat(data, im.reshape(1, 1), data); vconcat(labels, Mat::ones(1,1,CV_32F)*c, labels); } markerSize = im.size(); } } } 22 - 24 октября, Москва 33 Обучение и идентификация маркера // Обучение классификатора data.convertTo(data, CV_32F); auto train_data = ml::TrainData::create( data, ml::SampleTypes::ROW_SAMPLE, labels); auto knn = ml::KNearest::create(); knn->train(train_data); // Выбор маркера с помощью классификатора Mat data; marker.reshape(1,1).convertTo(data, CV_32F); int bestIndex = knn->findNearest(data, 1, noArray()); 22 - 24 октября, Москва 34 Признаки изображений • • • • • • • • • Значения цвета и яркости пикселей Моменты Направления градиентов Гистограммы градиентов (HOG) Гистограммы цветовых компонент Свертки различными ядрами LBP Haar … 22 - 24 октября, Москва 35 Спасибо за внимание Алексей Филимонов • [email protected] Александр Катаев • [email protected] 36