【问题标题】:Opencv; How to free IplImage*?开放式简历;如何释放 IplImage*?
【发布时间】:2014-01-10 19:29:51
【问题描述】:

我正在尝试掌握 OpenCV。目前我正在尝试从彼此中减去两帧并显示结果。我找到了可以很好地做到这一点的示例代码。 我的问题是我收到内存分配错误。 好吧,这没什么特别的,因为我正在为程序提供高清视频。 所以我的问题是如何释放 IplImage* 的分配内存? Mat 类型有类似 Mat.release() 的东西。 IplImage 没有,free(IplImage) 也没有。

这是我的代码:

#include <opencv2\opencv.hpp>
#include <opencv2\highgui\highgui.hpp>
#include <opencv2\highgui\highgui_c.h>


using namespace cv;

int main()
{
    std::string videofilename;

    std::cout << "Please specify the video name (make sure it is in the same folder\nas the application!):" << std::endl;
    std::cin >> videofilename;
    std::cout << "The name you provided: " << videofilename << std::endl;

    VideoCapture video(videofilename);

    if(!video.isOpened())
    {
        std::cout << "Could not open video file" << std::endl;
        return -1;
    }

    std::cout << "Number of frames: " << video.get(CV_CAP_PROP_FRAME_COUNT) << std::endl;
    std::cout << "Duration: "<< static_cast<int>(video.get(CV_CAP_PROP_FRAME_COUNT))/(30*60) << "min " << static_cast<int>((video.get(CV_CAP_PROP_FRAME_COUNT)))%(30*60)/30 << "sek" << std::endl;

    // Close it before opening for playing
    video.release();

    CvCapture* capture = cvCaptureFromAVI(videofilename.c_str()); 
    IplImage* frame = cvQueryFrame(capture);
    IplImage* currframe = cvCreateImage(cvGetSize(frame),IPL_DEPTH_8U,3);
    IplImage* destframe = cvCreateImage(cvGetSize(frame),IPL_DEPTH_8U,3);


    if ( !capture ) 
    {  
        std::cout << "Could not open video file" << std::endl;
        return -1; 
    }

    cvNamedWindow("dest", CV_WINDOW_AUTOSIZE);

    while(1)
    {
        frame = cvQueryFrame(capture);

        if(!frame)
        {
            printf("Capture Finished\n");
            break;
        }

        currframe = cvCloneImage(frame);    // copy frame to current
        frame = cvQueryFrame(capture);        // grab frame

        if(!frame)
        {
            printf("Capture Finished\n");
            break;
        }

        cvSub(frame, currframe, destframe);    // subtraction between the last frame to cur
        cvShowImage("dest", destframe);
        //cvReleaseImage(currframe); // doesn't work
        //free(currframe); // doesnt work either
        //delete(currframe); //again, no luck
        cvWaitKey(30);
    }

cvDestroyWindow("dest");
cvReleaseCapture(&capture);
return 0;
}

【问题讨论】:

  • 避免 IplImages、cv* 函数、整个过时的c-api。你已经成功打开了一个 VideoCapture,现在去使用它。

标签: c++ opencv memory free allocation


【解决方案1】:

您可以使用cvReleaseImage 释放IplImage。它将指向IplImage 的指针的地址,即IplImage** 作为参数,所以你必须这样做:

cvReleaseImage(&currframe);

而不是cvReleaseImage(currframe);

但请记住,cvQueryFrame(在您的情况下为frame)返回的图像是一种特殊情况,不应发布或修改。此外,如果您最终要使用cvCloneImage 对其进行初始化,则不必预先分配currFrame

最终代码如下所示:

int main()
{
std::string videofilename;

std::cout << "Please specify the video name (make sure it is in the same folder\nas the application!):" << std::endl;
std::cin >> videofilename;
std::cout << "The name you provided: " << videofilename << std::endl;

VideoCapture video(videofilename);

if(!video.isOpened())
{
    std::cout << "Could not open video file" << std::endl;
    return -1;
}

std::cout << "Number of frames: " << video.get(CV_CAP_PROP_FRAME_COUNT) << std::endl;
std::cout << "Duration: "<< static_cast<int>(video.get(CV_CAP_PROP_FRAME_COUNT))/(30*60) << "min " << static_cast<int>((video.get(CV_CAP_PROP_FRAME_COUNT)))%(30*60)/30 << "sek" << std::endl;

// Close it before opening for playing
video.release();

CvCapture* capture = cvCaptureFromAVI(videofilename.c_str()); 
IplImage* frame = cvQueryFrame(capture);
IplImage* currframe;
IplImage* destframe = cvCreateImage(cvGetSize(frame),IPL_DEPTH_8U,3);


if ( !capture ) 
{  
    std::cout << "Could not open video file" << std::endl;
    return -1; 
}

cvNamedWindow("dest", CV_WINDOW_AUTOSIZE);

while(1)
{
    frame = cvQueryFrame(capture);

    if(!frame)
    {
        printf("Capture Finished\n");
        break;
    }

    currframe = cvCloneImage(frame);    // copy frame to current
    frame = cvQueryFrame(capture);        // grab frame

    if(!frame)
    {
        printf("Capture Finished\n");
        break;
    }

    cvSub(frame, currframe, destframe);    // subtraction between the last frame to cur
    cvShowImage("dest", destframe);
    cvWaitKey(30);
    cvReleaseImage(&currframe);
}

cvDestroyWindow("dest");
cvReleaseCapture(&capture);
return 0;
}

【讨论】:

  • 谢谢!奇迹般有效!我只是忘记了该死的“&”:(。无论如何,对我的问题的第一条评论建议使用 VideoCapture 类而不是 cv 的东西。如果我再次更改代码会有很多好处吗?谢谢
  • @user2175762... 好吧,如果您使用 C++ API 而不是 C API,那么代码将更少且更易于管理。此外,您不必担心内存管理,因为它会由类自动处理。
  • @user2175762...如果它解决了您的问题,您可以考虑接受答案。
  • @sgarizvi 如果我在 while (frame = cvQueryFrame(cap)) 中从视频中查询帧怎么办
  • 我不会有内存泄漏
【解决方案2】:

使用cvReleaseImage()。比如要释放IplImage* frame,就用cvReleaseImage(&amp;frame)

对于Mat,您不需要显式释放它。超出代码块后会自动释放。


编辑:查看here 以了解有关cvReleaseImage() 的更多详细信息,其中解决了一些错误的发布情况。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-10-10
    • 2015-03-14
    • 2019-11-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多