实际上,我遇到了这个问题:
OpenCV Error: Insufficient memory (Failed to allocate 225792004 bytes) in OutOfMemoryError, file /build/buildd/opencv-2.4.8+dfsg1/modules/core/src/alloc.cpp, line 52
terminate called after throwing an instance of 'cv::Exception'
what(): /build/buildd/opencv-2.4.8+dfsg1/modules/core/src/alloc.cpp:52: error: (-4) Failed to allocate 225792004 bytes in function OutOfMemoryError
当我从main
调用以下方法时,我正在使用listOfImages
中的36张图片
void MainHelper::startProcessingDataSampleForROCCurve(bool downSampleData)
{
/*Step 5: Load test data*/
vector <Mat> imagesToTest;
///Looping over the segmented to validate the method we did
Diagnostics diagnoLearningAndTesting;
WindowsDataSet windowsDataSetInstance;
map <int , vector < double > > areaCalculatedPerImageForEachK;
for (int indexImage = 0; indexImage < listOfImages.size(); indexImage++)
{
Mat imageTestForIteration = listOfImages[indexImage];
imagesToTest.push_back(imageTestForIteration);
Mat imageTestBinaryForIteration = listOfBinaryImages[indexImage];
//Prepare the learning image list by removing only the image for testing
vector<Mat> listOfLearningImages(listOfImages.begin(),listOfImages.end());
listOfLearningImages.erase(listOfLearningImages.begin() + indexImage);
vector<Mat> listOfBinaryLearningImages(listOfBinaryImages.begin(),listOfBinaryImages.end());
listOfBinaryLearningImages.erase(listOfBinaryLearningImages.begin() + indexImage);
/*Step 7: Processing the images by having a vector of descriptor for every window in the image*/
ImageProcessingManager imageManager;
map <int , vector< vector<double> > > dictWindowPerFeaturesPerTile;
// map <int , vector< vector<Mat> > > dictTilesPerLearningImage;
map <int , vector< int > > dictAnnotationPerTile;
diagnoLearningAndTesting.startMethod(StringUtils::stringFormat("Learning Part.. %d",(indexImage + 1)));
for (int indexWindowLength = 0; indexWindowLength < Constants::windowsSize.size(); indexWindowLength ++)
{
int windowLength = Constants::windowsSize[indexWindowLength];
vector < int > annotationPerTile;
//TODO: It won't be filled for now for memory reasons
vector < vector <Mat> > tilesPerLearningImage;
vector < vector <double> > featuresPerTile = imageManager.processImagesInWindowsWithFeatures(listOfLearningImages, listOfBinaryLearningImages, tilesPerLearningImage, annotationPerTile, windowLength, Constants::percentageOfWhiteToConsiderIntrumentWindow);
dictWindowPerFeaturesPerTile[windowLength] = featuresPerTile;
// dictTilesPerLearningImage[windowLength] = tilesPerLearningImage;
dictAnnotationPerTile[windowLength] = annotationPerTile;
}
diagnoLearningAndTesting.endMethod();
MemoryUtils::displayMemoryUsage();
diagnoLearningAndTesting.startMethod(StringUtils::stringFormat("Testing Part.. %d",(indexImage + 1)));
//TODO: Change the value of the param here..
for (int kNearestNeighbor = 2; kNearestNeighbor <= Constants::kNearestNeighbor; kNearestNeighbor ++)
{
Diagnostics::LogWithTime(StringUtils::stringFormat("*** Running annotations with K = %d", kNearestNeighbor));
if (Constants::hierarchyWindowLevel == Multiple)
{
for (int indexOfImage = 0; indexOfImage < imagesToTest.size(); indexOfImage ++)
{
Mat image = imagesToTest[indexOfImage];
vector <Mat> testImagesInVect = boost::assign::list_of(image);
Mat binaryResultOfImageTest(image.rows, image.cols, CV_8UC1, Scalar(0.));
vector <Mat> binaryTestImagesInVect = boost::assign::list_of(binaryResultOfImageTest);
for (int indexWindowLength = 0; indexWindowLength < Constants::windowsSize.size(); indexWindowLength ++)
{
int windowLength = Constants::windowsSize[indexWindowLength];
Diagnostics::LogWithTime(StringUtils::stringFormat("Running annotations with windowLength = %d", windowLength));
/*Step 7-1: Learning vectors already loaded */
vector < int > annotationPerTile = dictAnnotationPerTile[windowLength];
// vector < vector <Mat> > tilesPerLearningImage = dictTilesPerLearningImage[windowLength];
vector < vector <double> > featuresPerTile = dictWindowPerFeaturesPerTile[windowLength];
/*Step 8: Processing the samples on which we need to make our tests by having a vector of descriptor for every window in the image*/
//TODO: GET THE BINARY VERSION OF THE IMAGES******
vector< vector <int> > annotationPerImageForTiles;
vector < vector <Mat> > tilesPerTestImage;
vector < vector < vector <double> > > featuresPerTiles = imageManager.processSetOfImages(testImagesInVect, vector<Mat>(), tilesPerTestImage, windowLength, Constants::percentageOfWhiteToConsiderIntrumentWindow, annotationPerImageForTiles);
vector < vector <Mat> > binaryTiles = imageManager.divideBinaryImagesInTiles(binaryTestImagesInVect, windowLength);
/*Step 9: Knn Classifier train data */
Mat trainData = VectorUtility <double>::toMat(featuresPerTile);
Mat dataClasses = VectorUtility <int>::toMat(annotationPerTile);
ClassifierManager classifier(trainData, dataClasses, kNearestNeighbor);
/*Step 10: Annotation Step*/
vector < vector <int> > resultsForEachTilePerImage = classifier.annotateTheTilesInImages(featuresPerTiles);
/*Step 10-1: Annotation Step with window hierarchy: Extract tiles which have probability > 0*/
vector <Mat> instrumentTiles;
vector <Mat> instrumentBinaryTiles;
for (int resultIndex = 0; resultIndex < resultsForEachTilePerImage.size(); resultIndex ++)
{
vector <int> resultsForTilePerImage = resultsForEachTilePerImage[resultIndex];
vector <Mat> tilesPerImage = tilesPerTestImage[resultIndex];
vector <Mat> tilesPerBinaryImage = binaryTiles[resultIndex];
for (int resultIndex = 0; resultIndex < resultsForTilePerImage.size(); resultIndex ++)
{
int result = resultsForTilePerImage[resultIndex];
if (result > 0)
{
Mat tile = tilesPerImage[resultIndex];
instrumentTiles.push_back(tile);
Mat binaryTile = tilesPerBinaryImage[resultIndex];
instrumentBinaryTiles.push_back(binaryTile);
if (indexWindowLength == Constants::windowsSize.size() - 1)
{
int valueOfPixel = (result * 255) / 100;
//This region should be set to valueOfPixel..
binaryTile.setTo(valueOfPixel);
}
}
}
}
testImagesInVect = instrumentTiles;
binaryTestImagesInVect = instrumentBinaryTiles;
//Release objects for memory reasons..
resultsForEachTilePerImage.clear();
tilesPerTestImage.clear();binaryTiles.clear();
trainData.release();dataClasses.release();
featuresPerTiles.clear();
}
/*Step 11: Draw images with the regions of interest we want*/
string imagePrefix = StringUtils::stringFormat("%sM-ImageResult%d-k%d-WL", Constants::pathOfResultImages.c_str(), indexImage,kNearestNeighbor);
for (int indexWindowLength = 0; indexWindowLength < Constants::windowsSize.size(); indexWindowLength ++)
{
imagePrefix = StringUtils::concat(imagePrefix, numberToString(Constants::windowsSize[indexWindowLength]));
}
string imageName = StringUtils::stringFormat("%s.png", imagePrefix.c_str());
imwrite(imageName, binaryResultOfImageTest);
if (Constants::generateROCCurve)
{
/*Step 12: Validation steps by showing the percentage of accuracy of this method (ROC courbe)*/
double areaOfAZ = windowsDataSetInstance.ROCCurveFor(imageTestBinaryForIteration, binaryResultOfImageTest, image, Constants::pathOfResultImages, StringUtils::stringFormat("%d-k%d.txt",indexImage, kNearestNeighbor), kNearestNeighbor);
vector <double> listOfAreasCalculated = areaCalculatedPerImageForEachK[kNearestNeighbor];
listOfAreasCalculated.push_back(areaOfAZ);
areaCalculatedPerImageForEachK[kNearestNeighbor] = listOfAreasCalculated;
}
}
}
}
//Clear Objects for memory reasons
dictAnnotationPerTile.clear();dictWindowPerFeaturesPerTile.clear();
listOfLearningImages.clear();listOfBinaryLearningImages.clear();
diagnoLearningAndTesting.endMethod();
//Clear all elements of imagesToTest
imagesToTest.clear();
MemoryUtils::displayMemoryUsage();
}
//Step #12: Additional step to display the mean and standard variation of the list of Areas calculated for each value of K
for (std::map<int, vector <double> >::iterator it = areaCalculatedPerImageForEachK.begin(); it != areaCalculatedPerImageForEachK.end(); ++it)
{
vector < double> areas = it->second;
double mean = VectorUtility<double>::mean(areas);
double std = VectorUtility<double>::standardDeviation(areas, mean);
Diagnostics::LogWithTime(StringUtils::stringFormat("******* For K = %d : Mean(Az) = %f, Std(Az) = %f",it->first, mean, std));
}
}
我认为我们不应该仔细阅读这里调用的每个方法的细节,因为我正在寻找的是在第一个{{1的每次迭代结束时释放内存的方法这意味着释放分配的for
/ vectors
及其对象。我找不到任何解决方案,所以我的问题:你对如何做到这一点有任何想法吗?此外,我是在正确的轨道上还是我应该仔细查看问题究竟在哪里?
答案 0 :(得分:4)
您正在制作一些副本,请尝试将const ref
保留在不会被修改的对象上。您也可以使用std::move
以避免复制。
例如,在您的代码中:
Mat image = imagesToTest[indexOfImage];
你实际上是在复制一个Mat
,在你的情况下是一个图像,因此占用了很大一部分内存。
代码的很大一部分也是如此。
请在此处查看move
您的数据,而不是执行实际副本:When to use Move Constructors/Assignments
您还可以通过&#34;推送&#34;将变量的生命周期限制在最小值。他们到最小的堆栈你可以。您甚至可以创建人工堆栈来限制变量的范围。
例如:
Mat a;
{
Mat b;
// ... do some stuff
} // Mat b won't exists any more after here
// Mat a still exists
当你说:
我认为我们不应该仔细阅读这里所说的每种方法的细节
我认为你犯了一个错误,你应该检查你的每个方法的签名,看看你是否真的不做任何多余的复制。 请参阅:Is it better in C++ to pass by value or pass by constant reference?