开源项目之视频会议程序 Omnimeeting

Omnimeeting是一个多平台的Ç+ +视频会议程序,使用库如 LiveMedia、OpenCv、DevIL、WxWidgets、ffmpeg等库,通过RTSP协议在互联网做到实时的摄像/音频流传输。它采用了流媒体的协议有:MJPEG、H263+、MP3、MP3ADU等等,它可以得到360度全方位影像和做一张脸检测/跟踪运动检测。一种新的算法,也可以做一个直接的全方位图像的人脸检测(支持人脸识别和跟踪提供I转换/发送全方位图像的API)。

项目如图:


程序效果如图:





omnimeeting提供的软件包包括omnistuff、streaming、gui三个主要文件和数据示例文件。

部分源码分析:

//创建发送和接受流
void MainFrame::OnMenuPreferencesClick( wxCommandEvent& event )
{

	if ( m_streamer_thread == NULL ) {
		m_streamer_thread = new StreamerCtrlThread( this );
	}

	if ( m_receiver_thread == NULL ) {
		m_receiver_thread = new ReceiverCtrlThread( this );
	}

    
	DialogOptions* window = new DialogOptions(this, m_streamer_thread, m_receiver_thread, this,
		ID_OPTIONS, _("Preferences..."));
    window->Show(true);

}

//创建发送和接受流
void MainFrame::OnMenuPreferencesClick( wxCommandEvent& event )
{

	if ( m_streamer_thread == NULL ) {
		m_streamer_thread = new StreamerCtrlThread( this );
	}

	if ( m_receiver_thread == NULL ) {
		m_receiver_thread = new ReceiverCtrlThread( this );
	}

    
	DialogOptions* window = new DialogOptions(this, m_streamer_thread, m_receiver_thread, this,
		ID_OPTIONS, _("Preferences..."));
    window->Show(true);

}

//关闭 则释放资源
void MainFrame::OnCloseWindow( wxCloseEvent& event )
{
	// provide a clean deletion of objects.
	if ( m_receiver_thread && m_receiver_thread->isReceiving() ) {
		wxMessageDialog dlg1( this, 
			wxT("Please stop by hand the receiver, then close.") , wxT( "Warning" ), wxOK );
		dlg1.ShowModal();
		return;
	}

	if ( m_streamer_thread && m_streamer_thread->isStreaming() ) {
		wxMessageDialog dlg1( this, 
			wxT("Please stop by hand the server streaming, then close."), wxT( "Warning" ), wxOK );
		dlg1.ShowModal();
		return;
	}

	destroy_garbage_collector_for_images ();

    wxWindow* window = this;
    window->Destroy();

	event.Skip();
}

//停止服务
void MainFrame::OnMenuitemActionsStopServerClick( wxCommandEvent& event )
{
	if ( m_streamer_thread != NULL ) {
		if (  m_streamer_thread->isStreaming() ) {
			m_streamer_thread->stopStreaming();

			PrintStatusBarMessage( wxT( "Streaming stopped" ), 0 );

			// no need to delete the object! Being a thread it will auto-destroy after
			// its exiting
			// recreate a new ojbect
			m_streamer_thread = new StreamerCtrlThread( this );
		}
		else {
			wxMessageDialog dlg1( this, wxT( "Server is not running" ), wxT( "Info" ), wxOK );
			dlg1.ShowModal();

			delete m_streamer_thread;
			m_streamer_thread = new StreamerCtrlThread( this );
		}
	}
	else {	
		wxMessageDialog dlg1( this, wxT( "Server is not running" ), wxT( "Info" ), wxOK );
		dlg1.ShowModal();
	}
}

//停止接收
void MainFrame::OnMenuitemActionsStopReceivingClick( wxCommandEvent& event )
{
	if ( m_receiver_thread != NULL ) {
		if ( m_receiver_thread->isReceiving() ) {
			m_receiver_thread->StopReceiving();

			PrintStatusBarMessage( wxT( "Receiving stopped" ), 1 );
		}
		else {
			wxMessageDialog dlg1( this, wxT( "Receiver is not running" ), wxT( "Info" ), wxOK );
			dlg1.ShowModal();

			delete m_receiver_thread;
			m_receiver_thread = new ReceiverCtrlThread( this );
		}
	}
	else {	
		wxMessageDialog dlg1( this, wxT( "Receiver is not running" ), wxT( "Info" ), wxOK );
		dlg1.ShowModal();
	}
}

