使用 VintaSoft Barcode .NET SDK 识别邮政条形码

博客分类:条形码   .NET

2026/04/07

邮政条形码已成为现代物流的关键要素。它们能够实现信件和包裹的自动分拣、货物的跟踪,并最大限度地减少人工劳动。下面,我们将讨论不同类型的邮政条形码、识别它们时遇到的挑战,以及如何在 .NET 应用程序中使用 VintaSoft Barcode .NET SDK 识别邮政条形码。


为什么需要邮政条形码?

邮政条形码是一种机器可读标签,它将实物与信息系统中的记录关联起来。一组简短的条形或点隐藏着对业务和物流至关重要的数据。

通常,邮政条形码用于:

如果没有这些标签,信件和包裹的批量处理将无法进行。条形码扫描的正确实施直接影响分拣速度、服务质量和运营成本。


邮政条形码的主要类型

全球使用数十种标准,但要创建自己的扫描系统,至少了解一些基本类别非常重要。

四态邮政条形码(4-State)

这是一种特殊的条形码,其中每个条形的高度和相对于基线的位置都有四种状态之一。美国、英国、澳大利亚、日本和其他国家的主要邮政运营商都使用此类条形码。这些条形码通常包含寄件人标识符、服务类型、唯一物品编号和路由信息,同时保持相对紧凑的尺寸。


一维条形码

许多物流和邮政公司使用常见的格式,例如交错式 2/5 (ITF)、Code 128 和其他一维条形码。它们方便地应用于贴纸和运输标签,易于被扫描仪读取,并且几乎所有条形码识别 SDK 都支持。


二维条形码

数据矩阵码和二维码在邮政行业中越来越常见。它们最常用于机器支付邮票、组合邮政标签以及用于增强追踪功能的附加贴纸。二维条形码比线性条形码包含更多数据,即使部分损坏通常也能读取。


在实际系统中,您可能会遇到这些选项的任意组合。因此,您为 .NET 应用程序选择的 SDK 至少应支持您的邮政运营商或物流合作伙伴使用的格式。


识别邮政条形码的挑战

理论上,条形码识别是一项简单的任务。但实际上,邮政环境给开发人员和算法带来了诸多挑战。

最常见的问题:

由于这些因素,仅仅依赖最简单的算法和基本设置是不可接受的。我们需要一个灵活且抗干扰的引擎,以及微调条形码识别参数的能力。在 .NET 项目中,VintaSoft Barcode .NET SDK 可以满足这一需求。


条形码扫描的硬件选项

扫描邮政条形码可以基于各种类型的设备,解决方案架构取决于所选设备。

一种常见的方法是使用现成的硬件条形码扫描器。这些扫描器可以是手持式、嵌入式或固定式设备。它们速度快、可靠性高,设计用于全天候运行,并且通常可以独立解码基本条形码类型。但是,此类设备与现代移动和 Web 应用程序的集成度较低,并且支持的格式扩展取决于制造商的固件。

另一种方法是使用通用摄像头,并通过软件处理图像。在这种情况下,"扫描器"可以是智能手机摄像头、平板电脑摄像头、网络摄像头、传送带上的工业摄像头,甚至是标准的文档扫描仪。条形码识别由嵌入在 .NET 应用程序中的库完成。这正是 VintaSoft Barcode .NET SDK 方案的工作原理:您可以控制要搜索哪些条形码、如何处理图像以及如何将结果集成到您的系统中。


VintaSoft Barcode .NET SDK 的功能

VintaSoft Barcode .NET SDK 是一款专业的 .NET 生态系统条形码识别和生成工具。以下功能对于邮政物流尤为重要。

首先,VintaSoft Barcode .NET SDK 支持多种条形码。其中包括四个州的邮政条形码,以及信封、包裹、邮票和物流标签上常用的线性条形码和二维条形码。这使得一个解决方案即可处理内部邮政标记和来自合作伙伴递送服务的条形码。

其次,VintaSoft Barcode .NET SDK 旨在处理复杂的真实世界图像。其算法能够处理噪声、倾斜、打印不完美以及条形码尺寸过小都会影响识别效果。当操作员使用手机拍摄包裹或传送带摄像头拍摄的视频效果不佳时,这一点尤为重要。

第三,开发人员拥有灵活的设置选项。他们可以指定要搜索的条形码类型列表,优先考虑速度和质量,将搜索区域限制在感兴趣的矩形范围内,并指定单个图像中预期的条形码数量。这种自定义功能有助于使 SDK 适应特定的分拣线、介质类型和操作员工作流程。

