Я працюю над роздрукованим вручну багатозначним розпізнаванням Java
, використовуючи OpenCV
бібліотеку для попередньої обробки та сегментації, і Keras
модель, навчену на MNIST (з точністю 0,98) для розпізнавання.
Розпізнавання, здається, працює досить добре, крім однієї речі. Мережа досить часто не впізнає їх (номер "один"). Я не можу зрозуміти, чи це відбувається через попередню обробку / неправильну реалізацію сегментації, або якщо мережа, що навчається на стандартному MNIST, просто не бачила номер один, який схожий на мої тестові випадки.
Ось як виглядають проблемні цифри після попередньої обробки та сегментації:
стає і класифікується як 4
. І так далі...
Це щось, що можна було б виправити, покращивши процес сегментації? А точніше, покращуючи навчальний набір?
Редагувати: Покращення навчального набору (збільшення даних) безумовно допоможе, що я вже тестую, питання правильної попередньої обробки ще залишається.
Моя попередня обробка складається з зміни розміру, перетворення в масштаб сірого, бінаризації, інверсії та розширення. Ось код:
Mat resized = new Mat();
Imgproc.resize(image, resized, new Size(), 8, 8, Imgproc.INTER_CUBIC);
Mat grayscale = new Mat();
Imgproc.cvtColor(resized, grayscale, Imgproc.COLOR_BGR2GRAY);
Mat binImg = new Mat(grayscale.size(), CvType.CV_8U);
Imgproc.threshold(grayscale, binImg, 0, 255, Imgproc.THRESH_OTSU);
Mat inverted = new Mat();
Core.bitwise_not(binImg, inverted);
Mat dilated = new Mat(inverted.size(), CvType.CV_8U);
int dilation_size = 5;
Mat kernel = Imgproc.getStructuringElement(Imgproc.CV_SHAPE_CROSS, new Size(dilation_size, dilation_size));
Imgproc.dilate(inverted, dilated, kernel, new Point(-1,-1), 1);
Попередньо оброблене зображення потім сегментується на окремі цифри наступним чином:
List<Mat> digits = new ArrayList<>();
List<MatOfPoint> contours = new ArrayList<>();
Imgproc.findContours(preprocessed.clone(), contours, new Mat(), Imgproc.RETR_EXTERNAL, Imgproc.CHAIN_APPROX_SIMPLE);
// code to sort contours
// code to check that contour is a valid char
List rects = new ArrayList<>();
for (MatOfPoint contour : contours) {
Rect boundingBox = Imgproc.boundingRect(contour);
Rect rectCrop = new Rect(boundingBox.x, boundingBox.y, boundingBox.width, boundingBox.height);
rects.add(rectCrop);
}
for (int i = 0; i < rects.size(); i++) {
Rect x = (Rect) rects.get(i);
Mat digit = new Mat(preprocessed, x);
int border = 50;
Mat result = digit.clone();
Core.copyMakeBorder(result, result, border, border, border, border, Core.BORDER_CONSTANT, new Scalar(0, 0, 0));
Imgproc.resize(result, result, new Size(28, 28));
digits.add(result);
}