c# winform调用摄像头识别二维码

/ C# / 没有评论 / 1807浏览

c# winform调用摄像头识别二维码

首先我们需要引用两个第三方组件:AForge和zxing。Aforge是摄像头操作组件,zxing是二维码识别组件。都是开源项目。避免重复造轮子。

其实一些操作代码我也是参照别人的,若侵犯您的版权,请和我联系。此博客仅供技术交流。下载和用法大家可以自行搜索下。

首先获取所有可用的摄像头设备,并加入到comboBox1中

private void getCamList(){
    try {
        //AForge.Video.DirectShow.FilterInfoCollection 设备枚举类
        videoDevices = new FilterInfoCollection(FilterCategory.VideoInputDevice);
        //清空列表框
        comboBox1.Items.Clear();
        if (videoDevices.Count == 0)
            throw new ApplicationException();
        //全局变量,标示设备摄像头设备是否存在
        DeviceExist = true;
        //加入设备
        foreach (FilterInfo device in videoDevices) {
            comboBox1.Items.Add(device.Name);
        }
        //默认选择第一项
        comboBox1.SelectedIndex = 0;
    }
    catch (ApplicationException) {
        DeviceExist = false;
        comboBox1.Items.Add("未找到可用设备");
    }
}

以下是启动按钮事件代码和一些其他代码。

private void start_Click(object sender, EventArgs e) {
    if (start.Text == "Start") {
        if (DeviceExist) {
            //视频捕获设备
            videoSource = new VideoCaptureDevice(videoDevices[comboBox1.SelectedIndex].MonikerString);
            //捕获到新画面时触发
            videoSource.NewFrame += new NewFrameEventHandler(video_NewFrame);
            //先关一下,下面再打开。避免重复打开的错误
            CloseVideoSource();
            //设置画面大小
            videoSource.DesiredFrameSize = new Size(160, 120);
            //启动视频组件
            videoSource.Start();
            start.Text = "Stop";
            //启动定时解析二维码
            timer1.Enabled = true;
            //启动绘制视频中的扫描线
            timer2.Enabled = true;
        }
    }
    else {
        if (videoSource.IsRunning) {
            timer2.Enabled = false;
            timer1.Enabled = false;
            CloseVideoSource();
            start.Text = "Start";
        }
    }
}
/// <summary>
/// 全局变量,记录扫描线距离顶端的距离
/// </summary>
int top = 0;
/// <summary>
/// 全局变量,保存每一次捕获的图像
/// </summary>
Bitmap img = null;

private void video_NewFrame(object sender, NewFrameEventArgs eventArgs){
    img = (Bitmap)eventArgs.Frame.Clone();
}

//close the device safely
private void CloseVideoSource() {
    if (!(videoSource == null)) {
        if (videoSource.IsRunning) {
            videoSource.SignalToStop();
            videoSource = null;
        }
    }
}

下面的代码是在画面中绘制扫描线。

private void timer2_Tick(object sender, EventArgs e){
    if (img == null) {
        return;
    }
    Bitmap img2 = (Bitmap)img.Clone();
    Pen p = new Pen(Color.Red);
    Graphics g = Graphics.FromImage(img2);
    Point p1 = new Point(0, top);
    Point p2 = new Point(pictureBox1.Width, top);
    g.DrawLine(p, p1, p2);
    g.Dispose();
    top += 2;
    top = top % pictureBox1.Height;
    pictureBox1.Image = img2;
}

下面是解码二维码:

private void timer1_Tick(object sender, EventArgs e) {
    if (img == null) {
        return;
    }
    #region 将图片转换成byte数组
    MemoryStream ms = new MemoryStream();
    img.Save(ms, System.Drawing.Imaging.ImageFormat.Bmp);
    byte[] bt = ms.GetBuffer();
    ms.Close(); 
    #endregion
    
    LuminanceSource source = new RGBLuminanceSource(bt, img.Width, img.Height);
    BinaryBitmap bitmap = new BinaryBitmap(new ZXing.Common.HybridBinarizer(source));
    Result result;
    try {
        //开始解码
        result = new MultiFormatReader().decode(bitmap);
    }
    catch (ReaderException re){
        return;
    }
    if (result != null) {
        textBox1.Text = result.Text;
    }
}

用了第三方组件,开发难度真是直线下降。内部具体怎么解码的,真的是一点不知道。还望有经验的高手不吝赐教。