最后,VintaSoft Barcode .NET SDK 可以轻松集成到各种类型的 .NET 应用程序中。该库可用于基于现代 .NET 版本构建的桌面解决方案、服务器服务、Web 服务和移动应用程序。这使得在公司的整个 IT 系统中构建统一的条形码识别架构成为可能。


邮政条形码扫描步骤

让我们来看一个典型的使用 VintaSoft Barcode .NET SDK 在 .NET 应用程序中实现的工作流程。

1. 首先,您需要获取信封或包裹的图像。这可以是上传的文件、扫描的文档、视频流中的单独帧,或使用移动设备摄像头拍摄的照片。在此步骤中,控制图像的大小和质量非常重要,以确保条形码占据足够的像素,并且在缩放时不会丢失。

2. 接下来,选择一组受支持的条形码类型。例如,您可以指定一个四州邮政条形码、一到两种 ITF 类型,以及一个 Data Matrix 条形码(如果您的运营商使用这种条形码)。此限制可提高速度并减少因随机图案、纹理和伪影造成的误判。

3. 接下来进行实际的条形码识别。应用程序调用 VintaSoft Barcode .NET SDK API,传入一张图片,并接收检测到的条形码集合。对于每个结果,该库会返回条形码类型、一个字符串值、图片区域的坐标以及一些其他参数。如果图片中包含例如邮政编码和承运商的物流条形码,则一次调用可以返回多个条形码。

4. 下一步是对接收到的数据进行分析和验证。字符串值将根据邮政运营商的内部格式进行解析。从中提取邮政编码、唯一运单号、客户ID、服务代码和其他逻辑字段。此步骤包括长度和结构验证、数据库匹配、校验位验证,以及在必要时对敏感数据部分进行掩码或加密。

5. 最后一步是将结果与业务逻辑集成。识别出的数据用于更新发货状态、自动生成路线,并记录收货、分拣和发货操作。操作员界面可以突出显示条形码区域,显示详细描述,并在置信度较低时提供重新扫描选项。


实用配置建议

为确保使用 VintaSoft Barcode .NET SDK 可靠快速地扫描邮政条形码,建议考虑以下几个实用要点。

首先,如果可能,将可识别的条形码格式列表限制为实际使用的条形码类型。这将减少处理时间,并降低噪声或部分徽标被错误地解释为其他条形码类型的可能性。

其次,仔细选择搜索区域。如果条形码几乎总是打印在信封或标签的特定区域,请定义一个感兴趣的矩形区域,并仅分析该区域。此方法在处理大型图像和视频流时尤其有用。

第三,测试不同的速度与质量配置。对于吞吐量至关重要的高负载分拣中心,可以将 SDK 配置为最大识别速度,重点关注典型的、未损坏的条形码。对于涉及具有法律意义的货物和大量问题标签的场景,启用更全面的分析模式更有意义。

第四,不要忘记拍摄条件。即使是最先进的SDK也无法弥补完全黑暗或来自灯光和展示柜的强烈眩光。操作界面可以包含相机引导、照明级别显示、自动缩放和条形码区域裁剪等功能。所有这些功能,结合VintaSoft Barcode .NET SDK的功能,可以显著提高最终成功读取邮政条形码的百分比。

结论

扫描和分析邮政条形码不仅仅是"识别图像中的条纹"。这项任务涉及一系列复杂的要求:格式多样、打印和拍摄条件不理想、数据吞吐量高,以及需要准确处理大量数据。通过使用像 VintaSoft Barcode .NET SDK 这样的专用 .NET 解决方案,您可以专注于业务逻辑,并将图像处理、解码和基本验证工作委托给成熟的工具。正确配置 SDK 并使用真实的信件和包裹样本进行全面测试,将使您能够构建一个可靠的系统,该系统将成为现代邮政物流跟踪和自动化的基础。


