繁体   English   中英

带位图的Android内存不足

[英]Android Out of Memory with bitmap

我正在创建一个从相机获取图像的应用程序(使用CameraKit库),处理该图像并使用Google Vision Api进行OCR读取,并得到以下错误:

致命例外:主要程序:com。 ,PID:1938 java.lang.OutOfMemoryError:无法分配到63701004字节分配,其中包含16777216可用字节和60MB,直到dalvik.system.VMRuntime.newNonMovableArray(Native Method)的dalvik.system.VMRuntime.newNonMovableArray(Native Method)处的OOM为止com。***处的android.graphics.Bitmap.createBitmap(Bitmap.java:882)处的android.graphics.Bitmap.createBitmap(Bitmap.java:905)com。***处的android.graphics.Bitmap.createBitmap(Bitmap.java:849) *。****。Reader.ReaderResultActivity.createContrast(ReaderResultActivity.java:123)位于com。*****。****。Reader.ReaderResultActivity.onCreate(ReaderResultActivity.java:47)位于android.app。在android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1140)在android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2612)在Activity.performCreate(Activity.java:6672)在android.app.ActivityThread.handleLaunchActivity(ActivityThread .java:2724),位于android.app.ActivityThread.-wrap12(ActivityThread.java),位于android.app.ActivityThread $ H.handleMessage(ActivityTh 在android.os.Handler.dispatchMessage(Handler.java:102)在android.os.Looper.loop(Looper.java:154)在android.app.ActivityThread.main(ActivityThread.java:6123)上读取.java:1473) )的com.android.internal.os.ZygoteInit $ MethodAndArgsCaller.run(ZygoteInit.java:867)的java.lang.reflect.Method.invoke(本机方法)com.android.internal.os.ZygoteInit.main(ZygoteInit .java:757)

ReaderResultActivity代码:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_reader_result);

    ImageView img1 = (ImageView)findViewById(R.id.imageView2);
    ImageView img2 = (ImageView)findViewById(R.id.imageView3);
    ImageView img3 = (ImageView)findViewById(R.id.imageView4);
    TextView scanResults = (TextView)findViewById(R.id.textView);

    //Get bitmap from a static class.
    Bitmap bitmap = Reader.img;

    Bitmap grayScale = toGrayscale(bitmap);
    Bitmap blackWhiteImage = createContrast(grayScale, 50);
    Bitmap invertColor = invertColor(blackWhiteImage);

    //Show process steps
    img1.setImageBitmap(grayScale);
    img2.setImageBitmap(blackWhiteImage);
    img3.setImageBitmap(invertColor);

    TextRecognizer detector = new TextRecognizer.Builder(getApplicationContext()).build();

    try {

        if (detector.isOperational()) {
            Frame frame = new Frame.Builder().setBitmap(invertColor).build();
            SparseArray<TextBlock> textBlocks = detector.detect(frame);
            String blocks = "";
            String lines = "";
            String words = "";
            for (int index = 0; index < textBlocks.size(); index++) {
                //extract scanned text blocks here
                TextBlock tBlock = textBlocks.valueAt(index);
                blocks = blocks + tBlock.getValue() + "\n" + "\n";
                for (Text line : tBlock.getComponents()) {
                    //extract scanned text lines here
                    lines = lines + line.getValue() + "\n";
                    for (Text element : line.getComponents()) {
                        //extract scanned text words here
                        words = words + element.getValue() + ", ";
                    }
                }
            }
            if (textBlocks.size() == 0) {
                scanResults.setText("Scan Failed: Found nothing to scan");
            } else {
                lines = lines.replaceAll("o", "0");
                lines = lines.replaceAll("A", "1");

                scanResults.setText(lines + "\n");
            }
        } else {
            scanResults.setText("Could not set up the detector!");
        }
    } catch (Exception e) {
        Toast.makeText(this, "Failed to load Image", Toast.LENGTH_SHORT)
                .show();
        Log.e("312", e.toString());
    }
}

