依赖库

  • ZXing C++ 库zxing-cppgit clone https://github.com/nu-book/zxing-cpp.git

  • OpenCV(用于图像加载和处理)

1. 多码检测

一张图像中包含多个条码(一维码、二维码等),并且需要检测每个码的类型、区域和内容,可以使用 ZXing 的 多码检测功能。ZXing 的 C++ 版本(zxing-cpp)支持多码检测,但需要结合 OpenCV 或其他图像处理库来实现。

实现代码

#include <iostream>
#include <zxing/BarcodeFormat.h>
#include <zxing/MultiFormatReader.h>
#include <zxing/DecodeHints.h>
#include <zxing/GenericLuminanceSource.h>
#include <zxing/HybridBinarizer.h>
#include <zxing/BinaryBitmap.h>
#include <zxing/Result.h>
#include <zxing/ResultPoint.h>
#include <opencv2/opencv.hpp>

using namespace zxing;
using namespace cv;

// 将 OpenCV 的 Mat 转换为 ZXing 的 LuminanceSource
std::shared_ptr<LuminanceSource> MatToLuminanceSource(const Mat& image) {
    int width = image.cols;
    int height = image.rows;
    std::vector<uint8_t> buffer(width * height);

    // 将图像转换为灰度数据
    if (image.channels() == 3) {
        Mat gray;
        cvtColor(image, gray, COLOR_BGR2GRAY);
        memcpy(buffer.data(), gray.data, width * height);
    } else if (image.channels() == 1) {
        memcpy(buffer.data(), image.data, width * height);
    } else {
        throw std::runtime_error("Unsupported image format");
    }

    return std::make_shared<GenericLuminanceSource>(width, height, buffer.data(), width, 0, 0, width, height);
}

int main() {
    // 加载图像
    Mat image = imread("path/to/your/image.png");
    if (image.empty()) {
        std::cerr << "Failed to load image!" << std::endl;
        return -1;
    }

    // 将图像转换为 ZXing 的 LuminanceSource
    auto source = MatToLuminanceSource(image);

    // 创建 BinaryBitmap
    auto binarizer = std::make_shared<HybridBinarizer>(source);
    auto bitmap = std::make_shared<BinaryBitmap>(binarizer);

    // 设置解码选项
    DecodeHints hints;
    hints.setTryHarder(true); // 尝试更复杂的解码
    hints.setFormats(BarcodeFormat::AllFormats); // 支持所有条码格式

    // 创建 MultiFormatReader
    MultiFormatReader reader;

    // 存储检测到的条码结果
    std::vector<Ref<Result>> results;

    try {
        // 解码图像中的所有条码
        results = reader.decodeMultiple(bitmap, hints);

        // 输出每个条码的信息
        for (const auto& result : results) {
            std::cout << "Code Type: " << BarcodeFormat::barcodeFormatNames[result->getBarcodeFormat()] << std::endl;
            std::cout << "Code Content: " << result->getText()->getText() << std::endl;

            // 获取条码的区域
            std::vector<Ref<ResultPoint>> points = result->getResultPoints();
            if (!points.empty()) {
                std::cout << "Code Region: " << std::endl;
                for (const auto& point : points) {
                    std::cout << "(" << point->getX() << ", " << point->getY() << ")" << std::endl;
                }
            }
            std::cout << "-------------------------" << std::endl;
        }

    } catch (const std::exception& e) {
        std::cerr << "Failed to decode: " << e.what() << std::endl;
    }

    return 0;
}

代码说明

  1. MatToLuminanceSource:

    • 将 OpenCV 的 Mat 图像转换为 ZXing 的 LuminanceSource,以便 ZXing 可以处理。

    • 支持灰度图像和三通道彩色图像。

  2. DecodeHints:

    • 设置解码选项,例如是否尝试更复杂的解码(TryHarder),以及支持的条码格式(AllFormats 表示支持所有格式)。

  3. MultiFormatReader:

    • 用于解码图像中的条码,支持多种条码格式。

  4. decodeMultiple:

    • 检测图像中的所有条码,并返回一个包含所有结果的向量。

  5. Result:

    • 存储解码结果,包括条码类型、内容和区域。

  6. ResultPoints:

    • 获取条码的区域信息,通常返回条码的角点坐标。

输出示例

如果图像中包含多个条码,程序会输出类似以下内容:

Code Type: QR_CODE
Code Content: https://example.com
Code Region:
(100, 100)
(200, 100)
(200, 200)
(100, 200)
-------------------------
Code Type: CODE_128
Code Content: 123456789
Code Region:
(300, 150)
(400, 150)
(400, 250)
(300, 250)
-------------------------

注意事项

  • 确保图像质量足够高,否则可能无法正确解码。

  • 如果图像中有多个条码,ZXing 的 decodeMultiple 方法会尝试检测所有条码。

  • 如果需要处理更复杂的图像(如旋转、畸变等),可以结合 OpenCV 进行预处理。

通过以上方法,你可以在 C++ 中使用 ZXing 检测图像中的所有条码,并获取它们的类型、区域和内容。


本站由 困困鱼 使用 Stellar 创建。