C# 为什么这不起作用?ZXing,位图,图像源
我正试图在WPF中从摄像头扫描二维码(使用Zxing-Zxing的解码方法仅适用于位图)。以下是我所拥有的:C# 为什么这不起作用?ZXing,位图,图像源,c#,wpf,bitmap,zxing,imagesource,C#,Wpf,Bitmap,Zxing,Imagesource,我正试图在WPF中从摄像头扫描二维码(使用Zxing-Zxing的解码方法仅适用于位图)。以下是我所拥有的: void Window2_Loaded(object sender, RoutedEventArgs e) { System.Windows.Threading.DispatcherTimer dispatcherTimer = new System.Windows.Threading.DispatcherTimer(); dispatcherTi
void Window2_Loaded(object sender, RoutedEventArgs e)
{
System.Windows.Threading.DispatcherTimer dispatcherTimer = new System.Windows.Threading.DispatcherTimer();
dispatcherTimer.Tick += new EventHandler(dispatcherTimer_Tick);
dispatcherTimer.Interval = new TimeSpan(0, 5, 0);
LoaclWebCamsCollection = new FilterInfoCollection(FilterCategory.VideoInputDevice);
LocalWebCam = new VideoCaptureDevice(LoaclWebCamsCollection[1].MonikerString);
LocalWebCam.NewFrame += new NewFrameEventHandler(Cam_NewFrame);
LocalWebCam.Start();
dispatcherTimer.Start();
}
转换方法(位图源到位图)-从另一个线程获取:
Bitmap GetBitmap(BitmapSource source)
{
Bitmap bmp = new Bitmap(
source.PixelWidth,
source.PixelHeight,
System.Drawing.Imaging.PixelFormat.Format32bppPArgb);
BitmapData data = bmp.LockBits(
new System.Drawing.Rectangle(System.Drawing.Point.Empty, bmp.Size),
ImageLockMode.WriteOnly,
System.Drawing.Imaging.PixelFormat.Format32bppPArgb);
source.CopyPixels(
Int32Rect.Empty,
data.Scan0,
data.Height * data.Stride,
data.Stride);
bmp.UnlockBits(data);
return bmp;
}
以及定时器方法:
private void dispatcherTimer_Tick(object sender, EventArgs e)
{
BarcodeReader Reader = new BarcodeReader();
if (frameHolder.Source != null)
{
Result result = Reader.Decode(GetBitmap((BitmapSource)frameHolder.Source));
decoded = result.ToString().Trim();
hey.Text = decoded;
}
}
以及新的框架方法:
void Cam_NewFrame(object sender, NewFrameEventArgs eventArgs)
{
try
{
System.Drawing.Bitmap img = (Bitmap)eventArgs.Frame.Clone();
MemoryStream ms = new MemoryStream();
img.Save(ms, ImageFormat.Bmp);
ms.Seek(0, SeekOrigin.Begin);
BitmapImage bi = new BitmapImage();
bi.BeginInit();
bi.StreamSource = ms;
bi.EndInit();
bi.Freeze();
Dispatcher.BeginInvoke(new ThreadStart(delegate
{
frameHolder.Source = bi;
}));
}
catch (Exception ex)
{
}
}
frameHolder
是我的图像控件
我做错了什么?。我很确定他不能从
框架支架中取出位图
,但我不知道为什么 您需要将二维码设置为可能的格式,否则它不会搜索任何内容
下面的代码应该可以帮助您传递图像路径:
public static string Find(string fileName)
{
if (File.Exists(fileName)) {
using (var bitmap = (Bitmap)Image.FromFile(fileName))
{
return Decode(bitmap, false, new List<BarcodeFormat> {BarcodeFormat.QR_CODE});
}
}
return null;
}
公共静态字符串查找(字符串文件名)
{
if(File.Exists(fileName)){
使用(var bitmap=(bitmap)Image.FromFile(文件名))
{
返回解码(位图、假、新列表{BarcodeFormat.QR_CODE});
}
}
返回null;
}
并解码:
private static string Decode(Bitmap bitmap, bool tryMultipleBarcodes, IList<BarcodeFormat> possibleFormats)
{
BarcodeReader barcodeReader = new BarcodeReader();
var previousFormats = barcodeReader.Options.PossibleFormats;
if (possibleFormats != null)
barcodeReader.Options.PossibleFormats = possibleFormats;
barcodeReader.Options.TryHarder = true;
barcodeReader.TryInverted = true;
barcodeReader.AutoRotate = true;
var result = barcodeReader.Decode(bitmap);
if (result != null) {
return result.ToString();
} else {
return null;
}
}
私有静态字符串解码(位图、bool-trymultipleBarcode、IList可能格式)
{
条码阅读器条码阅读器=新条码阅读器();
var previousFormats=barcodeReader.Options.PossibleFormats;
if(可能格式!=null)
条形码阅读器.Options.PossibleFormats=PossibleFormats;
barcodeReader.Options.TryHarder=true;
barcodeReader.TryInverted=true;
barcodeReader.AutoRotate=true;
var结果=条形码阅读器.Decode(位图);
如果(结果!=null){
返回result.ToString();
}否则{
返回null;
}
}
您需要将二维码设置为可能的格式,否则它不会搜索任何内容
下面的代码应该可以帮助您传递图像路径:
public static string Find(string fileName)
{
if (File.Exists(fileName)) {
using (var bitmap = (Bitmap)Image.FromFile(fileName))
{
return Decode(bitmap, false, new List<BarcodeFormat> {BarcodeFormat.QR_CODE});
}
}
return null;
}
公共静态字符串查找(字符串文件名)
{
if(File.Exists(fileName)){
使用(var bitmap=(bitmap)Image.FromFile(文件名))
{
返回解码(位图、假、新列表{BarcodeFormat.QR_CODE});
}
}
返回null;
}
并解码:
private static string Decode(Bitmap bitmap, bool tryMultipleBarcodes, IList<BarcodeFormat> possibleFormats)
{
BarcodeReader barcodeReader = new BarcodeReader();
var previousFormats = barcodeReader.Options.PossibleFormats;
if (possibleFormats != null)
barcodeReader.Options.PossibleFormats = possibleFormats;
barcodeReader.Options.TryHarder = true;
barcodeReader.TryInverted = true;
barcodeReader.AutoRotate = true;
var result = barcodeReader.Decode(bitmap);
if (result != null) {
return result.ToString();
} else {
return null;
}
}
私有静态字符串解码(位图、bool-trymultipleBarcode、IList可能格式)
{
条码阅读器条码阅读器=新条码阅读器();
var previousFormats=barcodeReader.Options.PossibleFormats;
if(可能格式!=null)
条形码阅读器.Options.PossibleFormats=PossibleFormats;
barcodeReader.Options.TryHarder=true;
barcodeReader.TryInverted=true;
barcodeReader.AutoRotate=true;
var结果=条形码阅读器.Decode(位图);
如果(结果!=null){
返回result.ToString();
}否则{
返回null;
}
}
首先
你知道这个方法有效吗?您是否使用从原始Cam\u NewFrame
方法保存的位图对其进行了测试
为了你的理智,这是你应该做的第一件事。例如
void Cam_NewFrame(object sender, NewFrameEventArgs eventArgs)
{
...
img.Save("some path");
然后用它测试条形码阅读器
其次
为什么要麻烦地转换位图,然后再转换回来
克隆位图时只需复制一份即可。然后在计时器方法中使用该克隆(显然要确保线程安全并正确处理它们)
最后,请阅读条形码阅读器
上的文档,您显然缺少很多配置(根据Matt Beldons)答案首先
你知道这个方法有效吗?您是否使用从原始Cam\u NewFrame
方法保存的位图对其进行了测试
为了你的理智,这是你应该做的第一件事。例如
void Cam_NewFrame(object sender, NewFrameEventArgs eventArgs)
{
...
img.Save("some path");
然后用它测试条形码阅读器
其次
为什么要麻烦地转换位图,然后再转换回来
克隆位图时只需复制一份即可。然后在计时器方法中使用该克隆(显然要确保线程安全并正确处理它们)
最后,请阅读BarcodeReader
上的文档,您显然缺少很多配置(根据Matt Beldons)答案ZXing.Net提供了使用BitmapSource实例的BarcodeReader类的特殊版本。
通常,如果您通过nuget将ZXing.Net包添加到项目中,则应该有对ZXing.presentation.dll的引用。如果没有,请从二进制发行版手动添加它。
特殊条形码阅读器位于名称空间ZXing.Presentation中。
您的方法的以下修改版本应该可以工作:
private void dispatcherTimer_Tick(object sender, EventArgs e)
{
BarcodeReader Reader = new ZXing.Presentation.BarcodeReader();
if (frameHolder.Source != null)
{
Result result = Reader.Decode((BitmapSource)frameHolder.Source);
decoded = result?.Text;
hey.Text = decoded;
}
}
不要忘记检查“result==null”,如果没有找到条形码,就会出现这种情况
顺便说一下,忘记你的Dispatchermer解决方案,在Cam_NewFrame中完成所有工作
void Cam_NewFrame(object sender, NewFrameEventArgs eventArgs)
{
try
{
System.Drawing.Bitmap img = (Bitmap)eventArgs.Frame.Clone();
// TODO: add some kind of mutex or similar here so that you don't start a new Decode before the previous one is finished
Dispatcher.BeginInvoke(new ThreadStart(delegate
{
// use the original BarcodeReader because we are using the bitmap instance directly
BarcodeReader Reader = new ZXing.BarcodeReader();
Result result = Reader.Decode(img);
decoded = result?.Text;
hey.Text = decoded;
}));
MemoryStream ms = new MemoryStream();
img.Save(ms, ImageFormat.Bmp);
ms.Seek(0, SeekOrigin.Begin);
BitmapImage bi = new BitmapImage();
bi.BeginInit();
bi.StreamSource = ms;
bi.EndInit();
bi.Freeze();
Dispatcher.BeginInvoke(new ThreadStart(delegate
{
frameHolder.Source = bi;
}));
}
catch (Exception ex)
{
}
}
扔掉下面的
...
System.Windows.Threading.DispatcherTimer dispatcherTimer = new System.Windows.Threading.DispatcherTimer();
dispatcherTimer.Tick += new EventHandler(dispatcherTimer_Tick);
dispatcherTimer.Interval = new TimeSpan(0, 5, 0);
...
dispatcherTimer.Start();
...
Bitmap GetBitmap(BitmapSource source)
{
...
}
...
private void dispatcherTimer_Tick(object sender, EventArgs e)
{
...
}
...
我没有编译或测试代码。让它更像是正确方向上的提示。ZXing.Net提供了一个使用BitmapSource实例的BarcodeReader类的特殊版本。
通常,如果您通过nuget将ZXing.Net包添加到项目中,则应该有对ZXing.presentation.dll的引用。如果没有,请从二进制发行版手动添加它。
特殊条形码阅读器位于名称空间ZXing.Presentation中。
您的方法的以下修改版本应该可以工作:
private void dispatcherTimer_Tick(object sender, EventArgs e)
{
BarcodeReader Reader = new ZXing.Presentation.BarcodeReader();
if (frameHolder.Source != null)
{
Result result = Reader.Decode((BitmapSource)frameHolder.Source);
decoded = result?.Text;
hey.Text = decoded;
}
}
不要忘记检查“result==null”,如果没有找到条形码,就会出现这种情况
顺便说一下,忘记你的Dispatchermer解决方案,在Cam_NewFrame中完成所有工作
void Cam_NewFrame(object sender, NewFrameEventArgs eventArgs)
{
try
{
System.Drawing.Bitmap img = (Bitmap)eventArgs.Frame.Clone();
// TODO: add some kind of mutex or similar here so that you don't start a new Decode before the previous one is finished
Dispatcher.BeginInvoke(new ThreadStart(delegate
{
// use the original BarcodeReader because we are using the bitmap instance directly
BarcodeReader Reader = new ZXing.BarcodeReader();
Result result = Reader.Decode(img);
decoded = result?.Text;
hey.Text = decoded;
}));
MemoryStream ms = new MemoryStream();
img.Save(ms, ImageFormat.Bmp);
ms.Seek(0, SeekOrigin.Begin);
BitmapImage bi = new BitmapImage();
bi.BeginInit();
bi.StreamSource = ms;
bi.EndInit();
bi.Freeze();
Dispatcher.BeginInvoke(new ThreadStart(delegate
{
frameHolder.Source = bi;
}));
}
catch (Exception ex)
{
}
}
扔掉下面的
...
System.Windows.Threading.DispatcherTimer dispatcherTimer = new System.Windows.Threading.DispatcherTimer();
dispatcherTimer.Tick += new EventHandler(dispatcherTimer_Tick);
dispatcherTimer.Interval = new TimeSpan(0, 5, 0);
...
dispatcherTimer.Start();
...
Bitmap GetBitmap(BitmapSource source)
{
...
}
...
private void dispatcherTimer_Tick(object sender, EventArgs e)
{
...
}
...
我没有编译或测试代码。更像是向正确方向暗示。我做错了什么?这里可能没有先知。只要你不说出你期望的结果和实际发生的事情,没有人能帮助你。你可能对学习和学习感兴趣。我做错了什么?这里可能没有先知。只要你不说出你期望的结果和实际发生的事情,没有人能帮助你。你可能对学习和学习感兴趣