//接收完毕则释放资源
void MainFrame::OnReceiverCtrlThreadEnd() 
{
	// provide a stop for the face_detecting/tracking class if it's available
	if ( face_detect ) {
		if ( gcard_use == true ) {
			if ( ctrl_gcard ) {
				ctrl_gcard->loop_stop();

				delete ctrl_gcard;
				ctrl_gcard = NULL;
			}

			if ( ctrl_vr_gcard ) {
				ctrl_vr_gcard->loop_stop();

				delete ctrl_vr_gcard;
				ctrl_vr_gcard = NULL;
			}
		}
		else {
			if ( ctrl_lookup ) {
				ctrl_lookup->loop_stop();

				delete ctrl_lookup;
				ctrl_lookup = NULL;
			}
			if ( ctrl_vr_lookup ) {
				ctrl_vr_lookup->loop_stop();

				delete ctrl_vr_lookup;
				ctrl_vr_lookup = NULL;
			}

		}

		ctrl_initialized = false;
		face_detect = false;
	}

	// important!: set to null our class, so that we can recreate it when necessary
	m_receiver_thread = NULL;

	reset_displayed_image_vector();

	clear_garbage_collector_for_images();

	video_received_window = false;
}

omnistuff测试代码:

int main(int argc, char**argv ) {

	/* ok, hardcode them for now... */
	double min_radius = 40;
	double max_radius = 220;
	double omni_center_x = 326;
	double omni_center_y = 250;
	OmniAlgoSimpleDetection<OmniGCardConverter, double, IplImage, CvPoint> *ctrl;
	OmniConversion<OmniGCardConverter, double, IplImage, CvPoint> *conv;
	bool ctrl_initialized = false;
	IplImage *frame;

	// init capturing
	CvCapture* capture = 0;

#ifdef WIN32
	char* filename = "..\\..\\data\\videos\\video_test-1-divx5.avi";
#else
	char* filename = "../../data/videos/video_test-1-divx5.avi";
#endif


	// hardcoding... it ugly but this is a sample test file
	const int c_array_length = 2;
	const char *c_array[c_array_length];

#ifdef WIN32
	// this seems to be the best Haar-cascade combination: it gives the lowest number of false-positive
	// Anyway improving the xml's with a good haar learning can rise up the performances.
	c_array[0] = "..\\..\\omnistuff\\data\\haarcascades\\haarcascade_upperbody.xml";
	c_array[1] = "..\\..\\omnistuff\\data\\haarcascades\\haarcascade_frontalface_default.xml";
#else
	c_array[0] = "../../omnistuff/data/haarcascades/haarcascade_upperbody.xml";
	c_array[1] = "../../omnistuff/data/haarcascades/haarcascade_frontalface_default.xml";
#endif

	if ( argc != 2 ) {
		printf( "To play a different file read below.\n" );
		printf( "usage: %s <avi file>\n", argv[0] );
		printf( "Now using %s\n", filename );
	}
	else {
		filename = argv[1];
		printf( "Now using %s\n", filename );
	}



	capture = cvCaptureFromAVI( filename ); 

	while ( 1 ) {
		frame = cvQueryFrame( capture );
		if( !frame ) {
			printf( "Some error occurred or end of video reached\n");
            break;
		}

		if ( !ctrl_initialized ) {
			conv = new OmniConversion<OmniGCardConverter, double, IplImage, CvPoint>(
				new OmniGCardConverter(  min_radius, 
								 max_radius, 
								 omni_center_x, 
								 omni_center_y, 
								 640,
								 480,
								 "omnigcardo",
								 "../../omnistuff/data/shaders/vertex_shader.cg",
								 "vertex_shader_main",
								 "../../omnistuff/data/shaders/pixel_shader.cg",
								 "pixel_shader_main") );
	
			if ( conv->is_initialized () ) {
				printf("great, gcard is initialized and ready to use...\n");
				ctrl_initialized = true;
			}
			else {
				printf( "some problem occurred: no gcard available...\n");
				exit(-1);
			}

			ctrl = new OmniAlgoSimpleDetection<OmniGCardConverter, double, IplImage, CvPoint>( conv, 
																			frame, 
																			(const char**)c_array,
																			c_array_length,
																			FREEZE_FRAME_BOUND,
																			TRACK_WINDOW_HITRATE);
		}

		ctrl->loop_next_frame( frame );

		cvWaitKey ( WAIT_KEY_VALUE );
	}

	cvReleaseCapture( &capture );

	return 0;
}


