OpenCV内存不足

时间:2011-04-06 10:35:30

标签: c++ memory opencv memory-leaks

我在Visual C ++ 2008和OpenCV 2.1上运行以下代码。它工作了一段时间(比如说3分钟)然后中止并出现错误

“内存不足(无法分配92610字节)未知功能,文件........ \ ocv \ opencv \ src \ cxcore \ cxalloc.cpp,第52行”

某处必须有一些内存泄漏(可能是图像创建),但我似乎无法掌握它。

#include "cv.h"
#include "highgui.h"
#include <stdio.h>
#include <iostream>
#include <math.h>

using namespace std;

void main()
{
    int i, j;
    int **arr = new int*[480], blob[6][8]={0};
    int max, maxi=-10, maxj=-10, div=80;
    int xmax=480, ymax=640;
    int frameH, frameW, fps, numFrames;
    double hue, sat, lum;
    int maxcolor, mincolor, maxcolval, mincolval;
    char key='a';
    CvScalar pix, destpix, destpix2, destpix3;
    IplImage *img, *dest, *hsv;

    for(i=0; i<480; i++)
        arr[i] = new int[640];

    CvCapture *capture = cvCaptureFromCAM(0);
    if(!capture)
    {
        cout<<"Cannot read video!!!!";
        exit(0);
    }

    frameH    = (int) cvGetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT);
    frameW    = (int) cvGetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH);
    fps       = (int) cvGetCaptureProperty(capture, CV_CAP_PROP_FPS);
    numFrames = (int) cvGetCaptureProperty(capture,  CV_CAP_PROP_FRAME_COUNT);
    printf("Width=%d Height=%d FPS=%d Count=%d\n", frameH, frameW, fps, numFrames);

    cvNamedWindow("win1", CV_WINDOW_AUTOSIZE);
    cvMoveWindow("win1", 10, 10);
    cvNamedWindow("win2", CV_WINDOW_AUTOSIZE);
    cvMoveWindow("win2", 600, 300);

    destpix.val[0]=0;
    destpix.val[1]=255;
    destpix.val[2]=0;
    destpix2.val[0]=0;
    destpix2.val[1]=0;
    destpix2.val[2]=0;
    destpix3.val[0]=255;
    destpix3.val[1]=255;
    destpix3.val[2]=255;

    while(key != 'q')
    {
        max=0;
        maxi=-10;
        maxj=-10;

        img = cvQueryFrame(capture);
        if(img == 0)break;

        dest = cvCloneImage(img);
        hsv = cvCloneImage(img);

        cvCvtColor(img, hsv, CV_BGR2HSV);

        for(i=0; i<xmax; i++)
            for(j=0; j<ymax; j++)
            {
                arr[i][j]=0;
                blob[i/div][j/div]=0;
            }           

        cout<<endl<<cvGet2D(hsv, 5, 5).val[0];
        //Looping through each pixel
        for(i=0; i<xmax; i++)
        {
            for(j=0; j<ymax; j++)
            {
                //Getting the current pixel (i, j)
                pix = cvGet2D(hsv, i, j);

                //Setting all pixels to black
                cvSet2D(dest, i, j, destpix2);

                hue = pix.val[0];
                sat = pix.val[1];
                lum = pix.val[2];

                //Looking for color red
                if((hue<5 || hue>177) && sat>120 && lum>60)
                {
                    arr[i][j] = 1;
                    cvSet2D(dest, i, j, destpix);
                }

                /*//Looking for color green
                if((hue>90 && hue<100) && sat>120 && lum>60)
                {
                    arr[i][j] = 1;
                    cvSet2D(dest, i, j, destpix);
                }*/

                /*//Looking for color blue
                if((hue>100 && hue<110) && sat>120 && lum>60)
                {
                    arr[i][j] = 1;
                    cvSet2D(dest, i, j, destpix);
                }*/

                /*//Looking for color yellow
                if((hue>30 && hue<40) && sat>120 && lum>60)
                {
                    arr[i][j] = 1;
                    cvSet2D(dest, i, j, destpix);
                }*/
            }   
        }

        //Counting the blobs in each grid
        for(i=0; i<xmax; i++)
        {
            for(j=0; j<ymax; j++)
            {
                if(arr[i][j])
                {
                    blob[i/div][j/div]++;
                }
            }
        }

        //Finding the grid with the largest blob
        for(i=0; i<xmax/div; i++)
            for(j=0; j<ymax/div; j++)
                if(blob[i][j]>max)
                {
                    max=blob[i][j];
                    maxi=i;
                    maxj=j;
                }

        if(max>200)
        {
            //Borders
            for(i=maxi*div; i<maxi*div+2; i++)
                for(j=maxj*div; j<maxj*div+div; j++)
                    cvSet2D(dest, i, j, destpix3);

            for(i=maxi*div+div-2; i<maxi*div+div; i++)
                for(j=maxj*div; j<maxj*div+div; j++)
                    cvSet2D(dest, i, j, destpix3);

            for(i=maxi*div; i<maxi*div+div; i++)
                for(j=maxj*div; j<maxj*div+2; j++)
                    cvSet2D(dest, i, j, destpix3);

            for(i=maxi*div; i<maxi*div+div; i++)
                for(j=maxj*div+div-2; j<maxj*div+div; j++)
                    cvSet2D(dest, i, j, destpix3);

            //Center
            for(i=maxi*div+(div/2)-5; i<maxi*div+(div/2)+5; i++)
                for(j=maxj*div+(div/2)-5; j<maxj*div+(div/2)+5; j++)
                    cvSet2D(dest, i, j, destpix3);
        }

        //Creating Windows
        //cvCvtColor(fin, dest, CV_HSV2BGR);
        key = cvWaitKey(20);
        cvShowImage("win1", dest);
        cvShowImage("win2", img);
    }

    cvWaitKey(0);
    cvReleaseCapture(&capture);
    cvReleaseImage(&dest);
    cvDestroyWindow("win1");
    cvDestroyWindow("win2");
}

