C#调用摄像头(AForge)实现扫描条码解析(Zxing)功能
网上找了很多代码,都比较零散,以下代码纯自己手写,经过测试。下面有链接,下载后可以直接使用。
介绍:
自动识别:点击Start按钮会调用PC摄像头,代码内置Timer,会每100毫秒识别一下当前摄像头图像中的图像,并调用条码识别功能判定是否有条码,如果有的话就直接停止,否则继循环识别。
截图:也可以手动截图,截图后存在运行目录,请自行查找。
补充:识别通过率取决于摄像头的像素,我的笔记本比较烂,所以通过率不高。高像素的摄像头通过率很高。
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms; using AForge;
using AForge.Controls;
using AForge.Imaging;
using AForge.Video;
using AForge.Video.DirectShow;
using System.Drawing.Imaging; using ZXing;
using ZXing.Common;
using ZXing.QrCode;
using ZXing.QrCode.Internal; /// <summary>
/// 20190515 by hanfre
/// 关于原理:
/// C#调用摄像头+存储图片+Zxing/Zbar图片识别.当开启摄像头的时候利用Timer对当前图片进行解析处理,识别条码;
/// 关于条码解析:
/// 这个DEMO含两个条码解析组件,分别是Zxing和Zbar,使用哪个可以自己切换;
/// 关于作者:
/// Hanfre
/// </summary>
namespace WindowsFormsApplication1
{
/// <summary>
/// 20190515 by hanfre
/// </summary>
public partial class Form1 : Form
{
#region 全局变量定义
FilterInfoCollection videoDevices;
VideoCaptureDevice videoSource;
public int selectedDeviceIndex = 0;
#endregion public Form1()
{
InitializeComponent(); InitializeView();
} #region 事件
/// <summary>
/// 启动
/// 20190515 by hanfre
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void BtnStart_Click(object sender, EventArgs e)
{
PbxScanner.Image = null; videoDevices = new FilterInfoCollection(FilterCategory.VideoInputDevice);
selectedDeviceIndex = 0;
videoSource = new VideoCaptureDevice(videoDevices[selectedDeviceIndex].MonikerString);//连接摄像头 videoSource.NewFrame += new NewFrameEventHandler(VspContainerClone);//捕获画面事件 videoSource.VideoResolution = videoSource.VideoCapabilities[selectedDeviceIndex];
VspContainer.VideoSource = videoSource;
VspContainer.Start(); StartVideoSource();
} /// <summary>
/// 停止
/// 20190515 by hanfre
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void BtnStop_Click(object sender, EventArgs e)
{
CloseVideoSource();
} /// <summary>
/// 保存
/// 20190515 by hanfre
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void BtnScanner_Click(object sender, EventArgs e)
{
if (videoSource == null)
return;
Bitmap bitmap = VspContainer.GetCurrentVideoFrame();
string fileName = DateTime.Now.ToString("yyyy-MM-dd-HH-mm-ss-ff") + ".jpg"; bitmap.Save(Application.StartupPath + "\\" + fileName, ImageFormat.Jpeg);
bitmap.Dispose();
} /// <summary>
/// 同步事件
/// 20190515 by hanfre
/// </summary>
/// <param name="sender"></param>
/// <param name="eventArgs"></param>
private void VspContainerClone(object sender, NewFrameEventArgs eventArgs)
{
PbxScanner.Image = (Bitmap)eventArgs.Frame.Clone();
} /// <summary>
/// Timer定时器
/// 20190515 by hanfre
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void TmScanner_Tick(object sender, EventArgs e)
{
if (PbxScanner.Image != null)
{
TmScanner.Enabled = false;
Bitmap img = (Bitmap)PbxScanner.Image.Clone();
if (DecodeByZxing(img))
///if (DecodeByZbar(img))
{
CloseVideoSource();
}
else
{
TmScanner.Enabled = true;
}
}
}
#endregion #region 方法
/// <summary>
/// 初始化
/// 20190515 by hanfre
/// </summary>
private void InitializeView()
{
BtnScanner.Enabled = false;
BtnStop.Enabled = false;
} /// <summary>
/// 启动
/// 20190515 by hanfre
/// </summary>
private void StartVideoSource()
{
TmScanner.Enabled = true;
BtnStart.Enabled = false;
BtnStop.Enabled = true;
BtnScanner.Enabled = true;
}
/// <summary>
/// 关闭
/// 20190515 by hanfre
/// </summary>
private void CloseVideoSource()
{
if (!(videoSource == null))
{
if (videoSource.IsRunning)
{
videoSource.SignalToStop();
videoSource = null;
}
} VspContainer.SignalToStop();
//videoSourcePlayer1.Stop();
//videoSourcePlayer1.Dispose(); TmScanner.Enabled = false;
BtnScanner.Enabled = false;
BtnStart.Enabled = true;
BtnStop.Enabled = false;
}
#endregion #region 方法/Zxing&Zbar
/// <summary>
/// 解码
/// 20190515 by hanfre
/// </summary>
/// <param name="b"></param>
/// <returns></returns>
private bool DecodeByZxing(Bitmap b)
{
try
{
BarcodeReader reader = new BarcodeReader();
reader.AutoRotate = true;
Result result = reader.Decode(b); TxtScannerCode.Text = result.Text;
}
catch (Exception e)
{
System.Console.WriteLine(e.Message);
TxtScannerCode.Text = "";
return false;
} return true;
} private bool DecodeByZbar(Bitmap b)
{
DateTime now = DateTime.Now; Bitmap pImg = ZbarMakeGrayscale3(b);
using (ZBar.ImageScanner scanner = new ZBar.ImageScanner())
{
scanner.SetConfiguration(ZBar.SymbolType.None, ZBar.Config.Enable, 0);
scanner.SetConfiguration(ZBar.SymbolType.CODE39, ZBar.Config.Enable, 1);
scanner.SetConfiguration(ZBar.SymbolType.CODE128, ZBar.Config.Enable, 1); List<ZBar.Symbol> symbols = new List<ZBar.Symbol>();
symbols = scanner.Scan((System.Drawing.Image)pImg); if (symbols != null && symbols.Count > 0)
{
string result = string.Empty;
symbols.ForEach(s => result += "条码内容:" + s.Data + " 条码质量:" + s.Quality + Environment.NewLine);
MessageBox.Show(result);
return true;
}
else
{
return false;
}
}
} /// <summary>
/// 处理图片灰度
/// </summary>
/// <param name="original"></param>
/// <returns></returns>
public static Bitmap ZbarMakeGrayscale3(Bitmap original)
{
//create a blank bitmap the same size as original
Bitmap newBitmap = new Bitmap(original.Width, original.Height); //get a graphics object from the new image
Graphics g = Graphics.FromImage(newBitmap); //create the grayscale ColorMatrix
System.Drawing.Imaging.ColorMatrix colorMatrix = new System.Drawing.Imaging.ColorMatrix(
new float[][]
{
new float[] {.3f, .3f, .3f, 0, 0},
new float[] {.59f, .59f, .59f, 0, 0},
new float[] {.11f, .11f, .11f, 0, 0},
new float[] {0, 0, 0, 1, 0},
new float[] {0, 0, 0, 0, 1}
}); //create some image attributes
ImageAttributes attributes = new ImageAttributes(); //set the color matrix attribute
attributes.SetColorMatrix(colorMatrix); //draw the original image on the new image
//using the grayscale color matrix
g.DrawImage(original, new Rectangle(0, 0, original.Width, original.Height),
0, 0, original.Width, original.Height, GraphicsUnit.Pixel, attributes); //dispose the Graphics object
g.Dispose();
return newBitmap;
}
#endregion
}
}
下载地址我已上传到CSDN,可以访问 https://download.csdn.net/download/fandoc/11180026 下载
C#调用摄像头(AForge)实现扫描条码解析(Zxing)功能的更多相关文章
- Smobiler实现扫描条码和拍照功能(开发日志八)
一.调用摄像头进行扫描 barcode000~2.jpg (198.62 KB, 下载次数: 5) 下载附件 2015-12-23 17:41 上传 具体步骤: 1. 加入TextBox控件:加入B ...
- 使用vue做移动app时,调用摄像头扫描二维码
现在前端技术发展飞快,前端都能做app了,那么项目中,也会遇到调用安卓手机基层的一些功能,比如调用摄像头,完成扫描二维码功能 下面我就为大家讲解一下,我在项目中调用这功能的过程. 首先我们需要一个中间 ...
- SNF开发平台WinForm-平板拍照及扫描二维码功能
在我们做项目的时候,经常会有移动平板处理检验,审核等,方便移动办公.这时就需要在现场拍照上传问题,把当场问题进行上传,也有已经拍完照的图片或加工过的图片进行上传.还有在车间现场一体机,工控机 这种产物 ...
- C# winfrom调用摄像头扫描二维码(完整版)
前段时间看到一篇博客,是这个功能的,参考了那篇博客写了这个功能玩一玩,没有做商业用途.发现他的代码给的有些描述不清晰的,我就自己整理一下发出来记录一下. 参考博客链接:https://www.cnbl ...
- C# - VS2019调用AForge库实现调用摄像头拍照功能
前言 作为一名资深Delphi7程序员,想要实现摄像头扫描一维码/二维码功能,发现所有免费的第三方库都没有简便的实现办法,通用的OpenCV或者ZXing库基本上只支持XE以上的版本,而且一维码的识别 ...
- Emgucv(一)Aforge切换摄像头并调用摄像头属性
一.新建一个Windows窗体应用程序,在Form1窗体上添加一个PictureBox控件.一个ComboBox控件,命名为PictureBox1.cbCapture,还有两个Button控件,Tex ...
- AForge调用摄像头拍照时设置分辨率
简单记录下AForge2.2.5.0版本调用摄像头拍照时设置分辨率的方法. FilterInfo info = _videoDevices[0];//获取第一个摄像头 _cameraDevice = ...
- Android入门(十六)调用摄像头相册
原文链接:http://www.orlion.ga/665/ 一.调用摄像头 创建一个项目ChoosePicDemo,修改activity_main.xml: <LinearLayout xml ...
- android: 调用摄像头拍照
很多应用程序都可能会使用到调用摄像头拍照的功能,比如说程序里需要上传一张图片 作为用户的头像,这时打开摄像头拍张照是最简单快捷的.下面就让我们通过一个例子来学 习一下,如何才能在应用程序里调用手机的摄 ...
随机推荐
- 【python+selenium学习】常见错误: 'gbk' codec can't decode byte 0xb0 in position 30
最近编写的自动化脚本,数据部分使用到了从配置文件中取,即自定义config.ini,但是在读取配置文件的时候却报错了'gbk' codec can't decode byte 0xb0 in posi ...
- tcp 3次握手和4次挥手
TCP标志位 (参考来源:https://blog.csdn.net/ltstud/article/details/73995933和 https://blog.csdn.net/weixin_308 ...
- 面向对象(五)--isinstance与issubclass方法、反射、内置方法(部分)、异常处理
一.isinstance与issubclass方法 1.isinstance是用来判断对象是否是某个类 isinstance(obj,class) 2.issubclass是用来判断一个类是否为另一个 ...
- 第一部分day5 文件操作
#-----文件操作----- 文件操作模式 1."r" 读 2."w" 清空写入 3."a" 追加 4."r+" 读写 ...
- Nginx Rewrite相关功能-防盗链
Nginx Rewrite相关功能-防盗链 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任.
- 浅析Volatile关键字
浅析Volatile关键字 在java中线程并发中,线程之间通信方式分为两种:共享内存和消息传递.共享内存指的是多个线程之间共享内存的属性状态:消息传递指的是线程之间发送信息来通信.在介绍volati ...
- asp.net Server.Transfer
页面跳转传参. 如果不是通用的跳转可以通过,在原始页面定义对象保存数据 跳转的目标页面可以: SourcePage page=(SourcePage)Context.Handler; //获取源页面的 ...
- 使用WIFI网卡 dhcp动态获取IP
前面几篇博客中,wifi网卡的ip都是手工设置的,本篇博客将来移植dhcp,使得wifi网卡可以动态的获取ip.路由等信息. 那我们去哪里下载dhcp源码呢?在pc机上执行dh +tab键,看一下有哪 ...
- mybatis框架,使用foreach实现复杂结果的查询--循环List集合方式
需求,根据用户角色列表 查询用户列表信息 之前我们传入的参数是Array,一个数组的形式,现在我们传入的是一个List集合,其他条件没有变化. /** * 需求:传入指定的用户角色,用户角色有1-n ...
- python基础之一:input、if、while