概述

之前有个需求,就是在web界面可以实现调用摄像头,用户把手机的个人二维码展示给摄像头,摄像头进行摄像识别用户。

其实本质就是保存图像二维码,在进行二维码识别。

下面来看看如何实现。

主要代码实现

1、初始化摄像头



    /// <summary>
    /// 初始化摄像头
    /// </summary>
    /// <param name="handle">控件的句柄</param>
    /// <param name="left">开始显示的左边距</param>
    /// <param name="top">开始显示的上边距</param>
    /// <param name="width">要显示的宽度</param>
    /// <param name="height">要显示的长度</param>
    public Pick(IntPtr handle, int left, int top, int width, int height)
    {
    mControlPtr = handle;
    mWidth = width;
    mHeight = height;
    mLeft = left;
    mTop = top;
    }
    [DllImport("avicap32.dll")]
    private static extern IntPtr capCreateCaptureWindowA(byte[] lpszWindowName, int dwStyle, int x, int y, int nWidth, int nHeight, IntPtr hWndParent, int nID);

    [DllImport("avicap32.dll")]
    private static extern int capGetVideoFormat(IntPtr hWnd, IntPtr psVideoFormat, int wSize);
    [DllImport("User32.dll")]
    private static extern bool SendMessage(IntPtr hWnd, int wMsg, int wParam, long lParam);

    2、开始显示图像


       /// <summary>
      /// 开始显示图像
      /// </summary>
      public void Start()
      {
      if (bStat)
      return;

      bStat = true;
      byte[] lpszName = new byte[100];

      hWndC = capCreateCaptureWindowA(lpszName, WS_CHILD | WS_VISIBLE, mLeft, mTop, mWidth, mHeight, mControlPtr, 0);

      if (hWndC.ToInt32() != 0)
      {
      SendMessage(hWndC, WM_CAP_SET_CALLBACK_VIDEOSTREAM, 0, 0);
      SendMessage(hWndC, WM_CAP_SET_CALLBACK_ERROR, 0, 0);
      SendMessage(hWndC, WM_CAP_SET_CALLBACK_STATUSA, 0, 0);
      SendMessage(hWndC, WM_CAP_DRIVER_CONNECT, 0, 0);
      SendMessage(hWndC, WM_CAP_SET_SCALE, 1, 0);
      SendMessage(hWndC, WM_CAP_SET_PREVIEWRATE, 66, 0);
      SendMessage(hWndC, WM_CAP_SET_OVERLAY, 1, 0);
      SendMessage(hWndC, WM_CAP_SET_PREVIEW, 1, 0);
      }

      return;

      }

      3、停止显示


          /// <summary>
        /// 停止显示



        /// </summary>
        public void Stop()
        {
        SendMessage(hWndC, WM_CAP_DRIVER_DISCONNECT, 0, 0);
        bStat = false;
        }

        4、抓图



          /// <summary>
          /// 抓图
          /// </summary>
          /// <param name="path">要保存bmp文件的路径</param>
          public void GrabImage(string path)
          {

          IntPtr hBmp = Marshal.StringToHGlobalAnsi(path);
          SendMessage(hWndC, WM_CAP_SAVEDIB, 0, hBmp.ToInt64());

          }

          /// <summary>
          /// 录像
          /// </summary>
          /// <param name="path">要保存avi文件的路径</param>
          public void Kinescope(string path)
          {
          IntPtr hBmp = Marshal.StringToHGlobalAnsi(path);
          SendMessage(hWndC, WM_CAP_FILE_SET_CAPTURE_FILEA, 0, hBmp.ToInt64());
          SendMessage(hWndC, WM_CAP_SEQUENCE, 0, 0);
          }

          /// <summary>
          /// 停止录像
          /// </summary>
          public void StopKinescope()
          {
          SendMessage(hWndC, WM_CAP_STOP, 0, 0);
          }

          完整代码


            using System;
            using System.Collections;
            using System.Configuration;
            using System.Data;
            using System.Linq;
            using System.Web;
            using System.Web.Security;
            using System.Web.UI;
            using System.Web.UI.HtmlControls;
            using System.Web.UI.WebControls;
            using System.Web.UI.WebControls.WebParts;
            using System.Xml.Linq;
            using System.Windows.Forms;

            using System.Runtime.InteropServices;

            using com.google.zxing.qrcode.decoder;
            using com.google.zxing.client;
            using com.google.zxing.common;

            using System.Threading;

            public partial class Decode : System.Web.UI.Page
            {
            // public delegate void SaveImg(Pick Pick1);
            /// <summary>
            /// 一个控制摄像头的类
            /// </summary>
            public class Pick
            {
            private const int WM_USER = 0x400;
            private const int WS_CHILD = 0x40000000;
            private const int WS_VISIBLE = 0x10000000;
            private const int WM_CAP_START = WM_USER;
            private const int WM_CAP_STOP = WM_CAP_START + 68;
            private const int WM_CAP_DRIVER_CONNECT = WM_CAP_START + 10;
            private const int WM_CAP_DRIVER_DISCONNECT = WM_CAP_START + 11;
            private const int WM_CAP_SAVEDIB = WM_CAP_START + 25;
            private const int WM_CAP_GRAB_FRAME = WM_CAP_START + 60;
            private const int WM_CAP_SEQUENCE = WM_CAP_START + 62;
            private const int WM_CAP_FILE_SET_CAPTURE_FILEA = WM_CAP_START + 20;
            private const int WM_CAP_SEQUENCE_NOFILE = WM_CAP_START + 63;
            private const int WM_CAP_SET_OVERLAY = WM_CAP_START + 51;
            private const int WM_CAP_SET_PREVIEW = WM_CAP_START + 50;
            private const int WM_CAP_SET_CALLBACK_VIDEOSTREAM = WM_CAP_START + 6;
            private const int WM_CAP_SET_CALLBACK_ERROR = WM_CAP_START + 2;
            private const int WM_CAP_SET_CALLBACK_STATUSA = WM_CAP_START + 3;
            private const int WM_CAP_SET_CALLBACK_FRAME = WM_CAP_START + 5;
            private const int WM_CAP_SET_SCALE = WM_CAP_START + 53;
            private const int WM_CAP_SET_PREVIEWRATE = WM_CAP_START + 52;
            private IntPtr hWndC;
            private bool bStat = false;
            private IntPtr mControlPtr;
            private int mWidth;
            private int mHeight;
            private int mLeft;
            private int mTop;



            /// <summary>
            /// 初始化摄像头
            /// </summary>
            /// <param name="handle">控件的句柄</param>
            /// <param name="left">开始显示的左边距</param>
            /// <param name="top">开始显示的上边距</param>
            /// <param name="width">要显示的宽度</param>
            /// <param name="height">要显示的长度</param>
            public Pick(IntPtr handle, int left, int top, int width, int height)
            {
            mControlPtr = handle;
            mWidth = width;
            mHeight = height;
            mLeft = left;
            mTop = top;
            }
            [DllImport("avicap32.dll")]
            private static extern IntPtr capCreateCaptureWindowA(byte[] lpszWindowName, int dwStyle, int x, int y, int nWidth, int nHeight, IntPtr hWndParent, int nID);

            [DllImport("avicap32.dll")]
            private static extern int capGetVideoFormat(IntPtr hWnd, IntPtr psVideoFormat, int wSize);
            [DllImport("User32.dll")]
            private static extern bool SendMessage(IntPtr hWnd, int wMsg, int wParam, long lParam);

            /// <summary>
            /// 开始显示图像
            /// </summary>
            public void Start()
            {
            if (bStat)
            return;

            bStat = true;
            byte[] lpszName = new byte[100];

            hWndC = capCreateCaptureWindowA(lpszName, WS_CHILD | WS_VISIBLE, mLeft, mTop, mWidth, mHeight, mControlPtr, 0);

            if (hWndC.ToInt32() != 0)
            {
            SendMessage(hWndC, WM_CAP_SET_CALLBACK_VIDEOSTREAM, 0, 0);
            SendMessage(hWndC, WM_CAP_SET_CALLBACK_ERROR, 0, 0);
            SendMessage(hWndC, WM_CAP_SET_CALLBACK_STATUSA, 0, 0);
            SendMessage(hWndC, WM_CAP_DRIVER_CONNECT, 0, 0);
            SendMessage(hWndC, WM_CAP_SET_SCALE, 1, 0);
            SendMessage(hWndC, WM_CAP_SET_PREVIEWRATE, 66, 0);
            SendMessage(hWndC, WM_CAP_SET_OVERLAY, 1, 0);
            SendMessage(hWndC, WM_CAP_SET_PREVIEW, 1, 0);
            }

            return;

            }

            /// <summary>
            /// 停止显示



            /// </summary>
            public void Stop()
            {
            SendMessage(hWndC, WM_CAP_DRIVER_DISCONNECT, 0, 0);
            bStat = false;
            }
            /// <summary>
            /// 抓图
            /// </summary>
            /// <param name="path">要保存bmp文件的路径</param>
            public void GrabImage(string path)
            {

            IntPtr hBmp = Marshal.StringToHGlobalAnsi(path);
            SendMessage(hWndC, WM_CAP_SAVEDIB, 0, hBmp.ToInt64());

            }

            /// <summary>
            /// 录像
            /// </summary>
            /// <param name="path">要保存avi文件的路径</param>
            public void Kinescope(string path)
            {
            IntPtr hBmp = Marshal.StringToHGlobalAnsi(path);
            SendMessage(hWndC, WM_CAP_FILE_SET_CAPTURE_FILEA, 0, hBmp.ToInt64());
            SendMessage(hWndC, WM_CAP_SEQUENCE, 0, 0);
            }

            /// <summary>
            /// 停止录像
            /// </summary>
            public void StopKinescope()
            {
            SendMessage(hWndC, WM_CAP_STOP, 0, 0);
            }

            }


            protected void Page_Load(object sender, EventArgs e)
            {

            }
            //void DoInit()
            //{
            // System.Windows.Forms.Form frm = new Form();
            // frm.Height = 300;
            // frm.Width = 300;
            // System.Windows.Forms.PictureBox Panel = new System.Windows.Forms.PictureBox();
            // Panel.Height = 300;
            // Panel.Width = 300;
            // Panel.Visible = true;
            // Panel.BackgroundImageLayout = ImageLayout.None;
            // frm.Controls.Add(Panel);
            // frm.TopMost = true;
            // Pick p = new Pick(Panel.Handle, 0, 0, 300, 300);
            // p.Start();
            // frm.Show();
            // p.Kinescope(Server.MapPath("img\\Decode2.avi"));
            // p.GrabImage(Server.MapPath("img\\Decode1.bmp"));
            // p.Stop();
            // frm.Close();
            // frm.Dispose();
            //}
              
            private void getQrcode()
            {
            try
            {

            //ThreadStart worker = new ThreadStart(DoInit);
            //Thread th = new Thread(worker);
            //th.IsBackground = true;
            //th.Start();
            System.Windows.Forms.Form frm = new Form();
            frm.Height = 300;
            frm.Width = 300;
            System.Windows.Forms.PictureBox Panel = new System.Windows.Forms.PictureBox();
            Panel.Height = 300;
            Panel.Width = 300;
            Panel.Visible = true;
            Panel.BackgroundImageLayout = ImageLayout.None;
            frm.Controls.Add(Panel);
            frm.TopMost = true;
            Pick p = new Pick(Panel.Handle, 0, 0, 300, 300);
            p.Start();
            int i = 1;
            while (i <= 1)
            {
            p.GrabImage(Server.MapPath("img\\Decode.bmp"));
            p.Kinescope(Server.MapPath("img\\Video.avi"));
            i++;
            }
            p.Stop();
            frm.Close();
            frm.Dispose();
            try
            {
            com.google.zxing.qrcode.QRCodeReader d = new com.google.zxing.qrcode.QRCodeReader();
            RGBLuminanceSource rg = new RGBLuminanceSource(new System.Drawing.Bitmap(Server.MapPath("img\\Decode.bmp")), new System.Drawing.Bitmap(Server.MapPath("img\\Decode.bmp")).Width, new System.Drawing.Bitmap(Server.MapPath("img\\Decode.bmp")).Height);
            com.google.zxing.LuminanceSource ls = rg;
            HybridBinarizer hb = new HybridBinarizer(ls);
            com.google.zxing.BinaryBitmap bm = new com.google.zxing.BinaryBitmap(hb);
            com.google.zxing.Result r = d.decode(bm);
            TextBox1.Text = r.Text;


            }
            catch (Exception ex)
            {

            TextBox1.Text = "";
            //MessageBox.Show(ex.Message+"111");

            throw new Exception(ex.Message);
            }


            }
            catch (Exception ee)
            {
            ee.ToString();
            }
            }
            protected void Timer1_Tick(object sender, EventArgs e)
            {
            //getQrcode();
            }
            protected void Button1_Click(object sender, EventArgs e)
            {
            getQrcode();
            }

            }