C++ 程序使用 OpenCV 实现视频捕获
前言
这是一个使用 Visual C++ 窗口表单编写的简单视频捕捉应用程序。这个工程既演示了窗口表单应用程序的创建,又演示了 OpenCV 的 Visual C++ 配置。
OpenCV 是免费的计算机视觉软件,也是图像处理的开源库。本文帮助程序员配置 visual c++ 开发环境,从而运行基于窗口控制的 OpenCV 应用程序。
OpenCV 库可以集成到开发环境中。它易于配置,如下六步展示了怎样来配置 visual studio 2010。
这篇文章涉及一个视频捕捉工程,它由 Visual Studio 2010 版本开发而成。
配置Visual C++
准备Visual Studio 2010
步骤1:
在项目的属性管理器中选择“Debug|Win32”,右键点击它,然后选择属性并继续下一步。
步骤2:
从C/C++范畴中选择通用的子范畴。选择添加额外的文件夹,添加下面的路径。
C:\opencv\build\include;
对于64位:
C:\opencv\build\x86\vc10\bin;
对于32位:
C:\opencv\build\x64\vc10\bin;
步骤3:
如果系统是64位的,选择库路径“C:\opencv\build\x86\vc10\lib”,否则选择库文件“C:\opencv\build\x64\vc10\lib”,然后点击Ok按钮。
步骤4:
在这一步中,需要添加OpenCV库。它们位于“C:\opencv\build\x86\vc10\lib”。
对于Debug版:
opencv_calib3d248d.lib | opencv_contrib248d.lib | opencv_core248d.lib |
opencv_features2d248d.lib | opencv_flann248d.lib | opencv_gpu248d.lib |
opencv_highgui248d.lib | opencv_imgproc248d.lib | opencv_legacy248d.lib |
opencv_ml248d.lib | opencv_nonfree248d.lib | opencv_objdetect248d.lib |
opencv_ocl248d.lib | opencv_photo248d.lib | opencv_stitching248d.lib |
opencv_superres248d.lib | opencv_video248d.lib | opencv_videostab248d.lib |
发布准备
在文件名中删除最后的字母 d。如 opencv_calib3d248d.lib 到 opencv_calib3d248.lib 等等。
步骤5:
变换通用语言运行支持,从纯MSIL通用语言运行支持(/clr:pure)换为通用语言运行支持(/clr)。然后点击“ok”完成配置。
步骤6:
添加下列环境地址:
64位:C:\opencv\build\x86\vc10\bin;
32位:C:\opencv\build\x64\vc10\bin;
使用代码
在开始写代码之前,需要如下所示一样包含头文件。在头文件之后的命名空间外,声明capture和frame变量。这些变量是指针变量。
#pragma once #include "opencv/cv.h" #include "opencv/highgui.h" #include "opencv2/opencv.hpp" #include "opencv2/core/core.hpp" CvCapture* capture; IplImage* frame;
cvCaptureFromCAM函数初始化第一个摄像头的采集(索引为0)。如果索引传入的为1,那么它初始化的是第二个摄像头,以此类推。
capture = cvCaptureFromCAM(0);
进度条以视频总帧数来初始化。CV_CAP_PROP_FRAME_COUNT是传递给cvGetCaptureProperty的一个常量,来得到视频的总帧数,而不是摄像头的。
trackBar1->Maximum = (int)cvGetCaptureProperty(capture,CV_CAP_PROP_FRAME_COUNT);
从资源中释放采集。
cvReleaseCapture(&capture);
下面的函数从摄像头中采集视频,也可以从像*.avi,*.mp4的视频文件中采集视频。
private: System::Void button2_Click(System::Object^ sender, System::EventArgs^ e) { if(comboBox1->Text == "") { MessageBox::Show(this,"Select Capture Method","Error!!!"); } if(button2->Text == "Start") { if (comboBox1->Text == "Capture From Camera") { capture = cvCaptureFromCAM(0); trackBar1->Minimum = 0; trackBar1->Maximum = 0; button2->Text = "Stop"; timer1->Start(); } else if (comboBox1->Text == "Capture From File") { openFileDialog1->Filter = "AVI files (*.avi)|*.txt|All files (*.*)|*.*"; openFileDialog1->FilterIndex = 2; openFileDialog1->RestoreDirectory = true; openFileDialog1->FileName =""; if ( openFileDialog1->ShowDialog() == System::Windows::Forms::DialogResult::OK ) { char *fileName = (char*) Marshal::StringToHGlobalAnsi(openFileDialog1->FileName).ToPointer(); capture = cvCaptureFromFile(fileName); trackBar1->Minimum = 0; trackBar1->Maximum = (int)cvGetCaptureProperty(capture,CV_CAP_PROP_FRAME_COUNT); button2->Text = "Stop"; timer1->Start(); } } } else if(button2->Text == "Stop") { cvReleaseCapture(&capture); button2->Text = "Start"; timer1->Stop(); } }
cvQueryFrame函数查询当前视频采集的帧数,分配给frame变量。
frame = cvQueryFrame(capture);
下面的声明是OpenCV中imshow("windowname",frame)函数的一个替换,用来显示图像。
pictureBox1->Image = gcnew System::Drawing::Bitmap(frame->width,frame->height,frame->widthStep,System::Drawing::Imaging::PixelFormat::Format24bppRgb,(System::IntPtr) frame->imageData); pictureBox1->Refresh();
定时器初始化为30个时间间隔。30个时间间隔之后将执行此函数。下面的函数将查询帧,并提取出视频的属性。以下常量用于提取视频属性:
CV_CAP_PROP_POS_FRAMES : 获得视频当前帧位置。
CV_CAP_PROP_FOURCC : 获得视频信息。
CV_CAP_PROP_POS_MSEC : 获得时间信息。
CV_CAP_PROP_FRAME_HEIGHT : 获得视频帧高。
CV_CAP_PROP_FRAME_WIDTH : 获得视频帧宽。
CV_CAP_PROP_FPS : 获得视频帧率(每秒多少帧)。.
private: System::Void timer1_Tick(System::Object^ sender, System::EventArgs^ e) { try { frame = cvQueryFrame(capture); if(frame != NULL) { pictureBox1->Image = gcnew System::Drawing::Bitmap(frame->width,frame->height,frame->widthStep,System::Drawing::Imaging::PixelFormat::Format24bppRgb,(System::IntPtr) frame->imageData); pictureBox1->Refresh(); trackBar1->Value = (int)cvGetCaptureProperty(capture,CV_CAP_PROP_POS_FRAMES); double codec_double = cvGetCaptureProperty(capture,CV_CAP_PROP_FOURCC); label6->Text = "Codec: " + System::Text::Encoding::UTF8->GetString(BitConverter::GetBytes((int)codec_double)); label7->Text = "Time: " + (TimeSpan::FromMilliseconds( cvGetCaptureProperty(capture,CV_CAP_PROP_POS_MSEC) ).ToString())->Substring(0, 8); label8->Text = "Frame No.: " + (int)cvGetCaptureProperty(capture,CV_CAP_PROP_POS_FRAMES); label9->Text = "Video Resolution: " + (int)cvGetCaptureProperty(capture,CV_CAP_PROP_FRAME_HEIGHT) + " X " + (int)cvGetCaptureProperty(capture,CV_CAP_PROP_FRAME_WIDTH); label11->Text = "Video Frame Rate: " + (int)cvGetCaptureProperty(capture,CV_CAP_PROP_FPS); } }catch(...){} }
播放进度条初始化以当前视频帧位置(译者加:,并在拖动进度条时用进度条的进度值设置当前视频帧位置)。CV_CAP_PROP_POS_FRAMES 是一个用来得到视频帧当前位置的常量:
private: System::Void trackBar1_Scroll(System::Object^ sender, System::EventArgs^ e) { cvSetCaptureProperty(capture,CV_CAP_PROP_POS_FRAMES, trackBar1->Value); }
兴趣点
-
学习如何配置 visual c++。
-
学习如何从视频文件中捕获视频。
-
学习如何提取视频属性。
参考:
[1] http://opencv.org/
[2] http://en.wikipedia.org/wiki/OpenCV
[3] http://docs.opencv.org/
[4] http://www.cs.iit.edu/~agam/cs512/lect-notes/opencv-intro/opencv-intro.html
致歉
作者母语非英语,文章用英语表述得可能不好或存在错误,欢迎批评指正。