在实际业务系统中,条码的识别需求随处可见——从仓储物流的包裹追踪、零售业的商品扫码,到票务系统的票据验证、医疗行业的样本追溯,都离不开对条码图片的自动化解析。

本文将介绍如何在 .NET 项目中通过 C# 实现一维条码扫描,涵盖从图片文件、内存流中读取条码,获取条码位置信息等实用示例。

注意:本文使用的免费库 FreeSpire.Barcode 不支持二维码(QR Code、Data Matrix 等)的扫描。


一、环境配置与依赖安装

首先需要创建一个 .NET 项目。无论是控制台应用还是桌面程序均可。

通过 NuGet 包管理器安装依赖库:

Install-Package FreeSpire.Barcode

或在 .NET CLI 中执行:

dotnet add package FreeSpire.Barcode

安装完成后,在代码文件中引入命名空间:

using Spire.Barcode;

二、核心 API 说明

条码扫描主要由 BarcodeScanner 类提供,其中包含以下常用方法:

方法 说明
Scan(string path) 从图片文件中扫描所有条码
Scan(Stream stream) 从数据流中扫描所有条码
Scan(Bitmap bitmap) 从位图对象中扫描所有条码
ScanOne(...) 快速扫描单一条码(适用于图像中只包含一个条码的场景)
ScanInfo(...) 扫描并获取条码类型、位置坐标等详细信息

所有 ScanScanInfo 方法均提供了带 BarCodeType 参数的重载版本,可指定只识别特定类型的一维条码(如 Code128、EAN-13 等),从而提高识别效率。


三、从图片文件扫描条码

3.1 扫描单张图片中的条码

最简单的场景是扫描一张图片中已存在的条码。以下示例演示如何从图片文件中读取 Code128 条码的内容:

using Spire.Barcode;

class Program
{
    static void Main(string[] args)
    {
        // 指定图片路径
        string imagePath = @"C:\barcode-sample.png";

        // 扫描图片中的条码,仅识别 Code128 类型
        string[] results = BarcodeScanner.Scan(imagePath, BarCodeType.Code128);

        // 输出识别结果
        if (results.Length > 0)
        {
            foreach (string result in results)
            {
                Console.WriteLine("识别到条码内容: " + result);
            }
        }
        else
        {
            Console.WriteLine("未识别到任何条码。");
        }
    }
}

Scan() 方法返回一个字符串数组,能够处理一张图片中包含多个条码的情形。若图片中恰好只有一个条码,也可使用 ScanOne() 方法直接返回字符串结果:

string result = BarcodeScanner.ScanOne(imagePath, BarCodeType.Code128);

3.2 扫描多种条码类型

在实际业务中,图片可能包含不同类型的一维条码(如 Code 128、EAN-13 混合出现)。若不确定条码类型,可直接调用不指定类型的方法重载:

string[] results = BarcodeScanner.Scan(imagePath);

四、从数据流扫描条码

在 Web 应用或微服务架构中,用户上传的图片通常以数据流(Stream)的形式存在,无需写入磁盘即可直接处理。这种方式可以减少 I/O 开销,提升响应速度,也更适合云端部署环境。

using System;
using System.IO;
using Spire.Barcode;

namespace BarcodeScanDemo
{
    class StreamScan
    {
        static void Main(string[] args)
        {
            string imagePath = @"C:\Barcode\stream_barcode.jpg";
            
            // 1. 将图片转换为内存流(适配上传流、网络流直接使用)
            using (FileStream fs = new FileStream(imagePath, FileMode.Open, FileAccess.Read))
            using (MemoryStream ms = new MemoryStream())
            {
                fs.CopyTo(ms);
                // 流指针复位(关键:必须将流位置重置到起始位置)
                ms.Position = 0;

                // 2. 从内存流中扫描条码(自动检测类型)
                string[] results = BarcodeScanner.Scan(ms);

                // 输出结果
                if (results != null && results.Length > 0)
                {
                    Console.WriteLine("流数据条码识别结果:" + results[0]);
                }
            }
        }
    }
}

除了 Stream 输入外,Scan() 方法还支持直接从 Bitmap 对象进行扫描,方便与现有的图像处理流程进行集成。


五、获取条码详细信息

