using
System;
using
System.Collections.Generic;
using
System.ComponentModel;
using
System.Data;
using
System.Drawing;
using
System.Linq;
using
System.Text;
using
System.Windows.Forms;
using
System.Diagnostics;
using
System.Runtime.InteropServices;
using
AForge.Video;
using
AForge.Video.DirectShow;
using
Emgu.CV;
using
Emgu.CV.CvEnum;
using
Emgu.CV.Structure;
using
Emgu.CV.UI;
using
System.Threading;
namespace
ImageProcessLearn
{
public
partial
class
FormCameraCapture : Form
{
private
int
framesCaptured;
//
已经捕获的视频帧数
private
int
frameCount;
//
需要捕获的总帧数
private
Stopwatch sw;
//
计时器
private
VideoCaptureDevice captureAForge
=
null
;
//
AForge视频捕获对象
private
bool
stopCapture;
//
是否停止捕获视频
private
object
lockObject
=
new
object
();
public
FormCameraCapture()
{
InitializeComponent();
sw
=
new
Stopwatch();
}
//
窗体加载时,获取视频捕获设备列表
private
void
FormCameraCapture_Load(
object
sender, EventArgs e)
{
FilterInfoCollection videoDevices
=
new
FilterInfoCollection(FilterCategory.VideoInputDevice);
if
(videoDevices
!=
null
&&
videoDevices.Count
>
0
)
{
int
idx
=
0
;
foreach
(FilterInfo device
in
videoDevices)
{
cmbCaptureDevice.Items.Add(
new
DeviceInfo(device.Name, device.MonikerString, idx, FilterCategory.VideoInputDevice));
idx
++
;
}
cmbCaptureDevice.SelectedIndex
=
0
;
}
}
//
当改变视频设备时,重新填充该设备对应的能力
private
void
cmbCaptureDevice_SelectedIndexChanged(
object
sender, EventArgs e)
{
if
(cmbCaptureDevice.SelectedItem
!=
null
)
{
//
保存原来选择的设备能力
Size oldFrameSize
=
new
Size(
0
,
0
);
int
oldMaxFrameRate
=
0
;
if
(cmbDeviceCapability.SelectedItem
!=
null
)
{
oldFrameSize
=
((DeviceCapabilityInfo)cmbDeviceCapability.SelectedItem).FrameSize;
oldMaxFrameRate
=
((DeviceCapabilityInfo)cmbDeviceCapability.SelectedItem).MaxFrameRate;
}
//
清除设备能力
cmbDeviceCapability.Items.Clear();
//
添加新的设备能力
int
oldCapIndex
=
-
1
;
//
原来选择的设备能力的新索引
VideoCaptureDevice video
=
new
VideoCaptureDevice(((DeviceInfo)cmbCaptureDevice.SelectedItem).MonikerString);
for
(
int
i
=
0
; i
<
video.VideoCapabilities.Length; i
++
)
{
VideoCapabilities cap
=
video.VideoCapabilities[i];
DeviceCapabilityInfo capInfo
=
new
DeviceCapabilityInfo(cap.FrameSize, cap.MaxFrameRate);
cmbDeviceCapability.Items.Add(capInfo);
if
(oldFrameSize
==
capInfo.FrameSize
&&
oldMaxFrameRate
==
capInfo.MaxFrameRate)
oldCapIndex
=
i;
}
//
重新选择原来的设备能力,或者选一个新的能力
if
(oldCapIndex
==
-
1
)
oldCapIndex
=
0
;
cmbDeviceCapability.SelectedIndex
=
oldCapIndex;
}
}
//
当改变设备能力时
private
void
cmbDeviceCapability_SelectedIndexChanged(
object
sender, EventArgs e)
{
if
(
int
.Parse(txtRate.Text)
>=
((DeviceCapabilityInfo)cmbDeviceCapability.SelectedItem).MaxFrameRate)
txtRate.Text
=
((DeviceCapabilityInfo)cmbDeviceCapability.SelectedItem).MaxFrameRate.ToString();
}
//
性能测试:测试获取指定帧数的视频,并将其转换成图像,所需要的时间,然后计算出FPS
private
void
btnPerformTest_Click(
object
sender, EventArgs e)
{
int
frameCount
=
int
.Parse(txtFrameCount.Text);
if
(frameCount
<=
0
)
frameCount
=
300
;
DeviceInfo device
=
(DeviceInfo)cmbCaptureDevice.SelectedItem;
btnPerformTest.Enabled
=
false
;
btnStart.Enabled
=
false
;
txtResult.Text
+=
PerformTestWithAForge(device.MonikerString, frameCount);
txtResult.Text
+=
PerformTestWithEmguCv(device.Index, frameCount);
txtResult.Text
+=
PerformTestWithOpenCv(device.Index, frameCount);
btnPerformTest.Enabled
=
true
;
btnStart.Enabled
=
true
;
}
//
AForge性能测试
private
string
PerformTestWithAForge(
string
deviceMonikerString,
int
frameCount)
{
VideoCaptureDevice video
=
new
VideoCaptureDevice(deviceMonikerString);
video.NewFrame
+=
new
NewFrameEventHandler(PerformTest_NewFrame);
video.DesiredFrameSize
=
((DeviceCapabilityInfo)cmbDeviceCapability.SelectedItem).FrameSize;
video.DesiredFrameRate
=
int
.Parse(txtRate.Text);
framesCaptured
=
0
;
this
.frameCount
=
frameCount;
video.Start();
sw.Reset();
sw.Start();
video.WaitForStop();
double
time
=
sw.Elapsed.TotalMilliseconds;
return
string
.Format(
"
AForge性能测试,帧数:{0},耗时:{1:F05}毫秒,FPS:{2:F02},设定({3})\r\n
"
, frameCount, time, 1000d
*
frameCount
/
time, GetSettings());
}
void
PerformTest_NewFrame(
object
sender, NewFrameEventArgs eventArgs)
{
framesCaptured
++
;
if
(framesCaptured
>
frameCount)
{
sw.Stop();
VideoCaptureDevice video
=
sender
as
VideoCaptureDevice;
video.SignalToStop();
}
}
//
EmguCv性能测试
private
string
PerformTestWithEmguCv(
int
deviceIndex,
int
frameCount)
{
Capture video
=
new
Capture(deviceIndex);
video.SetCaptureProperty(CAP_PROP.CV_CAP_PROP_FRAME_WIDTH, ((DeviceCapabilityInfo)cmbDeviceCapability.SelectedItem).FrameSize.Width);
video.SetCaptureProperty(CAP_PROP.CV_CAP_PROP_FRAME_HEIGHT, ((DeviceCapabilityInfo)cmbDeviceCapability.SelectedItem).FrameSize.Height);
video.SetCaptureProperty(CAP_PROP.CV_CAP_PROP_FPS,
double
.Parse(txtRate.Text));
sw.Reset();
sw.Start();
for
(
int
i
=
0
; i
<
frameCount; i
++
)
video.QueryFrame();
sw.Stop();
video.Dispose();
double
time
=
sw.Elapsed.TotalMilliseconds;
return
string
.Format(
"
EmguCv性能测试,帧数:{0},耗时:{1:F05}毫秒,FPS:{2:F02},设定({3})\r\n
"
, frameCount, time, 1000d
*
frameCount
/
time, GetSettings());
}
//
OpenCv性能测试
private
string
PerformTestWithOpenCv(
int
deviceIndex,
int
frameCount)
{
IntPtr ptrVideo
=
CvInvoke.cvCreateCameraCapture(deviceIndex);
CvInvoke.cvSetCaptureProperty(ptrVideo, CAP_PROP.CV_CAP_PROP_FRAME_WIDTH, ((DeviceCapabilityInfo)cmbDeviceCapability.SelectedItem).FrameSize.Width);
CvInvoke.cvSetCaptureProperty(ptrVideo, CAP_PROP.CV_CAP_PROP_FRAME_HEIGHT, ((DeviceCapabilityInfo)cmbDeviceCapability.SelectedItem).FrameSize.Height);
CvInvoke.cvSetCaptureProperty(ptrVideo, CAP_PROP.CV_CAP_PROP_FPS,
double
.Parse(txtRate.Text));
sw.Reset();
sw.Start();
for
(
int
i
=
0
; i
<
frameCount; i
++
)
CvInvoke.cvQueryFrame(ptrVideo);
sw.Stop();
CvInvoke.cvReleaseCapture(
ref
ptrVideo);
double
time
=
sw.Elapsed.TotalMilliseconds;
return
string
.Format(
"
OpenCv性能测试,帧数:{0},耗时:{1:F05}毫秒,FPS:{2:F02},设定({3})\r\n
"
, frameCount, time, 1000d
*
frameCount
/
time, GetSettings());
}
//
得到设置所对应的字符串
private
string
GetSettings()
{
return
string
.Format(
"
摄像头:{0},尺寸:{1}x{2},FPS:{3}
"
, ((DeviceInfo)cmbCaptureDevice.SelectedItem).Name,
((DeviceCapabilityInfo)cmbDeviceCapability.SelectedItem).FrameSize.Width,
((DeviceCapabilityInfo)cmbDeviceCapability.SelectedItem).FrameSize.Height,
txtRate.Text);
}
//
开始捕获视频
private
void
btnStart_Click(
object
sender, EventArgs e)
{
//
得到设置项
DeviceInfo cameraDevice
=
(DeviceInfo)cmbCaptureDevice.SelectedItem;
Size frameSize
=
((DeviceCapabilityInfo)cmbDeviceCapability.SelectedItem).FrameSize;
int
rate
=
int
.Parse(txtRate.Text);
ThreadParam param
=
new
ThreadParam(cameraDevice,
new
DeviceCapabilityInfo(frameSize, rate));
if
(rbAForge.Checked)
{
captureAForge
=
new
VideoCaptureDevice(cameraDevice.MonikerString);
captureAForge.DesiredFrameSize
=
frameSize;
captureAForge.DesiredFrameRate
=
rate;
captureAForge.NewFrame
+=
new
NewFrameEventHandler(captureAForge_NewFrame);
txtResult.Text
+=
string
.Format(
"
开始捕获视频(方式:AForge,开始时间:{0})......\r\n
"
, DateTime.Now.ToLongTimeString());
framesCaptured
=
0
;
sw.Reset();
sw.Start();
captureAForge.Start();
}
else
if
(rbEmguCv.Checked)
{
stopCapture
=
false
;
Thread captureThread
=
new
Thread(
new
ParameterizedThreadStart(CaptureWithEmguCv));
captureThread.Start(param);
}
else
if
(rbOpenCv.Checked)
{
stopCapture
=
false
;
Thread captureThread
=
new
Thread(
new
ParameterizedThreadStart(CaptureWithOpenCv));
captureThread.Start(param);
}
btnStart.Enabled
=
false
;
btnStop.Enabled
=
true
;
btnPerformTest.Enabled
=
false
;
}
private
void
captureAForge_NewFrame(
object
sender, NewFrameEventArgs eventArgs)
{
pbCapture.Image
=
(Bitmap)eventArgs.Frame.Clone();
lock
(lockObject)
{
framesCaptured
++
;
}
}
//
EmguCv视频捕获
private
void
CaptureWithEmguCv(
object
objParam)
{
bool
stop
=
false
;
int
framesCaptured
=
0
;
Stopwatch sw
=
new
Stopwatch();
txtResult.Invoke(
new
AddResultDelegate(AddResultMethod),
string
.Format(
"
开始捕获视频(方式:EmguCv,开始时间:{0})......\r\n
"
, DateTime.Now.ToLongTimeString()));
ThreadParam param
=
(ThreadParam)objParam;
Capture capture
=
new
Capture(param.deviceInfo.Index);
capture.SetCaptureProperty(CAP_PROP.CV_CAP_PROP_FRAME_WIDTH, param.deviceCapability.FrameSize.Width);
capture.SetCaptureProperty(CAP_PROP.CV_CAP_PROP_FRAME_HEIGHT, param.deviceCapability.FrameSize.Height);
capture.SetCaptureProperty(CAP_PROP.CV_CAP_PROP_FPS, param.deviceCapability.MaxFrameRate);
sw.Start();
while
(
!
stop)
{
pbCapture.Image
=
capture.QueryFrame().Bitmap;
framesCaptured
++
;
lock
(lockObject)
{
stop
=
stopCapture;
}
}
sw.Stop();
txtResult.Invoke(
new
AddResultDelegate(AddResultMethod),
string
.Format(
"
捕获视频结束(方式:EmguCv,结束时间:{0},用时:{1:F05}毫秒,帧数:{2},FPS:{3:F02})\r\n
"
,
DateTime.Now.ToLongTimeString(), sw.Elapsed.TotalMilliseconds, framesCaptured, framesCaptured
/
sw.Elapsed.TotalSeconds));
capture.Dispose();
}
//
OpenCv视频捕获
private
void
CaptureWithOpenCv(
object
objParam)
{
bool
stop
=
false
;
int
framesCaptured
=
0
;
Stopwatch sw
=
new
Stopwatch();
txtResult.Invoke(
new
AddResultDelegate(AddResultMethod),
string
.Format(
"
开始捕获视频(方式:OpenCv,开始时间:{0})......\r\n
"
, DateTime.Now.ToLongTimeString()));
ThreadParam param
=
(ThreadParam)objParam;
IntPtr ptrCapture
=
CvInvoke.cvCreateCameraCapture(param.deviceInfo.Index);
CvInvoke.cvSetCaptureProperty(ptrCapture, CAP_PROP.CV_CAP_PROP_FRAME_WIDTH, param.deviceCapability.FrameSize.Width);
CvInvoke.cvSetCaptureProperty(ptrCapture, CAP_PROP.CV_CAP_PROP_FRAME_HEIGHT, param.deviceCapability.FrameSize.Height);
CvInvoke.cvSetCaptureProperty(ptrCapture, CAP_PROP.CV_CAP_PROP_FPS, param.deviceCapability.MaxFrameRate);
sw.Start();
while
(
!
stop)
{
IntPtr ptrImage
=
CvInvoke.cvQueryFrame(ptrCapture);
MIplImage iplImage
=
(MIplImage)Marshal.PtrToStructure(ptrImage,
typeof
(MIplImage));
Image
<
Bgr,
byte
>
image
=
new
Image
<
Bgr,
byte
>
(iplImage.width, iplImage.height, iplImage.widthStep, iplImage.imageData);
pbCapture.Image
=
image.Bitmap;
//
pbCapture.Image = ImageConverter.IplImagePointerToBitmap(ptrImage);
framesCaptured
++
;
lock
(lockObject)
{
stop
=
stopCapture;
}
}
sw.Stop();
txtResult.Invoke(
new
AddResultDelegate(AddResultMethod),
string
.Format(
"
捕获视频结束(方式:OpenCv,结束时间:{0},用时:{1:F05}毫秒,帧数:{2},FPS:{3:F02})\r\n
"
,
DateTime.Now.ToLongTimeString(), sw.Elapsed.TotalMilliseconds, framesCaptured, framesCaptured
/
sw.Elapsed.TotalSeconds));
CvInvoke.cvReleaseCapture(
ref
ptrCapture);
}
//
停止捕获视频
private
void
btnStop_Click(
object
sender, EventArgs e)
{
if
(captureAForge
!=
null
)
{
sw.Stop();
if
(captureAForge.IsRunning)
captureAForge.SignalToStop();
captureAForge
=
null
;
txtResult.Text
+=
string
.Format(
"
捕获视频结束(方式:AForge,结束时间:{0},用时:{1:F05}毫秒,帧数:{2},FPS:{3:F02})\r\n
"
,
DateTime.Now.ToLongTimeString(), sw.Elapsed.TotalMilliseconds, framesCaptured, framesCaptured
/
sw.Elapsed.TotalSeconds);
}
lock
(lockObject)
{
stopCapture
=
true
;
}
btnStart.Enabled
=
true
;
btnStop.Enabled
=
false
;
btnPerformTest.Enabled
=
true
;
}
//
用于在工作线程中更新结果的委托及方法
public
delegate
void
AddResultDelegate(
string
result);
public
void
AddResultMethod(
string
result)
{
txtResult.Text
+=
result;
}
}
//
设备信息
public
struct
DeviceInfo
{
public
string
Name;
public
string
MonikerString;
public
int
Index;
Guid Category;
public
DeviceInfo(
string
name,
string
monikerString,
int
index) :
this
(name, monikerString, index, Guid.Empty)
{
}
public
DeviceInfo(
string
name,
string
monikerString,
int
index, Guid category)
{
Name
=
name;
MonikerString
=
monikerString;
Index
=
index;
Category
=
category;
}
public
override
string
ToString()
{
return
Name;
}
}
//
设备能力
public
struct
DeviceCapabilityInfo
{
public
Size FrameSize;
public
int
MaxFrameRate;
public
DeviceCapabilityInfo(Size frameSize,
int
maxFrameRate)
{
FrameSize
=
frameSize;
MaxFrameRate
=
maxFrameRate;
}
public
override
string
ToString()
{
return
string
.Format(
"
{0}x{1} {2}fps
"
, FrameSize.Width, FrameSize.Height, MaxFrameRate);
}
}
//
传递到捕获视频工作线程的参数
public
struct
ThreadParam
{
public
DeviceInfo deviceInfo;
public
DeviceCapabilityInfo deviceCapability;
public
ThreadParam(DeviceInfo deviceInfo, DeviceCapabilityInfo deviceCapability)
{
this
.deviceInfo
=
deviceInfo;
this
.deviceCapability
=
deviceCapability;
}
}
}