user957121
user957121

Reputation: 3066

Memory leak processing cv::Mat array in opencv

I tried to draw 10 * 10 matrix on a video frame and here is the drawing function:

void AddMatrixToVideo::process(cv::Mat &videoFrameInput)
{
    int MatrixStartPointX = 0;
    int MatrixStartPointY = 0;
    int m,n;

    for(int i = 0; i < matrixNumInRow; ++i) {
        for(int j = 0; j < matrixNumInColm; ++j) {
            //draw horizontal line
            for(m = MatrixStartPointX; m < MatrixStartPointX + matrixWidth; ++m) {
                    processGrayFrame(m,MatrixStartPointY,videoFrameInput);
                    processGrayFrame(m,MatrixStartPointY + matrixHeight,videoFrameInput);
            }
            //draw vertical line
            for(n = MatrixStartPointY; n < MatrixStartPointY + matrixHeight; ++n) {
//                    processGrayFrame(MatrixStartPointX,n,videoFrameInput);
//                    processGrayFrame(MatrixStartPointX + matrixWidth,n,videoFrameInput);
            }
            MatrixStartPointX += matrixWidth;
        }
        MatrixStartPointX = 0;
        MatrixStartPointY += matrixHeight;
    }
}

Here is the processGrayFrame():

void AddMatrixToVideo::processGrayFrame(int x,int y,cv::Mat &videoFrameInput)
{
    videoFrameInput.at<uchar>(y,x) = 255;
}

After running the program, it seems that the drawing progress works the memory usage keeps increasing and finally run out of memory. If I comment the processGrameFrame() function, the memory problem goes(of course it won't draw lines any more). So my question is why does the assigning operation cause the memory leak problem?

Upvotes: 1

Views: 1598

Answers (3)

Barney Szabolcs
Barney Szabolcs

Reputation: 12514

Use assert(0<=x&&x<m.cols&&0<=y&&y<m.rows) macro to check boundary conditions. (The checking only appears in the actual code if you set the DEBUG flag or you are in debug mode using an IDE.)


You can also have a potential leak if you don't clone-out the video frame.

The video frame cv::Mat (you probably got from cv::VideoCapture cap(0); cap>>frame;) has to be cloned-out. Otherwise in my experience you will have leak from time to time, not in every frame. (I think only when the place of the buffer gets changed.)

so the solution is cap>>frame_raw; Mat frame = frame_raw.clone(); (I think you actually call frame videoFrameInput).

REMARK:
I know it is not the point here but you rather get familiar with the opencv drawing functions (if not done so yet).
There is cv::line(mat, p1, p2, color,...), cv::rectangle(...), cv::ellipse(...) and cv::floodFill(...) for fills just to name a few. Those are way more efficient since they have more efficient memory access (not using .at<>() and also may optimize and paralellize access order).

Upvotes: 0

Sam
Sam

Reputation: 20058

It is very hard to have a memory leak when you use the C++ interface. Actually, you'll have to be expert to do it :)

It is either a false alarm, which happens often on Windows systems (see memory leak in opencv functions) either a leak in other part of the program.

To make sure it's not a leak, you should profile it with a leak detector.

Upvotes: 0

Keith Randall
Keith Randall

Reputation: 23265

Your processGrayFrame is right, that's how you're supposed to use it. The problem I think is you are not passing in x and y values that are in bounds. Your calls to processGrayFrame don't pass an in-bounds point. At least MatrixStartPointY + matrixHeight is certainly out of bounds.

Also make sure you're allocating the matrix correctly (that the element type is uchar when allocated - I think that would be CV_8UC1, at least if you have 8-bit chars).

Run OpenCV in debug mode, it should tell you when the coordinates are out of bounds.

Upvotes: 2

Related Questions