Ask Your Question

Revision history [back]

Memory leak with openCV on android

I am working on an app that uses opencv to process video.

This is the opencv part of my function:

//Open the streams
var merged = VideoCapture()
merged.open(file.path)
var flicker = VideoCapture()
flicker.open("$cacheLocation/flicker.avi")
var grain = VideoCapture()
grain.open("$cacheLocation/oldgrain.avi")

//Check if all streams are opened
if (!merged.isOpened || !flicker.isOpened || !grain.isOpened){
    Log.e("OpenCVHelper", "One or more streams did not open, ABORT!")
    throw Exception()
}

val videoWriter = VideoWriter()
videoWriter.open("$location/$fileName", VideoWriter.fourcc('M', 'J', 'P', 'G'), merged.get(Videoio.CAP_PROP_FPS), Size(merged.get(Videoio.CAP_PROP_FRAME_WIDTH), merged.get(Videoio.CAP_PROP_FRAME_HEIGHT)))

//Setup variables
var totalFrames = merged.get(Videoio.CAP_PROP_FRAME_COUNT)
var grainFrames = grain.get(Videoio.CAP_PROP_FRAME_COUNT)
var flickerFrames = flicker.get(Videoio.CAP_PROP_FRAME_COUNT)
var grainCounter = 0
var flickerCounter = 0

//Setup mat's
var frameMat = Mat()
var rgbaFrame = Mat()
var whiteAlphaMat = Mat.ones(Size(merged.get(Videoio.CAP_PROP_FRAME_WIDTH), merged.get(Videoio.CAP_PROP_FRAME_HEIGHT)),0)
whiteAlphaMat.setTo(Scalar((255).toDouble()))
var videoTmpMat = mutableListOf<Mat>()
var videoRgbaMat = mutableListOf<Mat>()
var flickerMat = Mat()
var grainMat = Mat()
var tmp = Mat()
var alpha = Mat()
var rgb = mutableListOf<Mat>()
var rgba = mutableListOf<Mat>()
var flickerAlphaMat = Mat()
var grainAplhaMat = Mat()


for(frameCounter in 0..totalFrames.toInt()){
    System.gc()
    //Set the position of the readers
    merged.set(Videoio.CAP_PROP_POS_FRAMES, frameCounter.toDouble())
    grain.set(Videoio.CAP_PROP_POS_FRAMES, grainCounter.toDouble())
    flicker.set(Videoio.CAP_PROP_POS_FRAMES, flickerCounter.toDouble())

    //Create material of the current frame
    merged.read(frameMat)

    //Create an rgba mat of the frame

    videoTmpMat.clear()
    Core.split(frameMat, videoTmpMat)
    videoRgbaMat.clear()
    videoRgbaMat.add(videoTmpMat[0])
    videoRgbaMat.add(videoTmpMat[1])
    videoRgbaMat.add(videoTmpMat[2])
    videoRgbaMat.add(whiteAlphaMat)
    Core.merge(videoRgbaMat, rgbaFrame)

    //Create the overlay materials
    flicker.read(flickerMat)
    grain.read(grainMat)

    //Create rgba of the overlays
    rgb.clear()
    rgba.clear()

    Imgproc.cvtColor(flickerMat, tmp, Imgproc.COLOR_BGR2GRAY)
    Imgproc.threshold(tmp, alpha, (100).toDouble(), (255).toDouble(), Imgproc.THRESH_BINARY)
    Core.split(flickerMat, rgb)
    rgba.add(rgb[0])
    rgba.add(rgb[1])
    rgba.add(rgb[2])
    rgba.add(alpha)

    Core.merge(rgba, flickerAlphaMat)

    //tmp = Mat()
    //alpha = Mat()
    //rgb = mutableListOf()
    //rgba = mutableListOf()
    rgb.clear()
    rgba.clear()

    Imgproc.cvtColor(grainMat, tmp, Imgproc.COLOR_BGR2GRAY)
    Imgproc.threshold(tmp, alpha, (100).toDouble(), (255).toDouble(), Imgproc.THRESH_BINARY)
    Core.split(grainMat, rgb)
    rgba.add(rgb[0])
    rgba.add(rgb[1])
    rgba.add(rgb[2])
    rgba.add(alpha)
    Core.merge(rgba, grainAplhaMat)

    //Apply blur to the frame
    Imgproc.blur(rgbaFrame, rgbaFrame, Size((8).toDouble(),(8).toDouble()))

    //Apply flicker to the frame
    Core.addWeighted(rgbaFrame, 1.0, flickerAlphaMat, 0.5, 0.0, rgbaFrame)

    //Apply grain to the frame
    Core.addWeighted(rgbaFrame, 1.0, grainAplhaMat, 0.5, 0.0, rgbaFrame)

    //Add a title
    Imgproc.putText(rgbaFrame, "Made with Super8Life", Point(10.0, 1050.0), 7, 2.0, Scalar(255.0,255.0,255.0), 2);

    //Write frame to file
    videoWriter.write(rgbaFrame)

    //Clear up memory
    //frameMat.release()
    //flickerAlphaMat.release()
    //flickerMat.release()
    //grainAplhaMat.release()
    //grainMat.release()
    //videoTmpMat.forEach {
    //    it.release()
    //}
    //videoRgbaMat.forEach {
    //    it.release()
    //}
    //whiteAlphaMat.release()

    //Handle the counters
    Log.d("OpenCVHelper", "Frame: $frameCounter")
    //val percentage = frameCounter.toDouble() / totalFrames * 100.toDouble()
    //Log.d("OpenCVHelper", "$percentage%")

    if (grainCounter < grainFrames -1){
        grainCounter ++;
    } else {
        grainCounter = 0;
    }
    if (flickerCounter < flickerFrames -1){
        flickerCounter ++;
    } else {
        flickerCounter = 0;
    }
}
videoWriter.release()

It eats up memory 4 of the 5 times of testing the app and that causes the app to crash.

I don't understand what I'm doing wrong? I have already moved the declaration of the Mat's outside the loop. Mat.release() doesn't do anything

thx a lot, Jules