• 基于开源的GOCW和Directshow.net,实现摄像头预览、采集、录像等操作


    本文基于开源的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, 00, filterInfo.achName, 1, ref oDevice, caGUID.cElems, caGUID.pElems, 00, 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,实现实时图像处理。




    附件列表

    • 相关阅读:
      4种常见的缓存问题及解决方案详解
      如果你不了解Java的JVM,那真的很难进BAT一线大厂!
      终于有人把分布式事务说清楚了!
      这3个并发编程的核心,你一定要知道!
      Java垃圾回收机制你还不明白?一线大厂面试必问的!
      几种置换算法
      [ERR] Node 172.168.63.202:7001 is not empty. Either the nodealready knows other nodes (check with CLUSTER NODES) or contains some
      redis集群添加删除节点
      redis集群安装部署
      在Ubuntu下永久修改主机名
    • 原文地址:https://www.cnblogs.com/jsxyhelu/p/14254163.html
    Copyright © 2020-2023  润新知