2017/10/23

Reading barcode with zxing-cpp and OpenCV Volume 2

1년전쯤 작성한 글인데 ZXing-cpp 와 OpenCV를 이용한 바코드 인식 글(https://goo.gl/kRtaYn)을 올렸었는데 관련 댓글이 달리고 다른 활용처가 있어서 다시 시도를 해 보았다.
물론 한번에 되지는 않았다.

ZXing-cpp 빌드는 문제가 없었으나 이를 사용하는경우 아래와 같은 링크 에러가 발생하였다.
error LNK2005: "public: static unsigned int const zxing::DecodeHints::CHARACTER_SET" (?CHARACTER_SET@DecodeHints@zxing@@2IB) already defined in xxx.obj

인터넷 검색을 통해 해결책(https://goo.gl/WkEEcY)을 찾았다.
문제는 Visual C++ 컴파일러만 발생한 것으로 문제가 발생한 부분을 아래와 같이 수정을 하면 해결이 되었다.

Old code:

DecodeHints.h:
static const DecodeHintType CHARACTER_SET = 1 << 30;
DecodeHints.cpp:
const DecodeHintType DecodeHints::CHARACTER_SET;

has been replaced by:

DecodeHints.h:
static const DecodeHintType CHARACTER_SET;
DecodeHints.cpp:
const DecodeHintType DecodeHints::CHARACTER_SET = 1 << 30;

그리고 이전 코드에서는 컴파일에 문제가 있어서 최신 ZXing에 포함되어 있는 opencv cli 코드(zxing-cpp-master\opencv-cli\src\main.cpp)를 이용하여 테스트 해 보았다.

컴파일및 링크는 문제가 없었으나 인식률은 그리 좋아 보이지 않았다.
물론 ZXing을 얼마나 이해하고 잘 쓰는지가 문제가 될 수 있어 좀 더 분석하고 파고들어봐야 할 것 같다.

아래 코드는 테스트에 사용한 코드 이다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
cv::String strFile( CStringA(dlgFile.GetPathName()) );
cv::Mat matImage = cv::imread(strFile);
 
cv::Mat matGray;
cv::cvtColor( matImage, matGray, CV_RGB2GRAY );
 
Ref<LuminanceSource> source = MatSource::create(matGray);
  
bool bHybrid = true;
string strResult;
try
{
 // Create luminance  source
 Ref<LuminanceSource> source = MatSource::create(matGray);
 
 // Search for QR code
 Ref<Reader> reader;
 
 if (true)
 {
  reader.reset(new MultiFormatReader);
 }
 else
 {
  reader.reset(new QRCodeReader);
 }
 
 Ref<Binarizer> binarizer(new GlobalHistogramBinarizer(source));
 Ref<BinaryBitmap> bitmap(new BinaryBitmap(binarizer));
 Ref<Result> result(reader->decode(bitmap, DecodeHints(DecodeHints::DEFAULT_HINT)));
 
 // Get result point count
 int resultPointCount = result->getResultPoints()->size();
 
 for (int j = 0; j < resultPointCount; j++)
 {
  // Draw circle
  circle(matImage
   , CvPoint(result->getResultPoints()[j]->getX(), result->getResultPoints()[j]->getY())
   , 10, cv::Scalar( 110, 220, 0 ), 2);
 }
 
 // Draw boundary on image
 if (resultPointCount > 1)
 {
  for (int j = 0; j < resultPointCount; j++)
  {
   // Get start result point
   Ref<ResultPoint> previousResultPoint = (j > 0) ? result->getResultPoints()[j - 1] : result->getResultPoints()[resultPointCount - 1];
 
   // Draw line
   //line(matImage, toCvPoint(previousResultPoint), toCvPoint(result->getResultPoints()[j]), cv::Scalar( 110, 220, 0 ),  2, 8 );
   line(matImage, CvPoint(previousResultPoint->getX(), previousResultPoint->getY())
    , CvPoint(result->getResultPoints()[j]->getX(), result->getResultPoints()[j]->getY())
    , cv::Scalar( 110, 220, 0 ), 2, 8 );
 
   // Update previous point
   previousResultPoint = result->getResultPoints()[j];
  }
 }
 
 if (resultPointCount > 0)
 {
  TRACE("Found Barcode : %s\n", result->getText()->getText().c_str());
  // Draw text
  putText(matImage, result->getText()->getText()
   , CvPoint(result->getResultPoints()[0]->getX(), result->getResultPoints()[0]->getY())
   , cv::FONT_HERSHEY_PLAIN, 1, cv::Scalar( 110, 220, 0 ));
 }
 
 // Show captured image
 cv::namedWindow( "ZXing", cv::WINDOW_AUTOSIZE );
 cv::imshow("ZXing", matImage);
}
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());
}
 
AfxMessageBox(CString(strResult.c_str()));

No comments :

Post a Comment