Как обрабатывать каждый кадр видео и сдвигать пиксели между кадрами с помощью камеры Android2 - PullRequest
0 голосов
/ 04 ноября 2019

Я новичок в Android, и в моем приложении мне нужно получать видео с камеры и смешивать пиксели из разных кадров. Я пытался получить кадры из захваченного видео с помощью mediaMetaDataRetriever, но это занимает слишком много времени. Теперь я использую ImageReader, чтобы получить каждый кадр в реальном времени, создать растровое изображение и поместить его в массив. Это занимает очень много места в оперативной памяти. и последующая обработка этого массива с тремя циклами также довольно продолжительна. Итак, как мне решить эту проблему с Camera2?

Смешивание массива растрового изображения:

 val outputFrames = arrayOfNulls<Bitmap>(1080)
    var videoDuration = frames.size
    if(videoDuration%2 != 0) videoDuration--
    var index = 0
    while (index < videoDuration) {
        var indexWidth = 1079
        while (indexWidth >= 0) {
            var indexHeight = 1919
            while (indexHeight >= 0) {
                if (outputFrames[indexWidth] == null) {
                    outputFrames[indexWidth] =
                        Bitmap.createBitmap(videoDuration, 1920, Bitmap.Config.ARGB_8888)
                    outputFrames[indexWidth]!![index, indexHeight] =
                        frames[0][indexWidth, indexHeight]
                } else outputFrames[indexWidth]!![index, indexHeight] =
                    frames[0][indexWidth, indexHeight]
                //Log.e("frame:", "$indexWidth $indexHeight /${outputFrames[indexWidth]}/")
                indexHeight--
            }
            indexWidth--
        }
        frames.removeAt(0)
        index++
    }

My Image Reader:

mImageReader = ImageReader.newInstance(mWidth,mHeight, PixelFormat.RGBA_8888,1)
    mImageReader.setOnImageAvailableListener(
        { reader ->
            val image = reader.acquireLatestImage()
            val planes = image.planes
            val buffer = planes[0].buffer
            val offset = 0
            val pixelStride = planes[0].pixelStride
            val rowStride = planes[0].rowStride
            val rowPadding = rowStride - pixelStride * mWidth
            // create bitmap
            val bitmap = Bitmap.createBitmap(
                mWidth + rowPadding / pixelStride,
                mHeight,
                Bitmap.Config.ARGB_8888
            )
            bitmap.copyPixelsFromBuffer(buffer)
            image.close()

        },
        mBackgroundHandler)

1 Ответ

0 голосов
/ 11 ноября 2019

Создание растрового изображения очень дорого, и оно будет тормозить ваше приложение, как ад. Попытайтесь получить свое изображение как:

mImageReader = ImageReader.newInstance(DISPLAY_WIDTH, DISPLAY_HEIGHT, ImageFormat.YUV_420_888, Runtime.getRuntime().availableProcessors());

После этого вы можете создать свое растровое изображение с помощью ScriptIntrinsicYuvToRGB, например:

Image.Plane Y = mImage.getPlanes()[0];
        Image.Plane U = mImage.getPlanes()[1];
        Image.Plane V = mImage.getPlanes()[2];

        int Yb = Y.getBuffer().remaining();
        int Ub = U.getBuffer().remaining();
        int Vb = V.getBuffer().remaining();

        byte[] data = new byte[Yb + Ub + Vb];

        Y.getBuffer().get(data, 0, Yb);
        V.getBuffer().get(data, Yb, Vb);
        U.getBuffer().get(data, Yb + Vb, Ub);

        RenderScript rs = RenderScript.create(Main2Activity.this);
        ScriptIntrinsicYuvToRGB yuvToRgbIntrinsic = ScriptIntrinsicYuvToRGB.create(rs, Element.U8_4(rs));

        Type.Builder yuvType = new Type.Builder(rs, Element.U8(rs)).setX(data.length);
        Allocation in = Allocation.createTyped(rs, yuvType.create(), Allocation.USAGE_SCRIPT);

        Type.Builder rgbaType = new Type.Builder(rs, Element.RGBA_8888(rs)).setX(DISPLAY_WIDTH).setY(DISPLAY_HEIGHT);
        Allocation out = Allocation.createTyped(rs, rgbaType.create(), Allocation.USAGE_SCRIPT);

        final Bitmap bmpout = Bitmap.createBitmap(DISPLAY_WIDTH, DISPLAY_HEIGHT, Bitmap.Config.ARGB_8888);

        in.copyFromUnchecked(data);

        yuvToRgbIntrinsic.setInput(in);
        yuvToRgbIntrinsic.forEach(out);
        out.copyTo(bmpout);

Этот код значительно ускоряет все, если вы используете его вфоновый поток.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...