在某些业务场景中,仅获取条码内容可能不够——例如需要对图片中的条码区域进行标注、裁剪或统计条码分布情况。此时可以使用 ScanInfo() 方法获取更丰富的信息,包括条码类型和四个顶点坐标。

string imagePath = @"C:\multi-barcode.png";

// 扫描并获取详细信息
BarcodeInfo[] barcodeInfos = BarcodeScanner.ScanInfo(imagePath);

for (int i = 0; i < barcodeInfos.Length; i++)
{
    Console.WriteLine($"条码 {i + 1}:");
    Console.WriteLine($"  内容: {barcodeInfos[i].DataString}");
    Console.WriteLine($"  类型: {barcodeInfos[i].BarCodeReadType}");

    // 获取条码在图片中的四个顶点坐标
    Point[] vertexes = barcodeInfos[i].Vertexes;
    Console.WriteLine($"  顶点坐标: ({vertexes[0].X}, {vertexes[0].Y}), " +
                      $"({vertexes[1].X}, {vertexes[1].Y}), " +
                      $"({vertexes[2].X}, {vertexes[2].Y}), " +
                      $"({vertexes[3].X}, {vertexes[3].Y})");
    Console.WriteLine();
}

该功能在需要对图片中的条码进行可视化标注、区域裁剪或多码联动处理时尤为实用。

输出结果示例:
扫描条码和位置信息


六、性能优化与常见问题

6.1 提高识别率的关键因素

在实际项目中,条码识别失败往往不是库本身的问题,而是图片质量造成的。以下因素对识别成功率有显著影响:

静区(Quiet Zone)不足:条码四周需要留出纯空白区域,为扫描设备提供稳定的背景参考。建议在生成或截图时确保条码周边有足够的空白边距。

分辨率过低:一维条码由极细的线条组成,当输出分辨率不足时,窄条无法被精确绘制,导致条空比例被破坏。建议在工业级应用中使用不低于 300 DPI 的图片。

图片角度与畸变:库支持从任意角度检测条码,但过度倾斜或透视畸变仍会影响识别率,尽量保持图片正对拍摄。

图片格式与清晰度:优先使用 PNG 格式,避免过度压缩导致条码边缘模糊。

6.2 识别速度优化

若扫描过程中遇到性能瓶颈,可以尝试以下优化措施:

  • 缩小图片尺寸:在保持条码清晰度的前提下,适当缩放图片尺寸可以显著减少扫描耗时。
  • 使用 ScanOne() 替代 Scan():如果确认图片中只有一个条码,使用 ScanOne() 方法比 Scan() 更高效。
  • 指定条码类型:当明确知道图片中的条码类型(如 Code128)时,传入 BarCodeType 参数可减少自动检测所需的时间。
// 更高效的写法:指定具体条码类型
string result = BarcodeScanner.ScanOne(imagePath, BarCodeType.Code128);
  • 预处理图片(灰度化、二值化):对输入图片进行灰度转换或二值化处理,有助于提升识别效率。

6.3 错误处理

在实际运行环境中,建议添加完善的错误处理逻辑:

try
{
    string[] results = BarcodeScanner.Scan(imagePath);
    if (results == null || results.Length == 0)
    {
        // 未识别到条码,可尝试图像增强处理或记录日志
        Console.WriteLine("未识别到条码,建议检查图片质量。");
    }
}
catch (Exception ex)
{
    Console.WriteLine($"条码扫描异常: {ex.Message}");
}

七、总结

本文介绍了如何在 .NET 项目中通过 C# 实现一维条码扫描,涵盖了从基础安装配置、单张图片扫描、数据流处理、多码识别到性能优化等各个环节。主要要点总结如下:

  • BarcodeScanner.Scan()ScanOne() 是条码识别的核心方法,支持图片文件、Stream 流和 Bitmap 对象三种输入方式
  • ScanInfo() 可获取条码类型和位置坐标,便于实现区域标注或数据分析
  • Web 应用中推荐使用内存流直接处理上传图片,避免磁盘 I/O 开销
  • 条码识别率受图片质量影响较大,需关注静区、分辨率和清晰度
  • 通过指定条码类型、缩小图片尺寸等方法可有效提升扫描速度

条码识别作为自动化数据处理的基础环节,其稳定性和准确度直接影响业务流程的效率。掌握上述技术要点后,开发者可以根据实际需求灵活构建适用于自身场景的一维条码扫描解决方案。

更多推荐