omnitest测试代码:

int main( int argc, char** argv ) {

#ifdef WIN32
	char* filename = "..\\..\\data\\videos\\video_test-1-divx5.avi";
#else
	char* filename = "../../data/videos/video_test-1-divx5.avi";
#endif

	if ( argc != 2 ) {
		printf( "To play a different file read below.\n" );
		printf( "usage: %s <avi file>\n", argv[0] );
		printf( "Now using %s\n", filename );
	}
	else {
		filename = argv[1];
		printf( "Now using %s\n", filename );
	}
    	
	MyTimer timer;
	
	// hardcoding... it ugly but this is a sample test file
	const int c_array_length = 2;
	const char *c_array[c_array_length];

#ifdef WIN32
	// this seems to be the best Haar-cascade combination: it gives the lowest number of false-positive
	// Anyway improving the xml's with a good haar learning can rise up the performances.
	c_array[0] = "..\\..\\omnistuff\\data\\haarcascades\\haarcascade_upperbody.xml";
	c_array[1] = "..\\..\\omnistuff\\data\\haarcascades\\haarcascade_frontalface_default.xml";
#else
	c_array[0] = "../../omnistuff/data/haarcascades/haarcascade_upperbody.xml";
	c_array[1] = "../../omnistuff/data/haarcascades/haarcascade_frontalface_default.xml";
#endif


	// Our OmniCtrl class.
	OmniLoopCtrl *ctrl;
	bool ctrl_initialized = false;

	// one second of timeout
	timer.Start(1000);

	IplImage *frame;

	// init capturing
	CvCapture* capture = 0;
	capture = cvCaptureFromAVI( filename ); 

	while ( 1 ) {
        frame = cvQueryFrame( capture );
		if( !frame ) {
			printf( "Some error occurred or end of video reached\n");
            break;
		}

		if ( !ctrl_initialized ) {
			ctrl = new OmniLoopCtrl( frame, 
									1/(double)RADIUS_MAX, 
									RADIUS_MIN,
									RADIUS_MAX,
									CENTER_X,
									CENTER_Y,
									c_array,
									c_array_length,
									FREEZE_FRAME_BOUND,
									TRACK_WINDOW_HITRATE );
			ctrl_initialized = true;
		}

		ctrl->loop_next_frame( frame );
		timer.frame_per_second++;
	}

	cvReleaseCapture( &capture );
	timer.Stop();
	if ( ctrl_initialized ) {
		ctrl->loop_stop();
		delete ctrl;
	}
	
	return 0;
}

vrfilter_test测试代码:

