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