Bug? Increasing memory usage per iteration when using findContours()
Hello all,
I've been trying to debug this for a month, sure it was my bad programming practise, but I think it may be a bug, so I'm asking here first before I report.
Consider the following code:
#include <sys/resource.h> // memory management.
#include <stdio.h>
#include <iostream>
#include <iomanip>
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/core/core.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/video/background_segm.hpp"
using namespace std;
using namespace cv;
// Load frame from disk.
void readFrame(int frameNum, Mat &frame) {
// Construct filenames
Mat image;
stringstream number, filename;
number << setw(7) << setfill('0') << frameNum; // expecting over 1e10 images over the installation period.
filename << "../images/store-" << number.str() << ".jpg"; // assumes jpegs!//
cout << "Loading filename: " << filename.str() << endl;
image = imread( filename.str() );
if (image.empty() or !image.data) {
cout << "Input image empty:\n";
}
frame = image.clone();
}
// Class to hold the perceptual chunks.
class percepUnit {
public:
cv::Mat image; // percept itself
cv::Mat mask; // alpha channel
// constructor method
percepUnit(cv::Mat &ROI, cv::Mat &alpha, int ix, int iy, int iw, int ih, int area) {
image = ROI.clone();
mask = alpha.clone();
}
};
// Segment foreground from background
void segmentForeground(list<percepUnit*> &percepUnitsForeground, Mat &foreground, Mat &frame) {
Mat contourImage = Mat(foreground.rows, foreground.cols, CV_8UC1, Scalar::all(0));
vector<vector<Point>> contours;
int area;
// The following causes strange spikes in memory usage:
// find contours
findContours(foreground, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE);
for (int idx = 0; idx < contours.size(); idx++) {
area = contourArea(contours[idx]);
if (area > 100) {
percepUnit *thisUnit = new percepUnit(frame, contourImage, 0, 0, 100,100, area);
percepUnitsForeground.push_back(thisUnit); // Append to percepUnits
}
}
/* The following does not:
findContours(foreground, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE);
for (int idx = 0; idx < contours.size(); idx++) {
area = contourArea(contours[idx]);
}*/
/* Neither does this:
for (int idx = 0; idx < 10; idx++) {
percepUnit *thisUnit = new percepUnit(frame, contourImage, 0, 0, 100,100, area);
percepUnitsForeground.push_back(thisUnit); // Append to percepUnits
}*/
}
int main(int argc, const char** argv)
{
int frameCount = 78298;
Mat frame, foreground;
BackgroundSubtractorMOG2 MOG2model;
list<percepUnit*> scratchPercepUnitsForeground;
// add rusage stuff
struct rusage usage; // memory usage.
for(int i=0; i<= 75; i++)
{
// run full segmenter here. (background disabled)
readFrame(frameCount, frame); // was frame = readFrame();
// Only process if this frame actually loaded (non empty)
if ( not frame.empty() ) {
MOG2model(frame,foreground); // Update MOG2 model, downscale?
// before we segment again clear scratch
// TODO how to delete the actual memory allocated? Run delete on everything?
for (list<percepUnit*>::iterator percepIter = scratchPercepUnitsForeground.begin();
percepIter != scratchPercepUnitsForeground.end();
percepIter++) {
delete *percepIter; // delete what we point to.
//percepIter = scratchPercepUnitsForeground.erase(percepIter); // remove the pointer itself, and update the iterator.
}
// Added with EDIT1
scratchPercepUnitsForeground.clear();
// Segment the foreground regions and generate boolImage to extract from background.
segmentForeground(scratchPercepUnitsForeground, foreground, frame);
}
frameCount++;
getrusage(RUSAGE_SELF, &usage);
cout << "DEBUG leakTest_bug_report " << i << " " << usage.ru_maxrss/1024.0 << endl;
}
return 0;
}
If you use the images available here, you will find that the program's memory usage increases, and it seems to increase with the number of foreground contours. Since I'm clearing my storage (scratchPercepUnitsForeground) for each frame, I don't ...