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)ComboBox控件顯示出多個(gè)數(shù)據(jù)源屬性的方法
這篇文章主要介紹了C#實(shí)現(xiàn)ComboBox控件顯示出多個(gè)數(shù)據(jù)源屬性的方法,實(shí)例分析了ComboBox控件的使用技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-09-09C#實(shí)體對(duì)象序列化成Json并讓字段的首字母小寫的兩種解決方法
這篇文章主要介紹了C#實(shí)體對(duì)象序列化成Json并讓字段的首字母小寫的兩種方法,在這兩種方法中小編比較推薦使用第二種方法,需要的朋友可以參考下2018-06-06基于C#實(shí)現(xiàn)的端口掃描器實(shí)例代碼
這篇文章主要介紹了基于C#實(shí)現(xiàn)的端口掃描器實(shí)例代碼,需要的朋友可以參考下2014-07-07當(dāng)用戶退出點(diǎn)擊瀏覽器后退仍可回到原來(lái)頁(yè)面的解決方案
這篇文章主要介紹了當(dāng)用戶退出點(diǎn)擊瀏覽器后退仍可回到原來(lái)頁(yè)面的解決方案 的相關(guān)資料,需要的朋友可以參考下2016-03-03基于C#?實(shí)現(xiàn)劉謙春晚魔術(shù)(示例代碼)
劉謙春晚魔術(shù)是一個(gè)讓人嘆為觀止的魔術(shù)表演,其中涉及到了數(shù)學(xué)、編程和創(chuàng)意的結(jié)合,看了春晚魔術(shù)的朋友們,是不是好奇春晚劉謙的魔術(shù)是怎么變的,本文分享C#?實(shí)現(xiàn)劉謙春晚魔術(shù)示例代碼,一起看看吧2024-02-02C#反射在實(shí)際應(yīng)用中的實(shí)例代碼
C#反射在實(shí)際應(yīng)用中的實(shí)例代碼,需要的朋友可以參考一下2013-03-03