本文基于开源的GOCW和Directshow.net,实现图像采集等操作。最为关键的部分在于可以实现摄像头的控制,同时关于视频采集进行了实现。
具体的内容请关注首发于51CTO的课程《基于Csharp+OpenCV图像处理实战》
首先拖控件,拉出窗体具体样子。
二、引入Directshow.net,开启摄像头预览
using DirectShowLib;
namespace WINFORM_DEMO
{
public partial class Form2 : Form
{
private Capture cam;
public Form2()
{
InitializeComponent();
//构造摄像头数据
foreach (DsDevice ds in DsDevice.GetDevicesOfCat(FilterCategory.VideoInputDevice))
{
cbCam.Items.Add(ds.Name);
}
//初始化摄像头
InitVideoDevice();
}
////helper////
public void InitVideoDevice()
{
try
{
if (cam != null)
cam.Dispose();
//读取参数
int VIDEODEVICE = 0; // zero based index of video capture device to use
const int VIDEOWIDTH = 640;// 是用默认(最大)分辨率
const int VIDEOHEIGHT = 480; // Depends on video device caps
const int VIDEOBITSPERPIXEL = 24; // BitsPerPixel values determined by device
cam = new Capture(VIDEODEVICE, VIDEOWIDTH, VIDEOHEIGHT, VIDEOBITSPERPIXEL, picPreview);
}
catch
{
MessageBox.Show("摄像头打开错误,请首先确保摄像头连接并至少支持1024*768分辨率!");
}
}
}
}
在这里,我们通过引入Capture.cs达到获取所有摄像头的目的,实现了摄像头预览。注意这的ViDEODEVICE是0,那么通过修改其就可以开启其他摄像头,需要注意的是首先要进行关闭。这里通过一个简单的重构可以达到目的。
////helper////
public void InitVideoDevice(int VIDEODEVICE = 0)
{
try
{
if (cam != null)
cam.Dispose();
//读取参数
const int VIDEOWIDTH = 640;// 是用默认(最大)分辨率
const int VIDEOHEIGHT = 480; // Depends on video device caps
const int VIDEOBITSPERPIXEL = 24; // BitsPerPixel values determined by device
cam = new Capture(VIDEODEVICE, VIDEOWIDTH, VIDEOHEIGHT, VIDEOBITSPERPIXEL, picPreview);
}
catch
{
MessageBox.Show("摄像头打开错误,请首先确保摄像头连接并至少支持1024*768分辨率!");
}
}
private void button1_Click(object sender, EventArgs e)
{
//获得选择的摄像头
int iSelect = cbCam.SelectedIndex;
//开启新摄像头
InitVideoDevice(iSelect);
}
最后, 添加摄像头属性控制,这里使用的是Dshow的相关内容,所以比较晦涩。
/// <summary>
/// Displays a property page for a filter
/// </summary>
/// <param name="dev">The filter for which to display a property page</param>
private void DisplayPropertyPage(IBaseFilter dev)
{
//Get the ISpecifyPropertyPages for the filter
ISpecifyPropertyPages pProp = dev as ISpecifyPropertyPages;
int hr = 0;
if (pProp == null)
{
//If the filter doesn't implement ISpecifyPropertyPages, try displaying IAMVfwCompressDialogs instead!
IAMVfwCompressDialogs compressDialog = dev as IAMVfwCompressDialogs;
if (compressDialog != null)
{
hr = compressDialog.ShowDialog(VfwCompressDialogs.Config, IntPtr.Zero);
DsError.ThrowExceptionForHR(hr);
}
else
{
MessageBox.Show("Item has no property page", "No Property Page", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
}
return;
}
//Get the name of the filter from the FilterInfo struct
FilterInfo filterInfo;
hr = dev.QueryFilterInfo(out filterInfo);
DsError.ThrowExceptionForHR(hr);
// Get the propertypages from the property bag
DsCAUUID caGUID;
hr = pProp.GetPages(out caGUID);
DsError.ThrowExceptionForHR(hr);
//Create and display the OlePropertyFrame
object oDevice = (object)dev;
hr = OleCreatePropertyFrame(this.Handle, 0, 0, filterInfo.achName, 1, ref oDevice, caGUID.cElems, caGUID.pElems, 0, 0, IntPtr.Zero);
DsError.ThrowExceptionForHR(hr);
Marshal.ReleaseComObject(oDevice);
if (filterInfo.pGraph != null)
{
Marshal.ReleaseComObject(filterInfo.pGraph);
}
// Release COM objects
Marshal.FreeCoTaskMem(caGUID.pElems);
}
为了正确使用,你还需要添加
//A (modified) definition of OleCreatePropertyFrame found here: http://groups.google.no/group/microsoft.public.dotnet.languages.csharp/browse_thread/thread/db794e9779144a46/55dbed2bab4cd772?lnk=st&q=[DllImport(%22olepro32.dll%22)]&rnum=1&hl=no#55dbed2bab4cd772
[DllImport("oleaut32.dll", CharSet = CharSet.Unicode, ExactSpelling = true)]
public static extern int OleCreatePropertyFrame(
IntPtr hwndOwner,
int x,
int y,
[MarshalAs(UnmanagedType.LPWStr)] string lpszCaption,
int cObjects,
[MarshalAs(UnmanagedType.Interface, ArraySubType = UnmanagedType.IUnknown)]
ref object ppUnk,
int cPages,
IntPtr lpPageClsID,
int lcid,
int dwReserved,
IntPtr lpvReserved);
以及
using System.Runtime.InteropServices;
并且在摄像头打开的时候添加相关变量定义。
private void button1_Click(object sender, EventArgs e)
{
//获得选择的摄像头
int iSelect = cbCam.SelectedIndex;
//开启新摄像头
InitVideoDevice(iSelect);
//生成配套的视频控制界面
if (theDevice != null)
{
Marshal.ReleaseComObject(theDevice);
theDevice = null;
}
//Create the filter for the selected video input device
string devicepath = cbCam.SelectedItem.ToString();
theDevice = CreateFilter(FilterCategory.VideoInputDevice, devicepath);
}
那么到这一步,基于开源的GOCW和Directshow.net,实现图像采集等操作就已经完成。下一步就是应该引入GOCW,实现实时图像处理。