android - 如何标准化 OpenCV Android 矩阵?

标签 android opencv opencv3.0

tl;dr 我的 KNearest 训练数据和真实数据的维度不同,导致我的应用程序崩溃。我怀疑我的 preProces 方法或我实例化训练数据的方式(drawable resource => bitmap => opencv matrix)是失败的原因。你们有人知道解决方案吗?

我一直在尝试使用适用于 Android 的 OpenCV 获得一个简单的 OCR 应用程序的工作演示。我使用 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 方法失败或者加载可绘制资源作为位图然后将它们转换为矩阵是它失败的原因。我想知道你们中是否有人遇到过类似的问题以及你们是如何解决的。

更新: 从位图创建的矩阵中似乎有相当多的噪音。这可能是问题所在吗?如果是,如何消除噪音?

最佳答案

看来这个问题的答案很简单。我使用 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())));
}
...

关于android - 如何标准化 OpenCV Android 矩阵?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36722023/

相关文章:

android - 在没有第三方库的情况下将图像从网络加载到网格

android - 从 Android 的 LocationManager 请求 getLastKnownLocation 时的空指针

c++ - vector Mat 的 opencv 切片

python-3.x - 如何使用opencv通过xmax xmin ymax ymin编写矩形(边界框)

javascript - Angularjs 搜索整个 HTML

java - 作为任何 RX 操作符调用 java 类内部的扩展函数

c++ - 在 vector 的 vector 中找到 Point3f 的最大值

c++ - 计算给定两组点的相似变换矩阵?

Java-OpenCV错误: Assertion failed while running FaceRecognition Program

python - BGR在OpenCV中的值(value)是什么?