private Bitmap processImage(Bitmap bitmap){
    Bitmap grayScale = toGrayscale(bitmap);
    Bitmap blackWhiteImage = createContrast(grayScale, 50);
    Bitmap invertColor = invertColor(blackWhiteImage);

    return invertColor;
}
public Bitmap toGrayscale(Bitmap bmpOriginal) {
    int width, height;
    height = bmpOriginal.getHeight();
    width = bmpOriginal.getWidth();

    Bitmap bmpGrayscale = Bitmap.createBitmap(width, height, bmpOriginal.getConfig());
    Canvas c = new Canvas(bmpGrayscale);
    Paint paint = new Paint();
    ColorMatrix cm = new ColorMatrix();
    cm.setSaturation(0);
    ColorMatrixColorFilter f = new ColorMatrixColorFilter(cm);
    paint.setColorFilter(f);
    c.drawBitmap(bmpOriginal, 0, 0, paint);
    return bmpGrayscale;
}

public static Bitmap createContrast(Bitmap src, double value) {
    // image size
    int width = src.getWidth();
    int height = src.getHeight();
    // create output bitmap
    Bitmap bmOut = Bitmap.createBitmap(width, height, src.getConfig());
    // color information
    int A, R, G, B;
    int pixel;
    // get contrast value
    double contrast = Math.pow((100 + value) / 100, 2);

    // scan through all pixels
    for(int x = 0; x < width; ++x) {
        for(int y = 0; y < height; ++y) {
            // get pixel color
            pixel = src.getPixel(x, y);
            A = Color.alpha(pixel);
            // apply filter contrast for every channel R, G, B
            R = Color.red(pixel);
            R = (int)(((((R / 255.0) - 0.5) * contrast) + 0.5) * 255.0);
            if(R < 0) { R = 0; }
            else if(R > 255) { R = 255; }

            G = Color.red(pixel);
            G = (int)(((((G / 255.0) - 0.5) * contrast) + 0.5) * 255.0);
            if(G < 0) { G = 0; }
            else if(G > 255) { G = 255; }

            B = Color.red(pixel);
            B = (int)(((((B / 255.0) - 0.5) * contrast) + 0.5) * 255.0);
            if(B < 0) { B = 0; }
            else if(B > 255) { B = 255; }

            // set new pixel color to output bitmap
            bmOut.setPixel(x, y, Color.argb(A, R, G, B));
        }
    }

    return bmOut;
}

Bitmap invertColor(Bitmap src){
    Bitmap copy = src.copy(src.getConfig(), true);

    for (int x = 0; x < copy.getWidth(); ++x) {
        for (int y = 0; y < copy.getHeight(); ++y) {
            int color = copy.getPixel(x, y);
            int r = Color.red(color);
            int g = Color.green(color);
            int b = Color.blue(color);
            int avg = (r + g + b) / 3;
            int newColor = Color.argb(255, 255 - avg, 255 - avg, 255 - avg);
            copy.setPixel(x, y, newColor);
        }
    }


    return copy;
}

已经尝试在清单中做到这一点

android:largeHeap =“ true”

但是应用程序仅在打开时停止运行:

ReaderResultActivity.createContrast(ReaderResultActivity.java:123)

没有“ largeHeap”标签的错误显示的同一行。 只是不知道该怎么办,但我认为在每个过程函数中都有所有这些“ Bitmap.CreateBitmap”。 但是如果不这样做,在OCR读取中会出现一个错误,指出位图格式错误。

您正在将三个位图加载到不同的图像视图中,而没有根据要在UI上显示的大小对其进行缩放。

Android设备的相机以比设备的屏幕密度高得多的分辨率捕获图片。

鉴于您使用的内存有限,理想情况下,您只想在内存中加载较低分辨率的版本。 较低分辨率的版本应与显示它的UI组件的大小匹配。 具有更高分辨率的图像不会提供任何可见的好处,但仍会占用宝贵的内存,并且由于额外的动态缩放而导致额外的性能开销。

您可以按照开发人员文档建议进行优化-https: //developer.android.com/topic/performance/graphics/load-bitmap.html

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM