博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
给你的应用“一只”智慧的眼睛 —— Barcode常识普及以及识别信息处理
阅读量:4327 次
发布时间:2019-06-06

本文共 19274 字,大约阅读时间需要 64 分钟。

在“”这篇文章中,我们通过“成像”、“截图”与“识别”三个步骤介绍了使用扫码的主要过程及注意事项。本文主要针对“识别”的过程,对Barcode的概念作出一个较为简单的介绍,同时也会讨论ZXing的使用方法。

 

是一个Java实现的开源库,可以支持多种Barcode的识别和生成,同时也为其它的语言提供了相应的接口,比如C++、Python、.Net等等。这里,我们使用,可以很方便的集成在UWP环境中,便于扫码工作的开发。

 

Barcode简介

Barcode是一种机器可读的数据表示方式,作为某种商品或产品的唯一标识。通常被翻译成条码,但我个人并不喜欢这种翻译,因为不是所有的barcode都是条形的。当然,这应该是有历史原因的。Barcode的形式多种多样,按照它们的外观,可以分为Linear barcode(一维码)和Matrix barcode(二维码)。你可能认为你对它们都有所了解,因为它们大概都是这个样子的:

     

但事实上,它们有甚至有可能是这样子的:

   

我们通常所说的二维码和上文提到的二维码有所不同,只是Matrix barcode的一种,叫做QR code。举这些例子只是为了说明Barcode种类繁多,有些编码格式并不常用,即使是ZXing也没有做到所有格式的支持,开发者只需了解就好。

 

Code 39、Code 128、EAN、UPC、QR Code是我们生活中能经常见到的几种编码格式,同时ZXing对几种格式都有比较好的支持。其中,UPC-A是一种国际通用的编码格式,由12个数字构成,EAN-13是在UPC-A基础上的一种扩充(多了一个数字)。快数一数你身边的薯片的编码是不是13位!如果是的话,它最前边的两个数字是不是“69”?在EAN-13的编码体系中,前三位数字表示商品生产商的国家(并不是商品所属公司的国家),中国的编码是690~699,美国是(000~019、030~039、060~139),日本是(450~459、490~499),and so on。不同的编码格式通常用在不同的领域,如果你看到了一个Code 39或者Code 128的Barcode,那么这很就可能是一个快递编码,这个时候你就可以去那些提供快递查询的网站查询一下你的快递信息,如果有API提供出来那就更是再好不过了。至于QR Code,就是我们经常用手机扫一扫的二维码,表示的信息更是多种多样,并不仅仅是一个url那么简单,至于这些信息如何处理,是我们一会儿将要讨论的内容。

 

配置工程

在提到,可以在Visual Studio环境下,通过nuget管理器安装ZXing.Net,如果你仅仅希望通过扫码得到一个扫码结果(比如字符串,或者是一个链接),当然可以这样做,而且过程十分简单。但这里我们并不推荐这种方法,因为从NuGet上得到的package只提供了一些简单的API接口,并没有将ZXing.Net的API全部提供出来,至于为什么这么做,说实话,我也不知道,可能是为了稳定性等原因。如果你是一个比较执着的programmer,也可以在使用NuGet包的情况下,自己实现其它丰富的功能,毕竟有ZXing的源代码可以参考,这就是开源的好处!在这篇文章中,我们还是以简单为主,毕竟ZXing.Net已经为我们提供了编译好的动态连接库,有什么理由让我们不用呢?

 

Important 官网提供的库和NuGet提供的库API稍微有些不同,如果需要更换,需要稍作修改,但过程并不是很繁琐。

 

你可以从下载ZXing.Net的Release,压缩包目录下的/winrt/zxing.winrt.dll即是我们希望添加到工程的引用。

 

然后,把这个reference添加到相应的工程里就行:

 

 

获取Barcode内容信息

 

首先,你可以按照“”这篇文章中提供的步骤,初始化摄像头、设置Timer并添加Tick事件,在Tick事件中,通过调用ZXing.Net的API获取扫码结果。

