当前位置 博文首页 > 随风去远方:winform 调用摄像头扫码识别二维码

    随风去远方:winform 调用摄像头扫码识别二维码

    作者:随风去远方 时间:2021-04-28 11:53

    因为公司业务需求,需要在Windows系统下调用摄像头识别二维码需求,就有了这个功能。

    我根据网上网友提供的一些资料,自己整合应用到项目中,效果还不错(就是感觉像素不是太好)

    现在将调用摄像头+识别二维码这两个功能单独出来写到这里,供大家讨论和参考。

    有什么不足或者问题大家可以提出来,共同改进共同进步

     

    创建一个空的winform项目解决方案,我起名叫他:ScanQRCode

    将Form1作为主窗体,设置相关属性:

      StartPosition:CenterScreen (窗体居中)

      添加一个居中标题:

     1   private void LoadTitleCenterData()
     2  {
     3             string titleMsg ="二维码识别主界面";
     4             Graphics g = this.CreateGraphics();
     5             Double startingPoint = (this.Width / 2) - (g.MeasureString(titleMsg, this.Font).Width / 2);
     6             Double widthOfASpace = g.MeasureString(" ", this.Font).Width;
     7             String tmp = " ";
     8             Double tmpWidth = 0;
     9 
    10             while ((tmpWidth + widthOfASpace) < startingPoint)
    11             {
    12                 tmp += " ";
    13                 tmpWidth += widthOfASpace;
    14             }
    15             this.Text = tmp + titleMsg;
    16  }

    最大最小化禁用:

     

    1  public Form1()
    2 {
    3    this.MinimizeBox = false; 
    4    this.MaximizeBox = false; 
    5    InitializeComponent();
    6    LoadTitleCenterData();
    7 }

     

     

     

    Form1中添加一个TableLayoutPanel,三行三列,比例按照百分比:10%,80%,10%这样

    在TableLayoutPanel的80%中再添加一个TableLayoutPanel,还是行比例:20%,80%这样(二八定律)

    在TableLayoutPanel中添加Panel,在其中手动在添加几个按钮和label

    最终界面这样(能看就行)

    添加一个二维码识别界面CameraQR:

    使用Nuget添加引用,搜索AForge,将如下程序包引入:

     

    添加一个识别二维码的窗体,命名名称为:CameraQR

    将VideoSourcePlayer添加到窗体中,Fill显示:

    窗体中定义几个私有变量:

    1 private AForge.Video.DirectShow.FilterInfoCollection _videoDevices;//摄像设备
    2 System.Timers.Timer timer;//定时器
    3 CameraHelper _cameraHelper = new CameraHelper();//视屏设备操作类

     

    窗体Load事件中获取拍照设备列表,并将第一个设备作为摄像设备(如有前后两个或多个摄像头,自己去改一下代码,设置成可以选择的,在CameraHelper中的CreateFilterInfoCollection()中)

     1  private void CameraQR_Load(object sender, EventArgs e)
     2 {
     3             // 获取视频输入设备
     4             _videoDevices = _cameraHelper.CreateFilterInfoCollection();//获取拍照设备列表
     5             if (_videoDevices.Count == 0)
     6             {
     7                 MessageBox.Show("无设备");
     8                 this.Dispose();
     9                 this.Close();
    10                 return;
    11             }
    12             resultStr = "";//二维码识别字符串清空
    13             _cameraHelper.ConnectDevice(videoSourcePlayer1);//连接打开设备
    14 }

    组件初始化完成之后,添加一个定时任务,用来阶段性识别摄像设备中的图片资源,我写的是每200毫秒去识别一次,如果图片中有二维码,就识别二维码;识别成功之后,关闭窗体,将识别结果返回给上一个界面,此处需要一个有识别二维码程序包

    使用Nuget添加引用,搜索ZXing,将如下程序包引入:

     

     

     代码如下(核心代码基本就这些)

    public CameraQR()
    {
       this.MinimizeBox = false;
       this.MaximizeBox = false;
       InitializeComponent();
       LoadTitleCenterData();
       CheckForIllegalCrossThreadCalls = false;//多线程中访问窗体控件资源不会异常
       AddTimer();//定时识别图片
    }
    
    private void AddTimer()
    {
      timer = new System.Timers.Timer();
      timer.Enabled = true;
      timer.Interval = 200;
      timer.Start();
      timer.Elapsed += new ElapsedEventHandler(PicToQRCode);
    }
    

    private void PicToQRCode(object sender, ElapsedEventArgs e) { if (_cameraHelper.img == null) return; BinaryBitmap bitmap = null; try { MemoryStream ms = new MemoryStream(); _cameraHelper.img.Save(ms, System.Drawing.Imaging.ImageFormat.Bmp); byte[] bt = ms.GetBuffer(); ms.Close(); LuminanceSource source = new RGBLuminanceSource(bt, _cameraHelper.img.Width, _cameraHelper.img.Height); bitmap = new BinaryBitmap(new ZXing.Common.HybridBinarizer(source)); } catch (Exception ex) { return; } Result result=null; try { //开始解码 result = new MultiFormatReader().decode(bitmap); } catch (ReaderException ex) { resultStr = ex.ToString(); } if (result != null) { resultStr = result.Text; this.DialogResult = DialogResult.OK; this.Close(); }
    }

    窗体关闭时,记得释放定时器 关闭摄像头(不然异常满天飞)

    private void CameraQR_FormClosing(object sender, FormClosingEventArgs e)
    {
          if (timer != null)
          {
              timer.Dispose();
          }
           _cameraHelper.CloseDevice();
     }

    CameraHelper类:

     1 public class CameraHelper
     2 {
     3     public FilterInfoCollection _videoDevices;//本机摄像硬件设备列表
     4     public VideoSourcePlayer _videoSourcePlayer;//视频画布
     5     public Bitmap img = null;//全局变量,保存每一次捕获的图像
     6     public System.Drawing.Image CaptureImage(VideoSourcePlayer sourcePlayer = null)
     7     {
     8 
     9         if (sourcePlayer == null || sourcePlayer.VideoSource == null)
    10         {
    11             if (_videoSourcePlayer == null)
    12                 return null;
    13             else
    14             {
    15                 sourcePlayer = _videoSourcePlayer;
    16             }
    17         }
    18 
    19         try
    20         {
    21             if (sourcePlayer.IsRunning)
    22             {
    23                 System.Drawing.Image bitmap = sourcePlayer.GetCurrentVideoFrame();
    24                 return bitmap;
    25             }
    26             return null;
    27 
    28         }
    29         catch (Exception ex)
    30         {
    31             return null;
    32         }
    33     }
    34 
    35     public FilterInfoCollection CreateFilterInfoCollection()
    36     {
    37         if (_videoDevices != null)
    38             return _videoDevices;
    39         _videoDevices = new FilterInfoCollection(FilterCategory.VideoInputDevice);
    40         return _videoDevices;
    41     }
    42 
    43     public VideoCaptureDevice ConnectDevice(VideoSourcePlayer videoSourcePlayer, FilterInfo filterInfo = null)
    44     {
    45         VideoCaptureDevice videoSource = new VideoCaptureDevice();
    46         if (filterInfo == null)
    47         {
    48             videoSource = new VideoCaptureDevice(_videoDevices[_videoDevices.Count - 1].MonikerString);
    49         }
    50         else
    51         {
    52             videoSource = new VideoCaptureDevice(filterInfo.MonikerString);
    53         }
    54 
    55         videoSource.NewFrame += new NewFrameEventHandler(video_NewFrame);
    56         videoSourcePlayer.VideoSource = videoSource;
    57         videoSourcePlayer.Start();
    58         _videoSourcePlayer = videoSourcePlayer;
    59         return videoSource;
    60     }
    61 
    62     private void video_NewFrame(object sender, NewFrameEventArgs eventArgs)
    63     {
    64         img = (Bitmap)eventArgs.Frame.Clone();
    65     }
    66 
    67     public void CloseDevice(VideoSourcePlayer videoSourcePlayer = null)
    68     {
    69         if (videoSourcePlayer == null)
    70         {
    71             if (_videoSourcePlayer == null)
    72                 return;
    73             _videoSourcePlayer.SignalToStop();
    74         }
    75         else
    76         {
    77             videoSourcePlayer.SignalToStop();
    78         }
    79     }
    80 }

    我用的测试二维码是:

    最终的别结果为:

     

     

     代码:https://github.com/Binzm/ScanQRCode.git

    bk