2013-12-22 79 views
1

我想要獲得OpenCV的一竅不通。此刻,我正試圖從對方減去兩幀並顯示結果。我找到了可以做到這一點的示例代碼。 我的問題是我得到一個內存分配錯誤。 那麼,沒什麼特別的,因爲我用高清視頻餵食節目。 所以我的問題是我如何釋放分配的IplImage *的內存? Mat類型有類似Mat.release()的東西。 IplImage沒有,免費(IplImage)的工作。Opencv;如何釋放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; 
} 
+0

請*避免* IplImages,CV *功能,整機過時C-API。你已經成功打開了VideoCapture,現在就去使用它。 – berak

回答

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; 
} 
+0

謝謝!奇蹟般有效!我只是忘了該死的「&」:(無論如何,我的問題的第一個評論建議使用VideoCapture類而不是cv的東西。如果我再次更改代碼會有很多好處嗎?Thx – user2175762

+0

@ user2175762。 ..好吧,如果你使用C++ API而不是C API,那麼代碼管理起來就會簡單和容易,而且,你不必擔心內存管理,因爲它會自動由類處理。 – sgarizvi

+0

@ user2175762你可能會考慮接受答案,如果它解決了你的問題 – sgarizvi

0

使用cvReleaseImage()。例如,如果您想要發佈IplImage* frame,請使用cvReleaseImage(&frame)

對於Mat,您不需要明確地發佈它。它將在其代碼塊之外自動釋放。


編輯:承擔更多的細節來看看herecvReleaseImage(),這對一些錯誤釋放的情況下解決。