int main( int argc, char** argv )
{
	//time for fps
	double now_time, end_time ;
	char fps_buff [20];
	CvPoint fps_point = cvPoint(10, 450);
	CvFont font;
	cvInitFont( &font, CV_FONT_HERSHEY_SIMPLEX, 0.6f, 0.6f, 0.0f, 2, CV_AA);
	CvVideoWriter *avi_writer = NULL;
	
#ifdef	USE_GRAPHIC_CARD
	OmniConversion<OmniGCardConverter, double, IplImage, CvPoint> *conv_gcard;
	OmniAlgoVRFilterDetection<OmniGCardConverter, double, IplImage, CvPoint> *ctrl_gcard;	
#else
	OmniConversion<OmniFastLookupTable, int, IplImage, CvPoint> *conv_lu;
	OmniAlgoVRFilterDetection<OmniFastLookupTable, int, IplImage, CvPoint> *ctrl_lu;
#endif		
	
	/* ok, hardcode them for now... */
	int min_radius = 55;
	int max_radius = 220;
	int omni_center_x = 320;
	int omni_center_y = 255;
		
    CvCapture* capture = 0;
	char *filename = NULL;	
	
	cvNamedWindow( "face_window", 1 );
	
	if ( argc != 2 )
		filename = 
#ifdef WIN32
		"..\\..\\data\\videos\\video_test-3-xvid.avi";
#else
		"../../data/videos/video_test-3-xvid.avi";
#endif
	else
		filename  = argv[1];
#ifdef SHOW_FPS_ON_IMAGE	
	int fps = 0;
	int rate = 0;
#endif

	capture = cvCaptureFromAVI( filename ); 
	printf("Using %s as omnidirectional video...\n", filename);
	
    if( !capture )
    {
        fprintf(stderr,"Could not initialize capturing...\n");
        return -1;
    }

	now_time = (double) clock ();
	end_time = (double) clock () + (1 * CLOCKS_PER_SEC);
    sprintf(fps_buff, " %d FPS", fps);
		
	bool initialized = false;

	
	while ( 1 )
    {
		IplImage* frame = 0;
		
        frame = cvQueryFrame( capture );

        if( !frame )
            break;

		if ( !initialized ) {
#ifdef	USE_GRAPHIC_CARD			
			conv_gcard = new OmniConversion<OmniGCardConverter, double, IplImage, CvPoint>(
					new OmniGCardConverter(min_radius, 
							 max_radius, 
							 omni_center_x, 
							 omni_center_y, 
							 640,
							 480,
							 "omnigcardo",
							 "../../omnistuff/data/shaders/vertex_shader.cg",
							 "vertex_shader_main",
							 "../../omnistuff/data/shaders/pixel_shader.cg",
							 "pixel_shader_main",
							 true));
			ctrl_gcard = new OmniAlgoVRFilterDetection<OmniGCardConverter, double, IplImage, CvPoint>( conv_gcard, 			
																									  frame );
#else
			conv_lu = new OmniConversion<OmniFastLookupTable, int, IplImage, CvPoint>(
					new OmniFastLookupTable(min_radius,
											max_radius,
											omni_center_x,
											omni_center_y,
											0.0,
											true ));
			ctrl_lu = new OmniAlgoVRFilterDetection<OmniFastLookupTable, int, IplImage, CvPoint>( conv_lu, 
																					frame );
			
#endif	/* USE_GRAPHIC_CARD */

																					

#ifdef SAVE_PROCESSED_VIDEO
			// FIXME: change that -1 value to a fourcc value to work with linux
			avi_writer = cvCreateAVIWriter( PROCESSED_VIDEO_PATH, CV_FOURCC('X', 'V', 'I', 'D') , PROCESSED_VIDEO_FPS,
					cvSize(frame->width, frame->height) );
#endif /* SAVE_PROCESSED_VIDEO */			
			
			initialized = true;
		}
		
#ifdef	USE_GRAPHIC_CARD		
		ctrl_gcard->loop_next_frame( frame );
#else		
		ctrl_lu->loop_next_frame( frame );
#endif
		
#ifdef SHOW_FPS_ON_IMAGE
		now_time = (double) clock ();
		if (end_time - now_time > DBL_EPSILON){
			fps++;
		}
		else{
			sprintf(fps_buff, " %d FPS", fps);
			end_time = (double) clock () + (1 * CLOCKS_PER_SEC);
			fps = 0;
		}

		cvPutText( frame, fps_buff , fps_point, &font, CV_RGB(0,255,0) );

		rate++;
#endif	/* SHOW_FPS_ON_IMAGE */
		
		cvShowImage( "face_window", frame);
		
#ifdef SAVE_PROCESSED_VIDEO
		cvWriteToAVI (avi_writer, frame);
#endif /* SAVE_PROCESSED_VIDEO */
		cvWaitKey( WAIT_KEY_VALUE );

	}
	
    cvReleaseCapture( &capture );

#ifdef SAVE_PROCESSED_VIDEO
	if (avi_writer != NULL)
		cvReleaseVideoWriter(&avi_writer);
#endif /* SAVE_PROCESSED_VIDEO */
	
}

学习的目标是成熟!~~~

 



评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值