提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

条码已渗透到我们生活的各个方面,如支付、物流仓储、零售和工业生产流水线等。扫码读码看似简单“一扫即得”,但在实际场景中却因环境、载体、条码状态等因素的影响而造成困难。如条码布局无序,且摆放角度随机,传统扫码设备难以快速锁定目标;受环境光照影响出现反光、高亮等情形;要定位的条码尺寸小,与周围背景对比度低,很难分辨等。传统条码定位依赖条码的边缘、明暗对比等几何特征,对模糊、遮挡、扭曲的条码适应性差。AI模型凭借对复杂特征的提取与适配能力,即使在强光、阴影等场景下,也能精准捕捉条码区域。例如,针对倾斜、旋转的条码,可通过数据增强训练,实现对任意角度条码的定位。

目前调用AI模型进行实际操作,使用语言比较多的有python和c++。本文将介绍如何在c++项目中paddle框架进行条码的快速定位,并给出相应的示例。

一、paddle是什么?

paddle是由百度开发并开源的深度学习框架,提供了丰富的工具组件和服务平台,适用于图像识别、自然语言处理、语音识别等多个领域;并且提供了预训练模型,可以快速完成模型微调并应用于实际业务场景。

二、使用步骤

1.安装paddle库

在c++项目中利用paddle框架进行推理需要安装paddle Inference推理库。相应的库可以自己从源代码进行编译,也可以下载编译好的release版本。paddle Inference推理库包含了头文件、dll动态库和lib动态库,如下图所示。

2.图像预处理

在代码中需要包含头文件"paddle_inference_api.h"

为了适应模型,需要对图像数据进行预处理和标准化,并转化为NCHW格式,代码如下:

void preprocess(const cv::Mat& img, const int height, const int width, std::vector<float> &input_data)
{
    if (img.empty()) {
        std::cerr << "图像为空!" << std::endl;
    }

    // BGR 转 RGB
    cv::Mat rgb_img;
    cv::cvtColor(img, rgb_img, cv::COLOR_BGR2RGB);

    // 归一化
    std::vector<float> mean = { 0.485f, 0.456f, 0.406f };
    std::vector<float> std = { 0.229f, 0.224f, 0.225f };
    cv::Mat normalized_img = normalize(rgb_img, mean, std);

    // resize + =>NCHW
    cv::Mat preprocess_img = cv::dnn::blobFromImage(
        normalized_img,                             // 原始BGR图像
        1.0,                             // 像素值归一化到0-1
        cv::Size(height, width),          // 目标尺寸224×224
        cv::Scalar(0), // 减去ImageNet均值(RGB顺序,swapRB=true时匹配)
        true,                            // BGR→RGB
        false,                           // 不裁剪
        CV_32F                           // 输出float32类型(适配模型输入)
    );

    memcpy(input_data.data(), preprocess_img.data, input_data.size() * sizeof(float));
 }

其中,归一化的标准和均值需要根据模型具体值修改。这里结合opencv中的cv::Mat作为图像数据的载体,也可以采用其他库。

3.运行推理

推理过程就是将预处理后的图像利用推理器进行推理,并得到推理结果。推理过程可以在GPU上,也可以在CPU上运行。推理过程相关代码如下:

void run(Predictor* predictor, 
    const std::vector<float>& input,const std::vector<int>& input_shape, 
    const std::vector<float>& scale_factor,const std::vector<int>& scale_factor_shape, 
    std::vector<float>* out_data)
{
    auto input_names = predictor->GetInputNames();

    auto image_handle = predictor->GetInputHandle(input_names[0]);
    image_handle->Reshape(input_shape);
    image_handle->CopyFromCpu(input.data());

    auto scale_factor_handle = predictor->GetInputHandle(input_names[1]);
    scale_factor_handle->Reshape(scale_factor_shape);
    scale_factor_handle->CopyFromCpu(scale_factor.data());

    predictor->Run();

    auto output_names = predictor->GetOutputNames();
    auto output_t = predictor->GetOutputHandle(output_names[0]);
    std::vector<int> output_shape = output_t->shape();
    int out_num = std::accumulate(output_shape.begin(), output_shape.end(), 1,
        std::multiplies<int>());

    out_data->resize(out_num);
    output_t->CopyToCpu(out_data->data());

}

三、测试结果

通过对不同环境下的一维码和二维码(包括QR码、DM码)进行测试,无论是低比度还是高反光都可以快速进行定位,如下图所示的各种复杂环境。


总结

本文介绍了利用c++加上paddle深度学习框架进行条码定位的过程,给出了图像预处理和推理的相关代码,并演示了复杂环境下的定位结果。实践表明,利用AI模型进行条码定位进行很高的可靠性,可以解决传统方法对于复杂环境无法定位的结果,大大提高定位的准确性和速度。

有需要完整代码的可以联系以下链接获取。

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