java - 如何提高在 MNIST 上训练的模型的数字识别?

标签 java opencv machine-learning image-recognition mnist

我正在使用 Java 进行手印多数字识别,使用 OpenCV 库进行预处理和分割,并使用 Keras 模型训练MNIST(精度为 0.98)用于识别。

除一件事外,识别似乎工作得很好。网络经常无法识别那些(数字“一”)。我无法弄清楚它是否是由于预处理/分割的不正确实现而发生的,或者如果在标准 MNIST 上训练的网络只是没有看到看起来像我的测试用例的第一名。

这是预处理和分割后有问题的数字的样子:

enter image description here变成 enter image description here并被分类为 4

enter image description here变成 enter image description here并被分类为 7

enter image description here变成 enter image description here并被分类为 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);
}

最佳答案

我相信你的问题是扩张过程。我知道你希望标准化图像尺寸,但你不应该打破比例,你应该调整到一个轴所需的最大值(允许最大重新缩放而不让另一个轴尺寸超过最大尺寸的轴)并填充与图像的其余部分的背景颜色。 这并不是说“标准 MNIST 只是没有看到看起来像你的测试用例的数字”,你让你的图像看起来像不同的训练数字(被识别的数字)

Overlap of the source and processed images

如果您保持图像(源图像和后处理图像)的正确宽高比,您会发现您不仅调整了图像大小,而且还“扭曲”了图像。这可能是非均匀扩张或不正确调整大小的结果

关于java - 如何提高在 MNIST 上训练的模型的数字识别?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58398983/

相关文章:

machine-learning - Storm 是否不适合批量学习?

python - 以下xgboost模型 TreeMap 中 'leaf'的值是什么意思?

machine-learning - 如何在 sklearn::LGBMClassifier() 中的 LightGBM 分类器的 feature_importances_ 中将 'gain' 设置为特征重要性度量

java - main方法可以放在父类中吗?如果是这样,可以在该 main 方法中实例化子对象吗?

java - 如何在 Spring 的一个 ConstraintValidator 中同时验证 @PathVariable 和 @RequestBody?

qt - Opencv使用QString文件名的imread和vector加载图像

python - 跟踪相同颜色的多个对象

java - 从数组中获取每个元素并将其放入不同的 JTable 行中

java - tomcat的默认缓存 header ?

python-3.x - 如何在keras预处理器中传递数组而不是路径