private async void TimerTick(object sender, object e){    try    {        if (_mediaCapture == null)            return;        var props = _mediaCapture.VideoDeviceController.GetMediaStreamProperties(MediaStreamType.VideoPreview);        uint width = 0, height = 0;        if (props is ImageEncodingProperties)        {            width = (props as ImageEncodingProperties).Width;            height = (props as ImageEncodingProperties).Height;        }        else if (props is VideoEncodingProperties)        {            width = (props as VideoEncodingProperties).Width;            height = (props as VideoEncodingProperties).Height;        }        System.Diagnostics.Debug.WriteLine("Start scanning...");        Result decodeResult = null;        using (VideoFrame frameFormat = new VideoFrame(BitmapPixelFormat.Rgba8, (int)width, (int)height))        {            using (var frame = await _mediaCapture.GetPreviewFrameAsync(frameFormat))            {                var buffer = new Windows.Storage.Streams.Buffer(                    (uint)(4 * frame.SoftwareBitmap.PixelWidth * frame.SoftwareBitmap.PixelHeight));                frame.SoftwareBitmap.CopyToBuffer(buffer);                var reader = new BarcodeReader();                decodeResult = reader.Decode(buffer.ToArray(), (int)width, (int)height, RGBLuminanceSource.BitmapFormat.RGB32);                System.Diagnostics.Debug.WriteLine(decodeResult);                if (decodeResult != null)                {                    await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>                    {                        resultTextBlock.Text = decodeResult.Text;                    });                }            }        }        //You can handle decodeResult by other ways.        if (decodeResult != null)            await Windows.System.Launcher.LaunchUriAsync(new Uri(decodeResult.Text));    }    catch (ArgumentNullException ane)    {        System.Diagnostics.Debug.WriteLine(ane.ToString());    }    catch (UriFormatException ufe)    {        System.Diagnostics.Debug.WriteLine(ufe.ToString());    }    catch (Exception ex)    {        System.Diagnostics.Debug.WriteLine("Timer tick exception: {0}!", ex);    }}

得到的Result包含两个重要的属性: Text和BarcodeFormat。其中,Text就是相关Barcode表示的文本信息,而BarcodeFormat则是对应的编码方式。你可能会问,知道内容就好了,要编码方式有什么用?这里有个问题是,同样的一段文本信息(尤其是纯数字信息)在不同的编码方式下可能会有不同的含义(比如两种完全不同的商品)。

 

解析内容

如同前面所说,Barcode可以表示各种各样的信息,可能是“Hello UWP!”这样的纯文本,也可能是图书的ISBN编码,或者是一个网络上的URL连接。这里,我们可以通过编码类型来判断,因为不同的编码类型应用场景不一样嘛,许多一维码根本就不支持非数字文本。此外,ZXing也为我们提供的方便的接口(NuGet上的ZXing.Net并没有),能标识出文本的具体内容:

ParsedResult parsedResult = ResultParser.parseResult(result);

parsedResult包含以下几种信息:

//// Summary://     Represents the type of data encoded by a barcode -- from plain text, to a URI,//     to an e-mail address, etc.public enum ParsedResultType{    ADDRESSBOOK = 0,    EMAIL_ADDRESS = 1,    PRODUCT = 2,    URI = 3,    TEXT = 4,    GEO = 5,    TEL = 6,    SMS = 7,    CALENDAR = 8,    WIFI = 9,    ISBN = 10,    VIN = 11}
ParsedResultType

 

后续工作

有了以上的内容,我们就可以对信息作进一步的处理,这就需要依赖于第三方服务提供的API接口了。

 

快递:

“快递100”为用户提供了一个非常方便的页面,通过快递条码就可以轻松查询到快递信息。

如果想要自定义页面,则推荐使用其API:

 

商品:

亚马逊为其网站的商品提供了商品搜索的,通过提供条码Id及其类型,则可以查询到相应商品信息。

ItemLookup页面中,填写一些查询的基本信息,Marketplace可供用户选择查询的数据源,webservices.amazon.com为美国的市场,中国市场可以选择webservices.amazon.cn。下面的三个参数需要用户注册亚马逊的AWS服务(注册过程相当复杂╮(╯_╰)╭)。

ItemLookup的过程,设置ItemId(code信息)和IdType(这里可以选择ASIN、SKU、UPC、EAN、ISBN),然后点击Run request就可以生成Request请求的URL,并且能获取到响应的服务器Response——一个xml文档,包含商品的各种信息。

Signed Request URL:

http://webservices.amazon.com/onca/xml?AWSAccessKeyId=********************&AssociateTag=************&IdType=UPC&ItemId=431604028525&Operation=ItemLookup&ResponseGroup=Images%2CItemAttributes%2COffers&SearchIndex=All&Service=AWSECommerceService&Timestamp=2016-05-30T12%3A49%3A51.000Z&Signature=**********************************************

Response:

f90faa33-3fb2-4fd7-a885-abe33ea6967f
0.1724468780000000
True
UPC
431604028525
Images
ItemAttributes
Offers
All
All
B008BO4D9G
http://www.amazon.com/Nature-Made-Pharmacist-Recommended-Concentrate/dp/B008BO4D9G%3FSubscriptionId%3DAKIAIZNMTNCCU6OFZG4A%26tag%3Dfreshomer-20%26linkCode%3Dxm2%26camp%3D2025%26creative%3D165953%26creativeASIN%3DB008BO4D9G
Technical Details
http://www.amazon.com/Nature-Made-Pharmacist-Recommended-Concentrate/dp/tech-data/B008BO4D9G%3FSubscriptionId%3DAKIAIZNMTNCCU6OFZG4A%26tag%3Dfreshomer-20%26linkCode%3Dxm2%26camp%3D2025%26creative%3D386001%26creativeASIN%3DB008BO4D9G
Add To Baby Registry
http://www.amazon.com/gp/registry/baby/add-item.html%3Fasin.0%3DB008BO4D9G%26SubscriptionId%3DAKIAIZNMTNCCU6OFZG4A%26tag%3Dfreshomer-20%26linkCode%3Dxm2%26camp%3D2025%26creative%3D386001%26creativeASIN%3DB008BO4D9G
Add To Wedding Registry
http://www.amazon.com/gp/registry/wedding/add-item.html%3Fasin.0%3DB008BO4D9G%26SubscriptionId%3DAKIAIZNMTNCCU6OFZG4A%26tag%3Dfreshomer-20%26linkCode%3Dxm2%26camp%3D2025%26creative%3D386001%26creativeASIN%3DB008BO4D9G
Add To Wishlist
http://www.amazon.com/gp/registry/wishlist/add-item.html%3Fasin.0%3DB008BO4D9G%26SubscriptionId%3DAKIAIZNMTNCCU6OFZG4A%26tag%3Dfreshomer-20%26linkCode%3Dxm2%26camp%3D2025%26creative%3D386001%26creativeASIN%3DB008BO4D9G
Tell A Friend
http://www.amazon.com/gp/pdp/taf/B008BO4D9G%3FSubscriptionId%3DAKIAIZNMTNCCU6OFZG4A%26tag%3Dfreshomer-20%26linkCode%3Dxm2%26camp%3D2025%26creative%3D386001%26creativeASIN%3DB008BO4D9G
All Customer Reviews
http://www.amazon.com/review/product/B008BO4D9G%3FSubscriptionId%3DAKIAIZNMTNCCU6OFZG4A%26tag%3Dfreshomer-20%26linkCode%3Dxm2%26camp%3D2025%26creative%3D386001%26creativeASIN%3DB008BO4D9G
All Offers
http://www.amazon.com/gp/offer-listing/B008BO4D9G%3FSubscriptionId%3DAKIAIZNMTNCCU6OFZG4A%26tag%3Dfreshomer-20%26linkCode%3Dxm2%26camp%3D2025%26creative%3D386001%26creativeASIN%3DB008BO4D9G
http://ecx.images-amazon.com/images/I/51j%2BGzAmXTL._SL30_.jpg
30
15
http://ecx.images-amazon.com/images/I/51j%2BGzAmXTL._SL75_.jpg
75
37
http://ecx.images-amazon.com/images/I/51j%2BGzAmXTL._SL75_.jpg
75
37
http://ecx.images-amazon.com/images/I/51j%2BGzAmXTL._SL110_.jpg
110
54
http://ecx.images-amazon.com/images/I/51j%2BGzAmXTL._SL160_.jpg
160
79
http://ecx.images-amazon.com/images/I/51j%2BGzAmXTL.jpg
500
247
http://ecx.images-amazon.com/images/I/51C8Vnbv71L._SL30_.jpg
30
19
http://ecx.images-amazon.com/images/I/51C8Vnbv71L._SL75_.jpg
75
48
http://ecx.images-amazon.com/images/I/51C8Vnbv71L._SL75_.jpg
75
48
http://ecx.images-amazon.com/images/I/51C8Vnbv71L._SL110_.jpg
110
71
http://ecx.images-amazon.com/images/I/51C8Vnbv71L._SL160_.jpg
160
103
http://ecx.images-amazon.com/images/I/51C8Vnbv71L.jpg
500
321
http://ecx.images-amazon.com/images/I/31m-odZf5HL._SL30_.jpg
30
22
http://ecx.images-amazon.com/images/I/31m-odZf5HL._SL75_.jpg
75
56
http://ecx.images-amazon.com/images/I/31m-odZf5HL._SL75_.jpg
75
56
http://ecx.images-amazon.com/images/I/31m-odZf5HL._SL110_.jpg
110
82
http://ecx.images-amazon.com/images/I/31m-odZf5HL._SL160_.jpg
160
120
http://ecx.images-amazon.com/images/I/31m-odZf5HL.jpg
500
375
Health and Beauty
Nature Made
474911
0031604028527
0031604028527
0783318987897
0431604028525
USP VERIFIED - United States Pharmacopeia (USP) sets standards for medicines, food ingredients, and dietary supplements worldwide. Nature Made was the first supplement product to be verified by USP, including fish oil supplements.
FOOD EQUIVALENT - Two fish oil pills contain the same amount of omega-3 fatty acids of two servings of fish.
SOURCE AND PURITY - Comes from deep ocean water fish (NOT FARM RAISED) and state-of-the-art purification processes remove mercury.  Omega-3 fish oil helps support a healthy heart.
2 BOTTLES OF 200 GEL TABS EACH -There are 200 fish oil capsules in each of two bottles, for a total of 400 softgels.
HIGH QUANTITY DOSAGE - Nature Made Fish Oil daily suggested usage contains 2,400 mg of fish oil with 720 mg of Omega-3 Fatty Acids (including 360 mg EPA and 240 mg DHA).
0
313
613
174
625
Nature Made
474911
1
320
630
180
620
1
474911
Health and Beauty
HEALTH_PERSONAL_CARE
Nature Made
400 Softgels
Nature Made
Nature Made Fish Oil (400 Softgels) Pharmacist Recommended Fish Oil Pills (2400mg Fish Oil Concentrate, 720mg of Omega 3 Fatty Acids, 360mg EPA, 240 mg DHA)
431604028525
431604028525
783318987897
031604028527
1560
USD
$15.60
64
0
0
0
1
1
http://www.amazon.com/gp/offer-listing/B008BO4D9G%3FSubscriptionId%3DAKIAIZNMTNCCU6OFZG4A%26tag%3Dfreshomer-20%26linkCode%3Dxm2%26camp%3D2025%26creative%3D386001%26creativeASIN%3DB008BO4D9G
New
lt2bT68NjTRG7AuG%2FAAqcBmiJtLextibUqq62er5gQHN%2FtsGphHchT6YZGwo9DRl4CDw8UuCEQki2TAilIIVkKZ03DwP194gQLXxDlAXT%2BvPLPifatvCMnSk9skoDe%2FETTBJg3o7sdO%2B%2FevV0UWM6Q%3D%3D
2135
USD
$21.35
Usually ships in 24 hours
now
0
0
0
1
Response

 

当然,这只是Amazon为我们提供的一个开发工具,在真正开发过程中,需要用code来构造Amazon的数据请求。

 

一些数据常量:

private const string AWS_ACCESS_KEY_ID = "********************";private const string AWS_SECRET_KEY = "****************************************";private const string AWS_ASSOCIATE_TAG = "************";private const string FORMAT_SORTABLE_TIME = "yyyy'-'MM'-'dd'T'HH':'mm':'ss'.000Z'";private static readonly string HASH_ALGORITHM_NAME = MacAlgorithmNames.HmacSha256;private const string ENDPOINT_ITEM_SEARCH_BY_PRODUCT_ID =    "http://webservices.amazon.com/onca/xml?AWSAccessKeyId={0}&AssociateTag={1}&IdType={2}&ItemId={3}&Operation=ItemLookup&ResponseGroup=Images%2CItemAttributes%2COffers&SearchIndex=All&Service=AWSECommerceService&Timestamp={4}&Signature={5}";private const string FORMAT_STRING_TO_SIGN =    "GET\nwebservices.amazon.com\n/onca/xml\nAWSAccessKeyId={0}&AssociateTag={1}&IdType={2}&ItemId={3}&Operation=ItemLookup&ResponseGroup=Images%2CItemAttributes%2COffers&SearchIndex=All&Service=AWSECommerceService&Timestamp={4}";
Constant variables

通过ItemId和IdType获取商品信息:

public static async Task
GetProductsById(String id, String idType){ try { String time = DateTime.Now.ToUniversalTime().ToString(FORMAT_SORTABLE_TIME); String stringToSign = String.Format(FORMAT_STRING_TO_SIGN, AWS_ACCESS_KEY_ID, AWS_ASSOCIATE_TAG, idType, id, WebUtility.UrlEncode(time)); IBuffer buffMsg; CryptographicKey hmacKey; IBuffer buffHMAC; String hmac = createHMAC(stringToSign, HASH_ALGORITHM_NAME, AWS_SECRET_KEY, out buffMsg, out hmacKey, out buffHMAC); String url = String.Format(ENDPOINT_ITEM_SEARCH_BY_PRODUCT_ID, AWS_ACCESS_KEY_ID, AWS_ASSOCIATE_TAG, idType, id, WebUtility.UrlEncode(time), WebUtility.UrlEncode(hmac)); HttpClient httpClient = new HttpClient(); HttpRequestMessage req = new HttpRequestMessage(HttpMethod.Get, new Uri(url)); req.Headers.AcceptEncoding.Clear(); HttpResponseMessage resp = await httpClient.SendRequestAsync(req); String responseStr = ""; if (resp.IsSuccessStatusCode) { IBuffer buf = await resp.Content.ReadAsBufferAsync(); responseStr = Encoding.UTF8.GetString(buf.ToArray()); } if (String.IsNullOrEmpty(responseStr)) return null; //Get data form xml string. LookupResponse response = null; try { using (var stream = new MemoryStream(Encoding.UTF8.GetBytes(responseStr))) { XmlSerializer xmlSerializer = new XmlSerializer(typeof(LookupResponse)); response = xmlSerializer.Deserialize(stream) as LookupResponse; } } catch (Exception) { return null; } if (response == null || response.Items == null || response.Items.Count <= 0) return null; return response.Items[0]; } catch { return null; }}
GetProductsById

中间有一个签名的过程需要用到HMAC的方法:

private static String createHMAC(String strMsg, String strAlgName, String key, out IBuffer buffMsg, out CryptographicKey hmacKey, out IBuffer buffMAC){    MacAlgorithmProvider objMacProv = MacAlgorithmProvider.OpenAlgorithm(strAlgName);    String strNameUsed = objMacProv.AlgorithmName;    BinaryStringEncoding encoding = BinaryStringEncoding.Utf8;    buffMsg = CryptographicBuffer.ConvertStringToBinary(strMsg, encoding);    IBuffer buffKeyMaterail = CryptographicBuffer.ConvertStringToBinary(key, BinaryStringEncoding.Utf8);    hmacKey = objMacProv.CreateKey(buffKeyMaterail);    buffMAC = CryptographicEngine.Sign(hmacKey, buffMsg);    return CryptographicBuffer.EncodeToBase64String(buffMAC);}
createHMAC

经过这些过程,就可以拿到Amazon的数据了,至于sample code中的LookupResponse如何构造,请参考AWS API以及Response返回数据。

 

后记

关于Barcode的处理还要看实际的应用场景,本文只是通过举例提到针对某些场景的处理方式,欢迎大家多多交流经验。

关于淘宝是否有对外开放的API,我本人并没有调研或者使用过,如果有的话,希望大家分享一下开发经验,谢谢!

 

Links

转载于:https://www.cnblogs.com/ms-uap/p/5528717.html

你可能感兴趣的文章
在线的JSON formate工具
查看>>
winform非常实用的程序退出方法!!!!!(转自博客园)
查看>>
xml解析
查看>>
centos安装vim
查看>>
linux工作调度(计划任务)
查看>>
hdu--1698 Just a Hook(线段树+区间更新+懒惰标记)
查看>>
SynchronousQueue
查看>>
Python学习笔记-EXCEL操作
查看>>
依照特定轨迹遍历字符串图
查看>>
Mantis 1.1.0 报告问题中设置必填项或取消必填项[Z]
查看>>
爬虫添加代理
查看>>
POJ 题目1204 Word Puzzles(AC自己主动机,多个方向查询)
查看>>
oracle经常使用函数(2)
查看>>
Iocomp控件之数字显示【图文】
查看>>
Androd开发之广告栏设计
查看>>
jquery.fly.min.js 拋物插件
查看>>
mini2440系统引导(五)串口UART
查看>>
JDK5.0新特性系列---9.注释功能Annotation
查看>>
普通平衡树(指针splay)
查看>>
【HEOI 2018】Day2 T2 林克卡特树
查看>>