C++利用OpenCV识别二维码QRCode

引子

项目需要用到C++进行二维码识别,虽然手机上随便扫码就可以轻易识别出来,但是到了电脑上可就没有那么方便了。
我要做的是能够一下子把一张图片上的几十个二维码一下子识别出来,如果成功的话,那岂不是比用手机一张张扫码快许多啊。当然现在已经成功了,现在把配置过程记录一下。
我查阅了一大堆资料,识别二维码的方法有很多,基本上分为用zbar和zxing两种,但是对效果来看,zxing的识别更胜一筹,而且zbar已经停止更新了。那么,作为9012年的萌薪,当然是选择效果强大的zxing了啊。

方法一:zxing

  1. 原理
    简单来讲,它先找二维码的三个角点,如果找到才会进行解码。
  2. 首先
    我们需要一份包装包:zxing的安装库,这是C++版本的,将它下载到你的电脑上
  3. 编译安装
    C++利用OpenCV识别二维码QRCode_第1张图片建立一个build的文件夹,编译,安装,命令行如下。
mkdir build
cd build
cmake ..
make
make install

这样就ok了。需要注意的是,CMakeLists.txt里面有OpenCV的依赖选项,所以最好提前配置好OpenCV。
4. 安装完成
如果你成功编译了,那么在build文件夹里面会有一个叫做libzxing.a文件,这就是你编译好的静态链接库,后面你想调用zxing的话就得把这个文件导进去。
5. 识别二维码
这里我编写了一个简单的函数,思想是,先用OpenCV imread函数读取图片,然后将其装换为灰度图,然后调用zxing的解码函数得到识别结果进行输出。
首先准备好CmakeLists.txt这个很基本,但很重要。

cmake_minimum_required (VERSION 3.1)
# Enable C++11
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED TRUE)
# 调试模式
set(CMAKE_BUILD_TYPE "Debug")
project (newPipeLocation)
#这是我自己的OpenCV安装路径
set(OpenCV_DIR /usr/local)
# zxing
set(ZXing_DIR /usr/local)
find_package(OpenCV 4 REQUIRED)

include_directories(
    ${OpenCV_DIR}/include
    ${ZXing_DIR}/include/zxing
    /home/wwh/Downloads/zxing-cpp/core/src
    /home/wwh/Downloads/zxing-cpp/opencv/src
    )
add_executable(main main.cpp)
# 这里的libzxing.a很重要
target_link_libraries(main 
    ${OpenCV_LIBS}
    /home/w/Downloads/zxing-cpp/build/libzxing.a
    )

主函数如下:(这个代码的好处是如果检测不到二维码,也可以输出一条显示信息,而不会使得程序崩溃)

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

using namespace std;
using namespace cv;
using namespace zxing;
using namespace zxing::qrcode;

void displayPicture(const string& winName, cv::Mat inputImage, int waitTime)
{
	// 暂时展示图片
	cv::namedWindow(winName, WINDOW_NORMAL);
	cv::resizeWindow(winName, 800, 800);
	cv::imshow(winName, inputImage);
	cv::waitKey(waitTime);
	cv::destroyAllWindows();
}

void help()
{
    cout<< "Usage:"<<endl;
    cout<< "cvtColor(image, imageHsv, COLOR_BGR2HSV);" <<endl;
    cout<< "cv::inRange(imageHsv, Scalar(35, 43, 46), Scalar(77, 255, 255), dstHsv);" <<endl;
    cout << "HSV色域设置参考:" << endl;
    cout << "Blue: min: Scalar(100, 43, 46); max: Scalar(124, 255, 255)" << endl;
    cout << "Green: min: Scalar(35, 43, 46); max: Scalar(77, 255, 255)" << endl;
    cout << "White: min: Scalar(0, 0, 221); max: Scalar(180, 30, 255)" << endl;
}

int main()
{
    string inputPathDir = "/home/wwh/Documents/myproject/newPipeLocation/test_images/";
    string imagePath = inputPathDir + "qr02.png";
    const string myWinName = "Show Image";
    cv::Mat image = cv::imread(imagePath);
    // cv::resize(image, image, Size(115, 100));
    // displayPicture("raw image", image, 1000);
    cv::Mat matGray;
    cv::cvtColor(image, matGray, COLOR_BGR2GRAY);

    // 进行尝试
    try
    {
        zxing::Ref<zxing::LuminanceSource> source = MatSource::create(matGray);
        // int width = source->getWidth();
	    // int height = source->getHeight();
        // fprintf(stderr, "image width: %d, height: %d\n", width, height);
        zxing::Ref<zxing::Reader> reader;
        reader.reset(new zxing::qrcode::QRCodeReader);
        zxing::Ref<zxing::Binarizer> binarizer(new zxing::GlobalHistogramBinarizer(source));
        zxing::Ref<zxing::BinaryBitmap> bitmap(new zxing::BinaryBitmap(binarizer));
        zxing::Ref<zxing::Result> result(reader -> decode(bitmap, zxing::DecodeHints(zxing::DecodeHints::QR_CODE_HINT)));
        std::string str = result -> getText() -> getText();
        fprintf(stderr, "recognization result: %s\n", str.c_str());
    }
    catch(const ReaderException& e)
    {
        cerr << e.what() << ", no QRCode, ignored" << endl;
    }
    displayPicture("en", matGray, 1000);
    return 0;
}

方法二:使用OpenCV自带的功能

我发现OpenCV4中已经集成了二维码解码的程序了,后面有时间再进行补充。

参考文献(大多数好像都没啥用就不放了)

你可能感兴趣的:(个人学习)