C# DirectShow預(yù)覽攝像頭并截圖
C# DirectShow預(yù)覽攝像頭并截圖,供大家參考,具體內(nèi)容如下
本事例通過(guò)Windows DirectX Filtergraph 一些列管道將電腦所接入視頻采集設(shè)備的視頻流播放到制定區(qū)域,通過(guò)ISampleGrabberCB接口的BufferCB回調(diào)函數(shù)截取圖片。
用此方法預(yù)覽圖像cpu占用率極低,比其其他事件綁定并逐幀顯示圖像性能更佳。
UI布局:

代碼如下:
using System;
using System.Drawing;
using System.Windows.Forms;
using DirectShowLib;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.ComTypes;
using System.Drawing.Imaging;
namespace Test
{
public partial class FormDirect : Form, ISampleGrabberCB
{
private int _previewWidth = 640;
private int _previewHeight = 480;
private int _previewStride = 0;
private int _previewFPS = 30;
private volatile bool isGrab = false;
IVideoWindow videoWindow = null;
IMediaControl mediaControl = null;
IFilterGraph2 graphBuilder = null;
ICaptureGraphBuilder2 captureGraphBuilder = null;
DsROTEntry rot = null;
public FormDirect()
{
InitializeComponent();
}
private void button2_Click(object sender, EventArgs e)
{
//截圖
isGrab = true;
}
private void button3_Click(object sender, EventArgs e)
{
string button_text = button3.Text;
if (button_text.Equals("Start Webcam"))
{
button3.Text = "Stop Webcam";
StartCamera();
}
else
{
button3.Text = "Start Webcam";
StopCamera();
}
}
private void StartCamera()
{
DsDevice[] devices = DsDevice.GetDevicesOfCat(FilterCategory.VideoInputDevice);
if (devices.Length == 0)
{
MessageBox.Show("No USB webcam connected");
button3.Text = "Start Webcam";
return;
}
else
{
CaptureVideo(devices[0]);
}
}
private void StopCamera()
{
button3.Text = "Start Webcam";
CloseInterfaces();
}
public void CaptureVideo(DsDevice device)
{
pictureBox1.Image = null;
int hr = 0;
IBaseFilter sourceFilter = null;
ISampleGrabber sampleGrabber = null;
try
{
// Get DirectShow interfaces
GetInterfaces();
// Attach the filter graph to the capture graph
hr = this.captureGraphBuilder.SetFiltergraph(this.graphBuilder);
DsError.ThrowExceptionForHR(hr);
// Use the system device enumerator and class enumerator to find
// a video capture/preview device, such as a desktop USB video camera.
sourceFilter = SelectCaptureDevice(device);
// Add Capture filter to graph.
hr = this.graphBuilder.AddFilter(sourceFilter, "Video Capture");
DsError.ThrowExceptionForHR(hr);
// Initialize SampleGrabber.
sampleGrabber = new SampleGrabber() as ISampleGrabber;
// Configure SampleGrabber. Add preview callback.
ConfigureSampleGrabber(sampleGrabber);
// Add SampleGrabber to graph.
hr = this.graphBuilder.AddFilter(sampleGrabber as IBaseFilter, "Frame Callback");
DsError.ThrowExceptionForHR(hr);
// Configure preview settings.
SetConfigParams(this.captureGraphBuilder, sourceFilter, _previewFPS, _previewWidth, _previewHeight);
// Render the preview
hr = this.captureGraphBuilder.RenderStream(PinCategory.Preview, MediaType.Video, sourceFilter, (sampleGrabber as IBaseFilter),null);
DsError.ThrowExceptionForHR(hr);
SaveSizeInfo(sampleGrabber);
// Set video window style and position
SetupVideoWindow();
// Add our graph to the running object table, which will allow
// the GraphEdit application to "spy" on our graph
rot = new DsROTEntry(this.graphBuilder);
// Start previewing video data
hr = this.mediaControl.Run();
DsError.ThrowExceptionForHR(hr);
}
catch
{
MessageBox.Show("An unrecoverable error has occurred.");
}
finally
{
if (sourceFilter != null)
{
Marshal.ReleaseComObject(sourceFilter);
sourceFilter = null;
}
if (sampleGrabber != null)
{
Marshal.ReleaseComObject(sampleGrabber);
sampleGrabber = null;
}
}
}
public void CaptureVideo()
{
pictureBox1.Image = null;
int hr = 0;
IBaseFilter sourceFilter = null;
ISampleGrabber sampleGrabber = null;
try
{
// Get DirectShow interfaces
GetInterfaces();
// Attach the filter graph to the capture graph
hr = this.captureGraphBuilder.SetFiltergraph(this.graphBuilder);
DsError.ThrowExceptionForHR(hr);
// Use the system device enumerator and class enumerator to find
// a video capture/preview device, such as a desktop USB video camera.
sourceFilter = FindCaptureDevice();
// Add Capture filter to graph.
hr = this.graphBuilder.AddFilter(sourceFilter, "Video Capture");
DsError.ThrowExceptionForHR(hr);
// Initialize SampleGrabber.
sampleGrabber = new SampleGrabber() as ISampleGrabber;
// Configure SampleGrabber. Add preview callback.
ConfigureSampleGrabber(sampleGrabber);
// Add SampleGrabber to graph.
hr = this.graphBuilder.AddFilter(sampleGrabber as IBaseFilter, "Frame Callback");
DsError.ThrowExceptionForHR(hr);
// Configure preview settings.
SetConfigParams(this.captureGraphBuilder, sourceFilter, _previewFPS, _previewWidth, _previewHeight);
// Render the preview
hr = this.captureGraphBuilder.RenderStream(PinCategory.Preview, MediaType.Video, sourceFilter, (sampleGrabber as IBaseFilter),null);
DsError.ThrowExceptionForHR(hr);
SaveSizeInfo(sampleGrabber);
// Set video window style and position
SetupVideoWindow();
// Add our graph to the running object table, which will allow
// the GraphEdit application to "spy" on our graph
rot = new DsROTEntry(this.graphBuilder);
// Start previewing video data
hr = this.mediaControl.Run();
DsError.ThrowExceptionForHR(hr);
}
catch
{
MessageBox.Show("An unrecoverable error has occurred.");
}
finally
{
if (sourceFilter != null)
{
Marshal.ReleaseComObject(sourceFilter);
sourceFilter = null;
}
if (sampleGrabber != null)
{
Marshal.ReleaseComObject(sampleGrabber);
sampleGrabber = null;
}
}
}
public IBaseFilter SelectCaptureDevice(DsDevice device)
{
object source = null;
Guid iid = typeof(IBaseFilter).GUID;
device.Mon.BindToObject(null, null, ref iid, out source);
return (IBaseFilter)source;
}
public IBaseFilter FindCaptureDevice()
{
int hr = 0;
#if USING_NET11
UCOMIEnumMoniker classEnum = null;
UCOMIMoniker[] moniker = new UCOMIMoniker[1];
#else
IEnumMoniker classEnum = null;
IMoniker[] moniker = new IMoniker[1];
#endif
object source = null;
// Create the system device enumerator
ICreateDevEnum devEnum = (ICreateDevEnum)new CreateDevEnum();
// Create an enumerator for the video capture devices
hr = devEnum.CreateClassEnumerator(FilterCategory.VideoInputDevice, out classEnum, 0);
DsError.ThrowExceptionForHR(hr);
// The device enumerator is no more needed
Marshal.ReleaseComObject(devEnum);
// If there are no enumerators for the requested type, then
// CreateClassEnumerator will succeed, but classEnum will be NULL.
if (classEnum == null)
{
throw new ApplicationException("No video capture device was detected.\r\n\r\n" +
"This sample requires a video capture device, such as a USB WebCam,\r\n" +
"to be installed and working properly. The sample will now close.");
}
// Use the first video capture device on the device list.
// Note that if the Next() call succeeds but there are no monikers,
// it will return 1 (S_FALSE) (which is not a failure). Therefore, we
// check that the return code is 0 (S_OK).
#if USING_NET11
int i;
if (classEnum.Next (moniker.Length, moniker, IntPtr.Zero) == 0)
#else
if (classEnum.Next(moniker.Length, moniker, IntPtr.Zero) == 0)
#endif
{
// Bind Moniker to a filter object
Guid iid = typeof(IBaseFilter).GUID;
moniker[0].BindToObject(null, null, ref iid, out source);
}
else
{
throw new ApplicationException("Unable to access video capture device!");
}
// Release COM objects
Marshal.ReleaseComObject(moniker[0]);
Marshal.ReleaseComObject(classEnum);
// An exception is thrown if cast fail
return (IBaseFilter)source;
}
public void GetInterfaces()
{
int hr = 0;
// An exception is thrown if cast fail
this.graphBuilder = (IFilterGraph2)new FilterGraph();
this.captureGraphBuilder = (ICaptureGraphBuilder2)new CaptureGraphBuilder2();
this.mediaControl = (IMediaControl)this.graphBuilder;
this.videoWindow = (IVideoWindow)this.graphBuilder;
DsError.ThrowExceptionForHR(hr);
}
public void CloseInterfaces()
{
if (mediaControl != null)
{
int hr = mediaControl.StopWhenReady();
DsError.ThrowExceptionForHR(hr);
}
if (videoWindow != null)
{
videoWindow.put_Visible(OABool.False);
videoWindow.put_Owner(IntPtr.Zero);
}
// Remove filter graph from the running object table.
if (rot != null)
{
rot.Dispose();
rot = null;
}
// Release DirectShow interfaces.
Marshal.ReleaseComObject(this.mediaControl); this.mediaControl = null;
Marshal.ReleaseComObject(this.videoWindow); this.videoWindow = null;
Marshal.ReleaseComObject(this.graphBuilder); this.graphBuilder = null;
Marshal.ReleaseComObject(this.captureGraphBuilder); this.captureGraphBuilder = null;
}
public void SetupVideoWindow()
{
int hr = 0;
// Set the video window to be a child of the PictureBox
hr = this.videoWindow.put_Owner(pictureBox1.Handle);
DsError.ThrowExceptionForHR(hr);
hr = this.videoWindow.put_WindowStyle(WindowStyle.Child);
DsError.ThrowExceptionForHR(hr);
// Make the video window visible, now that it is properly positioned
hr = this.videoWindow.put_Visible(OABool.True);
DsError.ThrowExceptionForHR(hr);
// Set the video position
Rectangle rc = pictureBox1.ClientRectangle;
hr = videoWindow.SetWindowPosition(0, 0, _previewWidth, _previewHeight);
DsError.ThrowExceptionForHR(hr);
}
private void SetConfigParams(ICaptureGraphBuilder2 capGraph, IBaseFilter capFilter, int iFrameRate, int iWidth, int iHeight)
{
int hr;
object config;
AMMediaType mediaType;
// Find the stream config interface
hr = capGraph.FindInterface(
PinCategory.Capture, MediaType.Video, capFilter, typeof(IAMStreamConfig).GUID, out config);
IAMStreamConfig videoStreamConfig = config as IAMStreamConfig;
if (videoStreamConfig == null)
{
throw new Exception("Failed to get IAMStreamConfig");
}
// Get the existing format block
hr = videoStreamConfig.GetFormat(out mediaType);
DsError.ThrowExceptionForHR(hr);
// copy out the videoinfoheader
VideoInfoHeader videoInfoHeader = new VideoInfoHeader();
Marshal.PtrToStructure(mediaType.formatPtr, videoInfoHeader);
// if overriding the framerate, set the frame rate
if (iFrameRate > 0)
{
videoInfoHeader.AvgTimePerFrame = 10000000 / iFrameRate;
}
// if overriding the width, set the width
if (iWidth > 0)
{
videoInfoHeader.BmiHeader.Width = iWidth;
}
// if overriding the Height, set the Height
if (iHeight > 0)
{
videoInfoHeader.BmiHeader.Height = iHeight;
}
// Copy the media structure back
Marshal.StructureToPtr(videoInfoHeader, mediaType.formatPtr, false);
// Set the new format
hr = videoStreamConfig.SetFormat(mediaType);
DsError.ThrowExceptionForHR(hr);
DsUtils.FreeAMMediaType(mediaType);
mediaType = null;
}
private void SaveSizeInfo(ISampleGrabber sampleGrabber)
{
int hr;
// Get the media type from the SampleGrabber
AMMediaType media = new AMMediaType();
hr = sampleGrabber.GetConnectedMediaType(media);
DsError.ThrowExceptionForHR(hr);
if ((media.formatType != FormatType.VideoInfo) || (media.formatPtr == IntPtr.Zero))
{
throw new NotSupportedException("Unknown Grabber Media Format");
}
// Grab the size info
VideoInfoHeader videoInfoHeader = (VideoInfoHeader)Marshal.PtrToStructure(media.formatPtr, typeof(VideoInfoHeader));
_previewStride = _previewWidth * (videoInfoHeader.BmiHeader.BitCount / 8);
DsUtils.FreeAMMediaType(media);
media = null;
}
private void ConfigureSampleGrabber(ISampleGrabber sampleGrabber)
{
AMMediaType media;
int hr;
// Set the media type to Video/RBG24
media = new AMMediaType();
media.majorType = MediaType.Video;
media.subType = MediaSubType.RGB24;
media.formatType = FormatType.VideoInfo;
hr = sampleGrabber.SetMediaType(media);
DsError.ThrowExceptionForHR(hr);
DsUtils.FreeAMMediaType(media);
media = null;
hr = sampleGrabber.SetCallback(this, 1);
DsError.ThrowExceptionForHR(hr);
}
public int BufferCB(double SampleTime, IntPtr pBuffer, int BufferLen)
{
if (isGrab)
{
Bitmap v = new Bitmap(_previewWidth, _previewHeight, _previewStride,PixelFormat.Format24bppRgb, pBuffer);
//v.RotateFlip(RotateFlipType.Rotate180FlipX);
v.RotateFlip(RotateFlipType.Rotate90FlipX);
this.BeginInvoke((MethodInvoker)delegate
{
pictureBox2.BackgroundImage = v;
isGrab = false;
});
}
return 0;
}
public int SampleCB(double SampleTime, IMediaSample pSample)
{
//throw new NotImplementedException();
return 0;
}
}
}
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
C#實(shí)現(xiàn)翻轉(zhuǎn)字符串的方法
這篇文章主要介紹了C#實(shí)現(xiàn)翻轉(zhuǎn)字符串的方法,涉及C#操作字符串的技巧,非常具有實(shí)用價(jià)值,需要的朋友可以參考下2015-04-04
C#使用Http Post方式傳遞Json數(shù)據(jù)字符串調(diào)用Web Service
這篇文章主要為大家詳細(xì)介紹了C#使用Http Post方式傳遞Json數(shù)據(jù)字符串調(diào)用Web Service,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-08-08
C#下實(shí)現(xiàn)創(chuàng)建和刪除目錄的實(shí)例代碼
這篇文章主要介紹了C#下實(shí)現(xiàn)創(chuàng)建和刪除目錄的方法,功能非常實(shí)用,需要的朋友可以參考下2014-08-08
如何獲取C#中方法的執(zhí)行時(shí)間以及其代碼注入詳解
這篇文章主要給大家介紹了關(guān)于如何獲取C#中方法的執(zhí)行時(shí)間以及其代碼注入的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起看看吧2018-11-11
C#實(shí)現(xiàn)生成所有不重復(fù)的組合功能示例
這篇文章主要介紹了C#實(shí)現(xiàn)生成所有不重復(fù)的組合功能,涉及C#數(shù)學(xué)運(yùn)算中組合數(shù)運(yùn)算的相關(guān)原理應(yīng)用操作技巧,需要的朋友可以參考下2017-12-12
C#實(shí)現(xiàn)將程序運(yùn)行信息寫(xiě)入日志的方法
這篇文章主要介紹了C#實(shí)現(xiàn)將程序運(yùn)行信息寫(xiě)入日志的方法,可實(shí)現(xiàn)將程序運(yùn)行信息寫(xiě)入日志并存儲(chǔ)在Debug目錄下的"/Log/PRG"下的功能,涉及C#針對(duì)日志的相關(guān)寫(xiě)入技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-08-08

