简体   繁体   English

带位图的Android内存不足

[英]Android Out of Memory with bitmap

I'm creating a app that gets a image from camera (using CameraKit library), process the image and do a OCR Read using Google Vision Api, And get this error: 我正在创建一个从相机获取图像的应用程序(使用CameraKit库),处理该图像并使用Google Vision Api进行OCR读取,并得到以下错误:

FATAL EXCEPTION: main Process: com. 致命例外:主要程序:com。 . , PID: 1938 java.lang.OutOfMemoryError: Failed to allocate a 63701004 byte allocation with 16777216 free bytes and 60MB until OOM at dalvik.system.VMRuntime.newNonMovableArray(Native Method) at android.graphics.Bitmap.nativeCreate(Native Method) at android.graphics.Bitmap.createBitmap(Bitmap.java:905) at android.graphics.Bitmap.createBitmap(Bitmap.java:882) at android.graphics.Bitmap.createBitmap(Bitmap.java:849) at com.****.****.Reader.ReaderResultActivity.createContrast(ReaderResultActivity.java:123) at com.*****.****.Reader.ReaderResultActivity.onCreate(ReaderResultActivity.java:47) at android.app.Activity.performCreate(Activity.java:6672) at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1140) at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2612) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2724) at android.app.ActivityThread.-wrap12(ActivityThread.java) at android.app.ActivityThread$H.handleMessage(ActivityTh ,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 read.java:1473) at android.os.Handler.dispatchMessage(Handler.java:102) at android.os.Looper.loop(Looper.java:154) at android.app.ActivityThread.main(ActivityThread.java:6123) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:867) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:757) 在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 Code: 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;
}

Already try to do this in Manifest 已经尝试在清单中做到这一点

android:largeHeap="true" android:largeHeap =“ true”

But the application just stop running when is on: 但是应用程序仅在打开时停止运行:

ReaderResultActivity.createContrast(ReaderResultActivity.java:123) ReaderResultActivity.createContrast(ReaderResultActivity.java:123)

The same line that appears on error without the "largeHeap" tag. 没有“ largeHeap”标签的错误显示的同一行。 Just dont know what to do, but i think that has something with all those "Bitmap.CreateBitmap" in every process function. 只是不知道该怎么办,但我认为在每个过程函数中都有所有这些“ Bitmap.CreateBitmap”。 But without doing this, in OCR reading, appear a error saying that the bitmap has a wrong format. 但是如果不这样做,在OCR读取中会出现一个错误,指出位图格式错误。

You are loading three bitmaps in different imageviews without scaling it according to the size you want to show on your UI. 您正在将三个位图加载到不同的图像视图中,而没有根据要在UI上显示的大小对其进行缩放。

Android devices's camera captures pictures with much higher resolution than the screen density of your device. Android设备的相机以比设备的屏幕密度高得多的分辨率捕获图片。

Given that you are working with limited memory, ideally you only want to load a lower resolution version in memory. 鉴于您使用的内存有限,理想情况下,您只想在内存中加载较低分辨率的版本。 The lower resolution version should match the size of the UI component that displays it. 较低分辨率的版本应与显示它的UI组件的大小匹配。 An image with a higher resolution does not provide any visible benefit, but still takes up precious memory and incurs additional performance overhead due to additional on the fly scaling. 具有更高分辨率的图像不会提供任何可见的好处,但仍会占用宝贵的内存,并且由于额外的动态缩放而导致额外的性能开销。

You can optimize it by following developer documentation suggestions - https://developer.android.com/topic/performance/graphics/load-bitmap.html 您可以按照开发人员文档建议进行优化-https: //developer.android.com/topic/performance/graphics/load-bitmap.html

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

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