以下是一些 C# 代码,演示如何识别相机图像中的邮政条形码:
/// <summary>
/// Recognizes postal barcodes from a <see cref="System.Drawing.Bitmap"/>.
/// </summary>
/// <param name="bitmap">A bitmap with barcodes.</param>
public static void RecognizePostalBarcodesFromBitmap(System.Drawing.Bitmap bitmap)
{
    // create barcode reader
    using (Vintasoft.Barcode.BarcodeReader reader = new Vintasoft.Barcode.BarcodeReader())
    {
        // specify that barcode reader must search for Postnet barcodes
        reader.Settings.ScanBarcodeTypes = Vintasoft.Barcode.BarcodeType.Postnet;
        // specify that barcode reader must search for Planet barcodes
        reader.Settings.ScanBarcodeTypes = Vintasoft.Barcode.BarcodeType.Planet;
        // specify that barcode reader must search for Intelligent Mail barcodes
        reader.Settings.ScanBarcodeTypes = Vintasoft.Barcode.BarcodeType.IntelligentMail;
        // specify that barcode reader must search for Australian Post barcodes
        reader.Settings.ScanBarcodeTypes = Vintasoft.Barcode.BarcodeType.AustralianPost;
        // specify that barcode reader must search for Japan Post barcodes
        reader.Settings.ScanBarcodeTypes = Vintasoft.Barcode.BarcodeType.JapanPost;
        // specify that barcode reader must search for Dutch KIX barcodes
        reader.Settings.ScanBarcodeTypes = Vintasoft.Barcode.BarcodeType.DutchKIX;
        // specify that barcode reader must search for Royal Mail barcodes
        reader.Settings.ScanBarcodeTypes = Vintasoft.Barcode.BarcodeType.RoyalMail;
        // specify that barcode reader must search for Royal Mail Mailmark 4-state barcode C barcodes
        reader.Settings.ScanBarcodeTypes = Vintasoft.Barcode.BarcodeType.Mailmark4StateC;
        // specify that barcode reader must search for Royal Mail Mailmark 4-state barcode L barcodes
        reader.Settings.ScanBarcodeTypes = Vintasoft.Barcode.BarcodeType.Mailmark4StateL;

        // specify that barcode reader must search for Deutsche Post Identcode barcodes
        reader.Settings.ScanBarcodeSubsets.Add(Vintasoft.Barcode.SymbologySubsets.BarcodeSymbologySubsets.DeutschePostIdentcodeBarcodeSymbology);
        // specify that barcode reader must search for Deutsche Post Leitcode barcodes
        reader.Settings.ScanBarcodeSubsets.Add(Vintasoft.Barcode.SymbologySubsets.BarcodeSymbologySubsets.DeutschePostLeitcodeBarcodeSymbology);
        // specify that barcode reader must search for DHL AWB barcodes
        reader.Settings.ScanBarcodeSubsets.Add(Vintasoft.Barcode.SymbologySubsets.BarcodeSymbologySubsets.DhlAwbBarcodeSymbology);
        // specify that barcode reader must search for FedEx Ground 96 barcodes
        reader.Settings.ScanBarcodeSubsets.Add(Vintasoft.Barcode.SymbologySubsets.BarcodeSymbologySubsets.FedExGround96BarcodeSymbology);
        // specify that barcode reader must search for Italian Post 2 of 5 barcodes
        reader.Settings.ScanBarcodeSubsets.Add(Vintasoft.Barcode.SymbologySubsets.BarcodeSymbologySubsets.ItalianPost2of5);
        // specify that barcode reader must search for Royal Mail Mailmark CMDM Type29 2D barcodes
        reader.Settings.ScanBarcodeSubsets.Add(Vintasoft.Barcode.SymbologySubsets.BarcodeSymbologySubsets.MailmarkCmdmType29BarcodeSymbology);
        // specify that barcode reader must search for Royal Mail Mailmark CMDM Type7 2D barcodes
        reader.Settings.ScanBarcodeSubsets.Add(Vintasoft.Barcode.SymbologySubsets.BarcodeSymbologySubsets.MailmarkCmdmType7BarcodeSymbology);
        // specify that barcode reader must search for Royal Mail Mailmark CMDM Type9 2D barcodes
        reader.Settings.ScanBarcodeSubsets.Add(Vintasoft.Barcode.SymbologySubsets.BarcodeSymbologySubsets.MailmarkCmdmType9BarcodeSymbology);
        // specify that barcode reader must search for Swiss PostParcel barcodes
        reader.Settings.ScanBarcodeSubsets.Add(Vintasoft.Barcode.SymbologySubsets.BarcodeSymbologySubsets.SwissPostParcelBarcodeSymbology);
 
        // read barcodes from image
        Vintasoft.Barcode.IBarcodeInfo[] infos = Vintasoft.Barcode.GdiExtensions.ReadBarcodes(reader, bitmap);

        // if barcodes are not detected
        if (infos.Length == 0)
        {
            System.Console.WriteLine("No barcodes found.");
        }
        // if barcodes are detected
        else
        {
            // get information about extracted barcodes

            System.Console.WriteLine(string.Format("{0} barcodes found:", infos.Length));
            System.Console.WriteLine();
            for (int i = 0; i < infos.Length; i++)
            {
                Vintasoft.Barcode.IBarcodeInfo info = infos[i];
                System.Console.WriteLine(string.Format("[{0}:{1}]", i + 1, info.BarcodeType));
                System.Console.WriteLine(string.Format("Value:      {0}", info.Value));
                System.Console.WriteLine(string.Format("Region:     {0}", info.Region));
                System.Console.WriteLine();
            }
        }
    }
}