閱讀787 返回首頁    go 阿裏雲 go 技術社區[雲棲]


視頻前景提取 (II)【IplImage版本】

以下代碼可以求出視頻的前景,用的方法就是拿第一幀做差分。。。

但是以下代碼有個致命的問題,那就是在視頻幀處理的過程中,不斷的create卻不釋放內存,導致了內存溢出。。

#include "cv.h"
#include "highgui.h"
 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <math.h>
#include <float.h>
#include <limits.h>
#include <time.h>
#include <ctype.h>
 
#ifdef _EiC
#define WIN32
#endif
 
static CvMemStorage* storage = 0;
 
int main()
{
    CvCapture* capture = 0;
    IplImage *frame, *frame_copy = 0,*img1=NULL;
    char* input_name;
 
	input_name = "002.avi";
  
    storage = cvCreateMemStorage(0);
 
    if( !input_name || (isdigit(input_name[0]) && input_name[1] == '\0') )
		//直接從攝像頭讀入
        capture = cvCaptureFromCAM( !input_name ? 0 : input_name[0] - '0' );
    else
		//從AVI視頻讀入
        capture = cvCaptureFromAVI( input_name ); 
 
    cvNamedWindow( "result", 1 );
 
	int flag=0;
    if( capture )
    {
		//如果捕捉到幀了
		//對每一幀做處理

        for(;;)
        {
			if( !cvGrabFrame( capture ))
				break;
            frame = cvRetrieveFrame( capture );
            if( !frame )
                break;
            
			if(flag==0)
			{
				//捕捉第一幀
				frame_copy = cvCreateImage( cvSize(frame->width,frame->height), IPL_DEPTH_8U, frame->nChannels );
				cvCopy(frame,frame_copy,0);
				flag=1;
			}

			img1 = cvCreateImage( cvSize(frame->width,frame->height), IPL_DEPTH_8U, frame->nChannels );

			cvAbsDiff(frame,frame_copy,img1);

			cvShowImage( "src", frame );
			cvShowImage( "result", img1 );
 
 
			//10ms中按任意鍵進入此if塊
            if( cvWaitKey( 10 ) >= 0 )
                break;
        }
 
        cvReleaseImage( &frame_copy );
		cvReleaseImage( &img1 );
        cvReleaseCapture( &capture );
    }
    
	cvDestroyWindow("src");
    cvDestroyWindow("result");
 
    return 0;
}


為了解決這個問題,可以在開始的時候設置標誌位,隻在第一次的時候create圖片:


#include "cv.h"
#include "highgui.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <math.h>
#include <float.h>
#include <limits.h>
#include <time.h>
#include <ctype.h>

#ifdef _EiC
#define WIN32
#endif


int main()
{
	CvCapture* capture = 0;
	IplImage *frame, *frame_copy = 0,*img1=NULL;
	char* input_name;

	input_name = "001.avi";

	if( !input_name || (isdigit(input_name[0]) && input_name[1] == '\0') )
		//直接從攝像頭讀入
		capture = cvCaptureFromCAM( !input_name ? 0 : input_name[0] - '0' );
	else
		//從AVI視頻讀入
		capture = cvCaptureFromAVI( input_name ); 

	cvNamedWindow( "result", 1 );

	int flag=0;
	if( capture )
	{
		//如果捕捉到幀了
		//對每一幀做處理

		for(;;)
		{
			if( !cvGrabFrame( capture ))
				break;
			frame = cvRetrieveFrame( capture );
			if( !frame )
				break;

			if(flag==0)
			{
				//捕捉第一幀
				if( !frame_copy )
					frame_copy = cvCreateImage( cvSize(frame->width,frame->height), IPL_DEPTH_8U, frame->nChannels );

				if( frame->origin == IPL_ORIGIN_TL )  
					cvCopy( frame, frame_copy, 0 );  
				else  
					cvFlip( frame, frame_copy, 0 );

				flag=1;
			}


			//為NULL就create一次,不然內存會溢出
			if( !img1 )
				img1 = cvCreateImage( cvSize(frame->width,frame->height), IPL_DEPTH_8U, frame->nChannels );

			cvAbsDiff(frame,frame_copy,img1);

			cvShowImage( "src", frame );
			cvShowImage( "result", img1 );


			//10ms中按任意鍵進入此if塊
			if( cvWaitKey( 10 ) >= 0 )
				break;
		}

		cvReleaseImage( &frame_copy );
		cvReleaseCapture( &capture );

		//不用釋放,因為開始的時候沒有顯式分配內存
		//cvReleaseImage( &frame );
		//cvReleaseImage( &img1 );
	}

	cvDestroyWindow("src");
	cvDestroyWindow("result");

	return 0;
}


最後更新:2017-04-03 05:39:31

  上一篇:go 10年後、20年後我將會是什麼樣子
  下一篇:go 牛腩新聞發布係統總結(二)--相對路徑與絕對路徑