2016/10/17

Reading barcode with zxing-cpp and OpenCV

zxing(https://github.com/zxing/zxing)을 이용하여 바코드 읽기를 테스트 해 보았다.
zxing은 원래 java로 만들어진 라이브러리인데 다양한 언어로 지원을 하고 있었다. C++의 경우 초기부터 지원을 해 오다가 zxing이 java 이외의 언어에 대한 지원이 소극적이더니 결국 C++은 더이상 지원을 하지 않고 있다. 다행이 C++을 지원하는 third-party projects(zxing cpp: https://github.com/glassechidna/zxing-cpp) 가 있어서 C++에서 쉽게 ZXing을 사용할 수 있었다.

ZXing cpp 빌드는 쉽게 하였는데 OpenCV 데이터를 ZXing에 넘기는게 문제였다. 컬러채널 및 흑백채널데이터를 넘겨도 ZXing에서 인식을 하지 못하였다.

인터넷을 검색하던 중 OpenCV의 이미지인 Mat 객체를 이용한 소스가 공개된 것을 찾았다.
https://github.com/geduino-foundation/zxing-cpp
MatSource는 LuminanceSource를 상속받아 getRow와 getMatrix 함수가 구현되어 있다. cv::Mat 객체로 생성을 하는 생성자가 있어 쉽게 객체를 생성할 수 있었다. 단 MatSource를 생성할 때 흑백 영상을 이용해야 한다.

아래 코드는 MatSource를 이용한 바코드 인식 코드 이다. OpenCV 예제소스는 QRCode만 인식하도록 되어 있어서 기본 코드에 있는 코드를 사용해 보았다.

source = MatSource::create(matGray);
 
vector<Ref<Result>>& vResult
string strResult;
try
{
    Ref<Binarizer> binarizer;
    if (bHybrid) 
    {
        binarizer = new HybridBinarizer(source);
    }
    else
    {
        binarizer = new GlobalHistogramBinarizer(source);
    }

    DecodeHints hints(DecodeHints::DEFAULT_HINT);
    hints.setTryHarder(false);
    Ref<BinaryBitmap> binary(new BinaryBitmap(binarizer));
    if (bSearchMulti)
    {
        MultiFormatReader delegate;
        GenericMultipleBarcodeReader reader(delegate);
        vResult = reader.decodeMultiple(binary, hints);
    }
    else
    {
        Ref<Reader> reader(new MultiFormatReader);
        vResult.push_back(reader->decode(binary, hints));
    }
}
catch (const ReaderException& e) 
{
    strResult = "zxing::ReaderException: " + string(e.what());
}
catch (const zxing::IllegalArgumentException& e) 
{
    strResult = "zxing::IllegalArgumentException: " + string(e.what());
}
catch (const zxing::Exception& e) 
{
    strResult = "zxing::Exception: " + string(e.what());
}
catch (const std::exception& e) 
{
    strResult = "std::exception: " + string(e.what());
}

6 comments :

  1. 전체 소스 좀 올려주실수 있을까요?

    ReplyDelete
    Replies
    1. 죄송합니다. 오래된 내용이라 현재는 코드가 없네요.
      참고로 말씀드리면 예제 코드의 첫 줄에있는 matGray가 인식하기 위한 바코드 이미지 입니다. 인식을 원하는 바코드 이미지를 읽어들이고 흑백 영상으로 변경을 하여 MatSource를 생성하시면 될 것 같습니다.

      Delete

    2. opencv에서 읽은 데이터를 zxing에 넘길 때 왜 문제가 발생하는건지
      그래서 Matsource가 어떠한 역할을 해서 해결이 가능하게 되는건지
      에 대해서 쉽게 설명 해주실수 있으신가요? 부탁드립니다.

      Delete
    3. 어떤 문제가 발생하는지도 모르는데 왜 문제가 발생하는지는 도저히 설명드릴 방법이 없네요. MatSource는 OpenCV 이미지 형식인 Mat 또는 IplImage를 ZXing에서 사용될 수 있도록 데이터과 관련 함수들을 정의해 놓은 클래스 입니다.

      Delete
  2. datamatrix 바코드를 혹시 테스트 해보신 적 있으신가요?

    ReplyDelete
  3. Hi there, sorry for bringing up an old thread, but can I ask have you solve your issue? How was it done?

    ReplyDelete