内存不足OpenCV C ++

时间:2015-12-14 16:43:09

标签: c++ opencv out-of-memory

实际上,我遇到了这个问题:

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及其对象。我找不到任何解决方案,所以我的问题:你对如何做到这一点有任何想法吗?此外,我是在正确的轨道上还是我应该仔细查看问题究竟在哪里?

1 个答案:

答案 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?