2016-04-19 2 views
1

tl; dr Мои данные обучения и реальные данные KNearest не имеют одинаковых размеров и приводят к сбою моего приложения. Я подозреваю, что мой метод preProces того, как я создаю свои данные обучения (drawable resource => bitmap => opencv matrix), является причиной сбоя. Кто-нибудь из вас знает решение?Как нормализовать матрицы OpenCV Android?

Я пытаюсь получить рабочую демонстрацию простого приложения OCR с OpenCV для Android. Я использую сборку в KNearest для распознавания символов. Прежде чем объект KNearest способен обнаруживать что-либо, он должен быть обучен. Для обучения я использую несколько контуров символов.

A black background with the outline of a 0 Это один из них (его ноль).

Обучение, похоже, неудивительно, что оно способно обнаруживать предполагаемые значения учебных образов. Хотелось бы, чтобы он сделал это и с другими изображениями (или на листе не разбил мое приложение). Это то, что я сделал, чтобы обучить KNearest модель:

Map<Character, Integer> images = new HashMap<>(); 
images.put('0', R.drawable.training0); 

// Prepare two sets of data, the images and their values. 
Mat trainingImages = new Mat(); 
Mat trainingLabels = new Mat(); 
for (int i = 0; i < 50; i++) { 
    for (Map.Entry<Character, Integer> entry : images.entrySet()) { 
     Bitmap bitmapImage = BitmapFactory.decodeResource(
      this.getResources(), entry.getValue()); 
     Mat matImage = new Mat(); 
     Utils.bitmapToMat(bitmapImage, matImage); 

     trainingLabels.push_back(new MatOfInt(entry.getKey() - '0')); 
     trainingImages.push_back(
      preProces(
       matImage, new Rect(0, 0, matImage.width(), matImage.height()))); 
     } 
    } 

mKNearest.train(trainingImages, Ml.ROW_SAMPLE, trainingLabels); 

Метод preProces ничего не делает больше, чем нормализации матрицы. Это то, что мой preProces метод выглядит следующим образом:

private Mat preProces(Mat image, Rect poi) { 
    Mat cutout = new Mat(image, poi); 
    Mat resized = new Mat(10, 10, CvType.CV_32F); 
    Mat converted = new Mat(); 
    Imgproc.resize(cutout, resized, resized.size()); 
    resized.reshape(1, 1).convertTo(converted, CvType.CV_32F); 
    return converted; 
} 

Сегментирования изображения, чтобы найти (возможно) символы не были сложны, я был в состоянии нарисовать прямоугольник вокруг (возможные) символов. Как только это будет сделано, я просто передаю каждую точку интереса через мой метод preProces, прежде чем передать его в метод mKNearest.findNeareset(...). Это происходит, когда происходит авария. Данные обучения и реальные данные, похоже, не имеют одинаковых размеров, что должен решить метод preProces.

Мое предположение заключается в том, что либо мой метод preProces терпит неудачу, либо загрузка загружаемых ресурсов в виде растрового изображения, а затем преобразование их в матрицы является причиной его отказа. Я хотел бы знать, были ли у некоторых из вас подобные проблемы и как вы это решили.

Обновление: Похоже, что в матрицах довольно много шума, который создается из растрового изображения. Может ли это быть проблемой, если да, то как удалить шум?

ответ

0

Кажется, ответ на этот вопрос был довольно простым. Я использовал Imgproc.canny() для обнаружения краев реальных данных, но не по данным обучения. Проблема была решена после передачи данных обучения через Imgproc.canny().

... 
Bitmap bitmapImage = BitmapFactory.decodeResource(
    this.getResources(), entry.getValue()); 
Mat matImage = new Mat(); 
Utils.bitmapToMat(bitmapImage, matImage); 

// This was all I had to add to the training data preparation. 
Mat cannyImage = new Mat(); 
Imgproc.Canny(matImage, cannyImage, 1.0, 255.0); 

trainingLabels.push_back(new MatOfInt(entry.getKey() - '0')); 
trainingImages.push_back(
    preProces(
     cannyImage, new Rect(0, 0, cannyImage.width(), cannyImage.height()))); 
} 
...