• C# Activex调用USB摄像头--附带源码


    前言


    最近在整理一些自己写过的东西,也算是重新熟悉一下并且优化一下吧。

    需求:获取本地USB摄像头视频显示,并且获取图片数据给底层做人脸识别。

    记得当时直接采用H5已经做好了,调试好了。。。。结果放上去使用发现必须需要证书才可以,

    然后因为某些原因(没办法自己写一个ssl证书)只能重写了一个之前使用Activex做的USB控件。

     H5调用USB摄像头参考:https://segmentfault.com/a/1190000011793960

    开发


    闲话:DLL缺少搜索找不到,推荐找dll https://www.zhaodll.com/

    引用:AForge.dll,AForge.Video.DirectShow.dll,AForge.Video.dll

    首先创建一个用户控件>放入一个pictureBox1>放入一个lable

    将用户控件调成灰色(明显。。。)大小随便后面可以调整,pictureBox1在父容器停靠,lab用于错误提示,效果如下:

    用户控件创建

    添加一个 IObjectSafety 接口。

     /*
          IObjectSafety 接口用于通知浏览器:“浏览器,我是安全的”
         */
        [ComImport, Guid("887FC3C3-A970-4A36-92EF-D4EB31541C40")]
        [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
        public interface IObjectSafety
        {
            [PreserveSig]
            int GetInterfaceSafetyOptions(ref Guid riid, [MarshalAs(UnmanagedType.U4)] ref int pdwSupportedOptions, [MarshalAs(UnmanagedType.U4)] ref int pdwEnabledOptions);
    
            [PreserveSig()]
            int SetInterfaceSafetyOptions(ref Guid riid, [MarshalAs(UnmanagedType.U4)] int dwOptionSetMask, [MarshalAs(UnmanagedType.U4)] int dwEnabledOptions);
        }
    View Code

    添加一个基础类,用于数据返回处理。

     public class USBInfo
        {
            /// <summary>
            /// 返回消息
            /// </summary>
            public class ReturnMessage
            {
                public bool result { get; set; }//结果
                public string message { get; set; }//消息
            }
    
            /// <summary>
            /// 返回视频分辨率
            /// </summary>
            public class GetResolvingPower
            {
                public int index { get; set; }//下标 -1(不存在摄像头),-2(发生意外错误)
                public VideoCapabilities Capabilities { get; set; }//信息
                public string error { get; set; }//错误
            }
    
        }
    View Code

    用户控件中实现:

     /// <summary>
        /// 继承IObjectSafety
        /// </summary>
        [ProgId("USBCamera")]
        [ClassInterface(ClassInterfaceType.AutoDual)]
        [Guid("887FC3C3-A970-4A36-92EF-D4EB31541C40")]
        [ComVisible(true)]
        public partial class USBCamera : UserControl, IObjectSafety
        {
            FilterInfoCollection videoDevices;//设备
            VideoCaptureDevice videoSource;//设备信息
            MemoryStream frameData;//图片数据
            static Thread th_usb;//监听线程
            static int sl_usb = 10000;//多久检查一次
            static int index_usb;//第一次打开选择的分辨率
    
            public USBCamera()
            {
                InitializeComponent();
                frameData = new MemoryStream();
            }
    
            //句柄销毁
            protected override void OnHandleDestroyed(EventArgs e)
            {
                Stop();
                base.OnHandleDestroyed(e);
            }
    
            /// <summary>
            /// 设置窗体相关大小
            /// </summary>
            /// <param name="width"></param>
            /// <param name="height"></param>
            /// <param name="fontformat">字体熟悉</param>
            /// <param name="fontsize">字体大小</param>
            /// <param name="promptInfo">提示信息</param>
            /// <param name="sleep">监听间隔</param>
            public void FormSize(int width, int height, string fontFormat, int fontSize, string promptInfo, int sleep)
            {
                this.Size = new Size(width, height);//窗体大小
                this.lab_Prompt.Font = new Font(fontFormat, fontSize, FontStyle.Bold); //字体熟悉
                this.lab_Prompt.ForeColor = Color.Red;//字体颜色
                this.lab_Prompt.Text = promptInfo;//提示信息
    
                //设置字体高宽
                var lab_width = (width / 3);
                var lab_height = (height / 3);
                this.lab_Prompt.Location = new System.Drawing.Point(lab_width, lab_height);
                sl_usb = sleep;//监听时间
            }
    
            /// <summary>
            /// 打开视频
            /// </summary>
            /// <param name="index">USB可用分辨率数组下标</param>
            public void Start(int index)
            {
                index_usb = index;
                if (videoSource != null)
                {
                    videoSource.NewFrame -= new NewFrameEventHandler(video_NewFrame);
                    videoSource.SignalToStop();
                    videoSource = null;
                }
                // 创建视频源
                Trace.WriteLine("usbcamera have cameras" + videoDevices.Count.ToString());
                videoSource = new VideoCaptureDevice(videoDevices[0].MonikerString);
                // 设置新帧事件处理程序
                videoSource.NewFrame += new NewFrameEventHandler(video_NewFrame);
                // 启动视频源
                try
                {
                    videoSource.VideoResolution = this.videoSource.VideoCapabilities[index];
                    videoSource.Start();
    
                    if (th_usb == null || !th_usb.IsAlive)
                    {
                        th_usb = new Thread(GetUSB);
                        th_usb.Start();
                    }
                    this.lab_Prompt.Text = null;
                }
                catch (Exception ex)
                {
                    Trace.WriteLine("usbcamera Start()遇到错误" + ex.Message + ex.StackTrace);
                }
            }
    
            /// <summary>
            /// 停止视频
            /// </summary>
            public void Stop()
            {
                if (videoSource != null)
                {
                    videoSource.NewFrame -= new NewFrameEventHandler(video_NewFrame);
                    //当不再需要捕捉时,发出停止的信号
                    videoSource.SignalToStop();
                    videoSource = null;
                    Trace.WriteLine("usbcamera stop()....");
                    if (pictureBox1.Image != null)//清空控件
                    {
                        pictureBox1.Image.Dispose();
                        pictureBox1.Image = null;
                    }
                    this.lab_Prompt.Text = null;
                }
            }
    
            /// <summary>
            /// 视频帧获取回调
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="eventArgs"></param>
            private void video_NewFrame(object sender, NewFrameEventArgs eventArgs)
            {
                try
                {
                    lab_Prompt.Text = null;
                    Trace.WriteLine("usbcamera video_NewFrame()....");
                    eventArgs.Frame.Save(frameData, ImageFormat.Bmp);
                    if (pictureBox1.InvokeRequired)
                    {
                        //写入数据
                        pictureBox1.BeginInvoke((MethodInvoker)delegate ()
                        {
                            try
                            {
                                if (pictureBox1.Image != null)
                                {
                                    Image img = pictureBox1.Image;
                                    img.Dispose();
                                }
                                pictureBox1.Image = new Bitmap(frameData);
                            }
                            catch (Exception ex)
                            {
                                if (pictureBox1.Image != null)
                                {
                                    pictureBox1.Image.Dispose();
                                    pictureBox1.Image = null;
                                }
                            }
                        });
                    }
                    else
                    {
                        pictureBox1.Image = new Bitmap(frameData);
                    }
                }
                catch (Exception ex)
                {
                    if (pictureBox1.Image != null)
                    {
                        pictureBox1.Image.Dispose();
                        pictureBox1.Image = null;
                    }
                }
            }
    
            /// <summary>
            /// 获取USB(USB连接不正常),不存在给出提示,存在重新Start
            /// </summary>
            public void GetUSB()
            {
                while (true)
                {
                    var usb = new FilterInfoCollection(FilterCategory.VideoInputDevice);
                    if (usb.Count <= 0)
                    {
                        Stop();
                        lab_Prompt.BeginInvoke((MethodInvoker)delegate ()
                        {
                            this.lab_Prompt.Text = "未连接上摄像头,检查连接是否正常。";
                        });
                    }
                    else
                    {
                        //重新连接上 执行Start
                        if (!string.IsNullOrWhiteSpace(this.lab_Prompt.Text))
                        {
                            Start(index_usb);
                        }
                    }
                    Thread.Sleep(sl_usb);
                }
            }
    
            #region USB视频操作
            /// <summary>
            /// 测试Activex是否可用
            /// </summary>
            /// <returns>true/false</returns>
            public bool Connection()
            {
                return true;
            }
    
            /// <summary>
            /// 获取截图
            /// </summary>
            /// <returns></returns>
            public ReturnMessage GetScreenshots()
            {
                try
                {
                    return new ReturnMessage()
                    {
                        result = true,
                        message = Convert.ToBase64String(frameData.ToArray())
                    };
                }
                catch (Exception EX)
                {
                    Trace.WriteLine("usbcamera GetImage() 错误...." + EX.Message + EX.StackTrace);
                    return new ReturnMessage() { result = false, message = EX.Message + " " + EX.StackTrace };
                }
            }
    
            /// <summary>
            /// 获取USB摄像头分辨率
            /// </summary>
            /// <returns>json(GetResolvingPower)</returns>
            public string GetResolution()
            {
                var list = new List<GetResolvingPower>();
                try
                {
                    videoDevices = new FilterInfoCollection(FilterCategory.VideoInputDevice);
                    if (videoDevices.Count > 0)
                    {
                        videoSource = new VideoCaptureDevice(videoDevices[0].MonikerString);
                        for (int i = 0; i < videoSource.VideoCapabilities.Length; i++)
                        {
                            list.Add(new GetResolvingPower
                            {
                                index = i,
                                Capabilities = videoSource.VideoCapabilities[i],
                            });
                        }
                    }
                    else
                    {
                        list.Add(new GetResolvingPower
                        {
                            index = -1,
                            Capabilities = null,
                            error = "不存在USB摄像头",
                        });
                    }
                }
                catch (Exception EX)
                {
                    list.Add(new GetResolvingPower
                    {
                        index = -2,
                        Capabilities = null,
                        error = EX.Source + " " + EX.Message
                    });
                }
                return Newtonsoft.Json.JsonConvert.SerializeObject(list);
            }
            #endregion
    
            #region IObjectSafety 成员直接复制
            private const string _IID_IDispatch = "{00020400-0000-0000-C000-000000000046}";
            private const string _IID_IDispatchEx = "{a6ef9860-c720-11d0-9337-00a0c90dcaa9}";
            private const string _IID_IPersistStorage = "{0000010A-0000-0000-C000-000000000046}";
            private const string _IID_IPersistStream = "{00000109-0000-0000-C000-000000000046}";
            private const string _IID_IPersistPropertyBag = "{37D84F60-42CB-11CE-8135-00AA004BB851}";
    
            private const int INTERFACESAFE_FOR_UNTRUSTED_CALLER = 0x00000001;
            private const int INTERFACESAFE_FOR_UNTRUSTED_DATA = 0x00000002;
            private const int S_OK = 0;
            private const int E_FAIL = unchecked((int)0x80004005);
            private const int E_NOINTERFACE = unchecked((int)0x80004002);
    
            private bool _fSafeForScripting = true;
            private bool _fSafeForInitializing = true;
    
            public int GetInterfaceSafetyOptions(ref Guid riid, ref int pdwSupportedOptions, ref int pdwEnabledOptions)
            {
                int Rslt = E_FAIL;
    
                string strGUID = riid.ToString("B");
                pdwSupportedOptions = INTERFACESAFE_FOR_UNTRUSTED_CALLER | INTERFACESAFE_FOR_UNTRUSTED_DATA;
                switch (strGUID)
                {
                    case _IID_IDispatch:
                    case _IID_IDispatchEx:
                        Rslt = S_OK;
                        pdwEnabledOptions = 0;
                        if (_fSafeForScripting == true)
                            pdwEnabledOptions = INTERFACESAFE_FOR_UNTRUSTED_CALLER;
                        break;
                    case _IID_IPersistStorage:
                    case _IID_IPersistStream:
                    case _IID_IPersistPropertyBag:
                        Rslt = S_OK;
                        pdwEnabledOptions = 0;
                        if (_fSafeForInitializing == true)
                            pdwEnabledOptions = INTERFACESAFE_FOR_UNTRUSTED_DATA;
                        break;
                    default:
                        Rslt = E_NOINTERFACE;
                        break;
                }
    
                return Rslt;
            }
    
            public int SetInterfaceSafetyOptions(ref Guid riid, int dwOptionSetMask, int dwEnabledOptions)
            {
                int Rslt = E_FAIL;
                string strGUID = riid.ToString("B");
                switch (strGUID)
                {
                    case _IID_IDispatch:
                    case _IID_IDispatchEx:
                        if (((dwEnabledOptions & dwOptionSetMask) == INTERFACESAFE_FOR_UNTRUSTED_CALLER) && (_fSafeForScripting == true))
                            Rslt = S_OK;
                        break;
                    case _IID_IPersistStorage:
                    case _IID_IPersistStream:
                    case _IID_IPersistPropertyBag:
                        if (((dwEnabledOptions & dwOptionSetMask) == INTERFACESAFE_FOR_UNTRUSTED_DATA) && (_fSafeForInitializing == true))
                            Rslt = S_OK;
                        break;
                    default:
                        Rslt = E_NOINTERFACE;
                        break;
                }
    
                return Rslt;
            }
    
            #endregion
        }
    View Code

    用于测试的HTML页面代码:

    <!DOCTYPE html>
    <html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
        <title></title>
        <meta charset="utf-8" />
        <script>
    
            //初始化 设置USB控件大小和显示
            var array = new Array();
            window.onload = function () {
                var USBCamera = document.getElementById("USBCamera");
                USBCamera.Stop(); //停止视频
                array = JSON.parse(document.getElementById("USBCamera").GetResolution());//获取USB分辨率
    
                /*
                判断获取数据是否成功(USB连接是否正常)
                大于1为成功,摄像头基本有多个分辨率
                也可以判断返回值中index是否为负数
                获取到的分辨率最大的为第一个下标为:0
                */
                if (array.length > 1) {
                    //分辨率下标 宽 高
                    var index = 0, width = 0, height = 0;
                    for (var i = 0; i < array.length; i++) {
                        var size = array[i].Capabilities.FrameSize;
                        if (size.Width > width && size.Height > height) {
                            index = i;
                            width = size.Width;
                            height = size.Height;
                        }
                    }
                    //此处我获取分辨率的最大值赋值,实际可以更改
                    USBCamera.FormSize(width, height, "宋体", 9, "", 10000);//初始化
                    USBCamera.Start(index);//打开摄像头
                } else {
                    if (array[0].index == -1) { //-1未连接
                        USBCamera.FromSize(400, 400, "宋体", 9, "摄像头未连接", 10000);
    
                    } if (array[0].index == -2) { //-2 获取是发生错误
                        USBCamera.FromSize(400, 400, "宋体", 9, "摄像头连接有异常,请联系管理人员!", 10000);
                    }
                }
            }
    
            //关闭时执行Stop
            window.BeforeUnloadEvent = function () {
                document.getElementById("USBCamera").Stop();
            }
    
            //测试连接
            function TestConnection() {
                alert(document.getElementById("USBCamera").Connection());
            }
    
            //打开摄像头
            function StartCamera() {
                document.getElementById("USBCamera").Start(0);
            }
    
            //关闭摄像头
            function StopCamera() {
                document.getElementById("USBCamera").Stop();
            }
    
            //获取截图
            function GetScreenshots() {
                var imgInfo = document.getElementById("USBCamera").GetScreenshots();
                if (imgInfo.result) {
                    document.getElementById("DisplayScreenshots").src = "data:image/jpg;base64," + imgInfo.message;
                } else {
                    alert("截图获取失败");
                }
            }
    
            //获取分辨率
            function GetResolution() {
                console.log(document.getElementById("USBCamera").GetResolution());
            }
        </script>
    
    </head>
    <body>
        <div>
            <button onclick="TestConnection()">测试连接</button>
            <button onclick="StartCamera()">打开摄像头</button>
            <button onclick="StopCamera()">关闭摄像头</button>
            <button onclick="GetScreenshots()">获取截图</button>
            <button onclick="GetResolution()">获取分辨率</button>
        </div>
        <hr />
        <h3>截图显示</h3>
        <img style="300px;height:300px;" id="DisplayScreenshots" />
        <div style="float:right;70%">
            <object id="USBCamera" classid="clsid:887FC3C3-A970-4A36-92EF-D4EB31541C40">
                <div class="alert alert-danger">视频控件载入失败!如未安装,请<a href="InstallationPackage/Setup1.msi">下载安装</a></div>
            </object>
        </div>
    </body>
    </html>
    View Code

    实现的效果图:

    结语


    VS使用的2015社区版,社区版。。。有点尴尬所以打包使用的 Visual Studio Installer

    一回生二回熟,第一次写这个满脸蒙蔽。

    不过这次稍微整理了一下,改动了一点,后续准备找个人脸识别的开源接口融合进来。

    下面给个下载地址,可以直接调试,需要注意使用IE,由于没有加证书,IE需要设置。

    工具>Internet选项
                     >安全>加入受信任的站点>  
                     >自定义级别>ActiveX控件和插件>ActivexX控件自动提示>启用
                                                                      >对未标记为可安全执行的脚本的ActivexX控件初始化并执行脚本>启用

    百度云盘链接:下载

  • 相关阅读:
    STM32 Systick定时器
    STM32F10X_CL
    公司版STM32工作原理
    STM32外部中断实验
    STM32的串口通信
    STM32调试过程中常见的问题及解决方法
    【转】 STM32 入门教程 系统时钟 SysTick
    STM32学习5 FLASH编程
    STM32学习笔记之Systick
    STM32 USART 串口简单使用
  • 原文地址:https://www.cnblogs.com/psjinfo/p/10436127.html
Copyright © 2020-2023  润新知