4 个答案:

答案 0 :(得分:3)

“内存不足”实际上意味着“当我尝试分配内存时出错”。

你很可能实际上已经在某个地方损坏了某些内容,而不是实际内存不足,尤其是这种代码风格。

答案 1 :(得分:2)

CloneImage的文档说:

  

制作完整的图像副本

     

IplImage * cvCloneImage(const   IplImage * image);

     

图像       原始图像。

     

函数cvCloneImage完整   包括标题的图像副本,   投资回报率和数据

您正在每个循环创建一个深层副本,并使用相同的指针保存它。每个循环都会在没有释放内存的情况下松开前面的分配。

修改

此功能可以帮助您:

  

ReleaseImage

     

发布标题和图片数据

     

void cvReleaseImage(IplImage ** image   );

     

图像       指向解除分配图像标题的双指针。

     

函数cvReleaseImage发布   标题和图像数据。这个   

是一种缩短的形式
if( *image )
{
    cvReleaseData( *image );
    cvReleaseImageHeader( image );
}

尝试在while循环结束时释放内存。

答案 2 :(得分:1)

IplImage * img,* dest,* hsv;

检查文档,看看是否负责释放上述指针,然后再将它们分配给新值。

答案 3 :(得分:1)

老帖子,但这个问题肯定让我头疼了......

我完全遇到了同样的问题,我只是使用普通的绘图功能。你在这里基本上想要在每次迭代中复制一个图像。目前的情况是:

dest = cvCloneImage(img)将分配内存,将整个图像克隆到其中并将指针返回到此新内存,那么您将丢失之前的指针值dest。所以,如果到那时你还没有用cvReleaseImage(img)释放内存,你就会有内存泄漏。

必须有一种更简单的方法,确实有:

    /* Copies source array to destination array */
    CVAPI(void)  cvCopy( const CvArr* src, CvArr* dst,
                         const CvArr* mask CV_DEFAULT(NULL) );

所以你只需要使用cvCopy(img, dest); dest中的内容将被覆盖=&gt;没有内存泄漏