2016/10/20

Create barcode using Zint static library

이전 글에서 작성한 대로 생성한 Zint 정적 라이브러리를 이용하여 바코드를 생성해 보았다.
Build Zint static library on windows

라이브러리는 정상적으로 동작을 하였다.
사용법은 설명 보다는 코드로 남기는 것이 이해가 쉬울 것 같아 코드로 남긴다.

struct zint_symbol *pZintSymbolStruct;

    // Zint symbol 생성
    pZintSymbolStruct = ZBarcode_Create();
    if (pZintSymbolStruct != nullptr)
    {
        TRACE("Symbol successfully created!\n");

        // 생성할 바코드 문자열. 최대 128자
        unsigned char szBuf[ZINT_TEXT_SIZE] = "created barcode by Zint\0";

        // 주어진 문자열로 바코드 생성.
        // 문자열 길이를 0으로 입력하면 입력된 문자열의 첫번째 Null 까지 Encode.
        ZBarcode_Encode(pZintSymbolStruct, szBuf, 0);

        // 생성한 바코드를 파일로 저장.
        // 바코드 타입을 설정하지 않으면 기본으로 Code 128이 설정된다.
        // Symbol 생성시 기본 출력 파일 이름은 out.png
        // 각도는 0, 90, 180, 270 를 입력할 수 있다.
        // 그 이외의 각도를 넘기면 예외가 발생한다.
        ZBarcode_Print(pZintSymbolStruct, 0);


        // Symbol 초기화
        ZBarcode_Clear(pZintSymbolStruct);
        // Barcode를 QRCode로 지정
        pZintSymbolStruct->symbology = BARCODE_QRCODE;
        // 출력 파일은 out2.png로 지정
        strcpy_s(pZintSymbolStruct->outfile, FILENAME_MAX, "out2.png");
        // 바코드로 생성할 문자열 설정
        strcpy_s((char*)szBuf, ZINT_TEXT_SIZE, "한글 바코드, 韓字!");
        // 인코딩과 파일 저장을 한번에 수행
        ZBarcode_Encode_and_Print(pZintSymbolStruct, szBuf, 0, 0);


        // Symbol 초기화
        ZBarcode_Clear(pZintSymbolStruct);
        pZintSymbolStruct->symbology = BARCODE_QRCODE;
        strcpy_s((char*)szBuf, ZINT_TEXT_SIZE, "메모리에 바코드 생성");
        // 바코드를 인코딩하여 메모리에 저장
        // 바코드는 pZintSymbolStruct->bitmap 에 저장
        ZBarcode_Encode_and_Buffer(pZintSymbolStruct, szBuf, 0, 270);

        // 메모리에 저장된 바코드 이미지를 이용하여 OpenCV Mat 생성
        cv::Mat matBarcode = cv::Mat(
            pZintSymbolStruct->bitmap_height
            , pZintSymbolStruct->bitmap_width
            , CV_8UC3
            , pZintSymbolStruct->bitmap);

        // 화면에 보여주기
        cv::namedWindow("Barcode");
        cv::imshow("Barcode", matBarcode);
    }

    // Symbol 삭제
    ZBarcode_Delete(pZintSymbolStruct);

zint_symbol 구조체에 여러 설정을 하여 바코드를 생성할 수 있다.
설정할 수 있는 항목은 여백, 배경색, 전경색, 테두리 등을 설정할 수 있다.
자세한 설정 방법은 Zint 매뉴얼(http://www.zint.org.uk/Manual.aspx?type=p&page=1)에 설명되어 있다.

2016/10/19

Build Zint static library on windows

ZXing 자바 버전에는 바코드를 생성할 수 있지만 cpp 버전인 ZXing cpp에는 바코드 생성 기능이 포함되저 있지 않았다. 그래서 바코드를 생성할 수 있는 라이브러리를 찾다가 발견한 것이 ZInt 이다.
CMake를 지원하여 쉽게 빌드가 될 줄 알았는데 종속성때문에 쉽게 되지 않았다. ZInt를 빌드하려면 zlib와 libpng가 필요한데 Zint에 포함되어 있지 않아 직접 만들어서 구성을 해 줘야 한다. 직접 빌드하여 ZInt에 포함되어 있는 프로젝트를 빌드해보려 했지만 여러차례 실패하고 직접 프로젝트를 만들어 정적 라이브러리를 생성했다.
잊지 않기 위해 빌드 절차를 기록 했다.

우선 필요한 라이브러리인 zlib와 libpng를 빌드 한다.
CMake를 이용하여 빌드 환경을 구성 하였다.
zlib는 CMAKE_INSTALL_PREFIX만 설정하고 빌드 하였다.
빌드하면 동적 라이브러와 정적 라이브러리를 얻을 수 있다.

libpng의 경우 빌드해 놓은 zlib 정보를 설정해 주어야 한다.
아래 항목에 대하여 입력을 해 준다.
CMAKE_INSTALL_PREFIX: 설치 경로
ZLIB_INCLUDE_DIR: zlib CMAKE_INSTALL_PREFIX/include
ZLIB_LIBRARY_DEBUG: zlib project path/Debug/zlibstaticd.lib
ZLIB_LIBRARY_RELEASE: zlib project path/Release/zlibstatic.lib

이제 본격적으로 ZInt를 빌드할 차례이다.
먼저 Visual Studio에서 정적 라이브러리 프로젝트를 생성하고 ZInt 에 포함되어있는 backend 폴더의 소스를 생성한 프로젝트에 모두 추가한다.
그리고 Preprocessor 설정에 Zint 라이브러리 버전을 아래와 같이 설정해 주어야 한다.
Preprocessor definitions
ZINT_VERSION="2.4.3.0"

다음으로 추가 포함 경로에 zlib와 libpng 의 설치 경로의 include 폴더를 지정한다.
zlib's CMAKE_INSTALL_PREFIX\include
libpng's CMAKE_INSTALL_PREFIX\include

다음, 추가 라이브러리 경로를 Debug와 Release에 맞게 설정 한다.
Additional Library Directories
Debug
zlib project path\Debug
libpng project path\Debug

Release
zlib project path\Release
libpng project path\Release

마지막으로 추가 종속성 라이브러리를 설정 한다.
Librarian -> Additional Dependencies
Debug
zlibstaticd.lib, libpng16_staticd.lib

Release
zlibstatic.lib, libpng16_static.lib

이제 구성을 다 마쳤다. 빌드만 하면 된다.
Visual Studio 2015버전으로 빌드를 했는데 아무런 에러없이 정적 라이브러리를 얻을 수 있었다.
다음에는 만들어진 라이브러리를 이용해서 바코드를 만들어 보겠다.

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());
}

2016/10/09

Memory leak problem with OpenCV 3.1 custom build

OpenCV 빌드 후 라이브러리를 테스트 하는 도중 Debug 빌드 라이브러리의 메모리 누스가 포착 되었다.
오래전 2.2 버전을 빌드하여 테스트 할 때에도 비슷한 문제가 있었는데 동일하지는 않지만 유사한 것 같다.
Release 버전으로 테스트한 결과 문제가 없었다. 혹시나 해서 OpenCV.org에서 배포하는 배포(Release 버전 밖에 없는) 버전으로 테스트 해 보았는데 문제가 없었다.
공식 배포 버전은 Release 버전밖에 없어 Debug 모드에서의 테스트는 할 수 없었고 공식배포건 빌드한 버전이던 Release 버전에는 문제가 없었다.

Test OpenCV 3.1 with VTK 7.0 in Visual Studio 2015

지난 포스팅에서 설명한 OpenCV 3.1 빌드 후 생성 된 라이브러리는 테스트 해 보았다.

Build OpenCV 3.1 with VTK 7.0 in Visual Studio 2015

OpenCV 테스트는 opencv_world 라이브러리만 사용하면 되었고 VTK를 사용한 opencv_viz를 사용하려면 VTK include 파일과 opencv_world 가 아닌 개별 빌드한 라이브러리를 사용해야만 했다.

Hello OpenCV Viz

이전 포스트에서 테스트했던 OpenCV viz 소스가 문제없이 동작을 하였다.

+ 2016/10/12
opencv_viz 모듈이 opencv_core 모듈을 참조하는 것은 빌드할 때 opencv_core 라이브러리를 참조하였기때문이였다. dll 수를 줄이기 위해 opencv_world를 사용할 수 있도록 opencv_viz 빌들할 때 참조 라이브러리를 opencv_world로 변경을 하니 opencv_viz.dll 과 opencv_world.dll 파일만 있으면 opencv_viz 관련 함수들이 동작을 하였다.

2016/10/07

Build OpenCV 3.1 with VTK 7.0 in Visual Studio 2015

Build OpenCV 3.1 with VTK 7.0 in Visual Studio 2015

Visual Stuido 2015 버전에서 OpenCV 3.1과 VTK 7.0을 빌드해 보았다.

주인공인 OpenCV 3.1와 VTK 7.0 가 준비가 되어야 겠고 빌드 구성을 위해 CMake가 필요하다.
CMake 는 3.6.2 버전을 사용하였다.

우선 VTK를 OpenCV 빌드에 사용할 수 있도록 빌드를 해야 한다. 빌드를 신속하게 하기위해 필요 없는 것으 빌드하지 않도록 하였다. 그리고 이때 주의 할 사항은 OpenGL설정이다. VTK 7.0에서는 Rendering Backend가 OpenGL2 로 새롭게 작성이 되었고 이 것이 기본값으로 되어있다.
하지만 OpenCV 에서는 이를 지원하지 않고 이전 버전의 OpenGL을 사용해야 한다. 그래서 Rendering Backend 설정과 OpenGL 설정을 변경해 주어야 한다. 아래는 VTK를 빌드할 때 구성한 내용이다.

Srouce: E:/DevWork/OpenCV/VTK-7.0.0_x64
Build:  E:/DevWork/OpenCV/VTK-7.0.0_x64/VS2015_x64

Configuration options
  BUILD_EXAMPLES                   uncheck
  BUILD_SHARED_LIBS                uncheck
  BUILD_TESTING                    uncheck
  Module_vtkRenderingOpenGL        check
  Module_vtkRenderingContextOpenGL check
  Module_vtkRenderingVolumeOpenGL  check
  VTK_RENDERING_BACKEND            OpenGL
  CMAKE_INSTALL_PREFIX             BuildPath/install

Build projects
  ALL_BUILD with debug configuration
  INSTALL with release configuration

VTK 를 아무 문제없이 빌드를 했다면 이제 OpenCV를 빌드할 차례이다.
빠른 빌드를 위해 필요없는 항목은 제거를 했지만 간단한 테스트를 위해 Test 프로젝트를 빌드를 수행하였다.

Source: E:/DevWork/OpenCV/opencv_v3.1.0/sources
Build:  E:/DevWork/OpenCV/opencv_v3.1.0/VS2015_x64_vtk

Configuration options
  BUILD_DOCS            uncheck
  BUILD_EXAMPLES        uncheck
  BUILD_TESTS           check
  VTK_DIR               E:/DevWork/OpenCV/VTK-7.0.0_x64/VS2015_x64
  WITH_OPENGL           check
  WITH_OPENMP           check
 
  BUILD_opencv_python2  uncheck
  BUILD_opencv_python3  uncheck
  BUILD_opencv_viz      check

Build projects
  ALL_BUILD with debug configuration
  INSTALL with release configuration

위 설정으로 Configure를 마치면 로그화면에서 아래와 같이 VTK가 포함이 된 것을 확인 할 수 있다.
VTK support:                 YES (ver 7.0.0)

구성 완료후 빌드를 하여 bin 폴더의 test 파일들 중 opencv_text_viz.exe를 실행시켜 정상 동작을 확인 하였다.
마지막으로 opencv_world를 만들기 위해서 아래 설정을 변경하고 다시 빌드하였다.
viz와 world를 함께 빌드하면 문제가 발생을 하여 우선 viz를 제거하고 빌드하였다.
이 라이브러리를 정상적으로 사용이 가능한지는 추후 테스트를 해 봐야 알 수 있을 것 같다.

Configuration options
  BUILD_opencv_viz      uncheck
  BUILD_opencv_world    check
 
Build projects
  ALL_BUILD with debug & release configuration

Build 경로 아래의 install 폴더에 라이브러리를 사용하기 위한 파일들이 있다. 디버그용이 필요한 경우 Build 경로의 bin 폴더와 lib 폴더의 파일들을 이용하면 된다. 헤더파일은 install 폴더에 포함되어 있는 include 파일을 이용하면 된다.

라이브러리는 빌드 하였고 이제 테스트를 해 볼 차례이다.

2016/10/06

VTK Textbook and User Guide

VTK Textbook 과 User Guide가 PDF 버전으로 공개가 되었다.
내 기억으로는 구매를 인쇄본을 구매해야만 얻을 수 있었는데 이제 PDF 버전은 무료로 공개된 것 같다.


VTK Textbook
http://www.vtk.org/vtk-textbook/
http://www.kitware.com/products/books/VTKTextbook.pdf

VTK User Guide 11th
http://www.vtk.org/vtk-users-guide/
http://www.kitware.com/products/books/VTKUsersGuide.pdf

2016/10/05

Using VTK with MFC Project

VTK 버전 7.0이 나와서 새로 빌드도 해 보고 다시 공부좀 해볼까 하여 오랜만에 VTK를 빌드해 보았다.
아주 오랜만에 다시 해 보는 것이고 이전 기록이 많지않아 동일한 시행착오를 피할 수 없었다.
빌드를 무사히 마치고 Visual Studio 에서 테스트 하는데 더 큰 걸림돌이 있었다.
검색 결과 CMake를 이용하지 않는 경우 초기화(?) 코드가 필요 하였다.
게다가 버전 7은 버전 6에서 변경된 사항이 있어 동일한 코드로 초기화가 되지 않았다.
추후 동일한 문제로 고생하지 않기 위해 기록을 남긴다.


For VTK 6.x
다른 헤더파일을 포함하기 전에 먼저 "vtkAutoInit.h"를 포함하고 일부 모듈을 초기화 해 주어야 한다.

#include "vtkAutoInit.h"
VTK_MODULE_INIT(vtkInteractionStyle);
VTK_MODULE_INIT(vtkRenderingFreeType);
VTK_MODULE_INIT(vtkRenderingFreeTypeOpenGL);
VTK_MODULE_INIT(vtkRenderingOpenGL);

#define vtkRenderingCore_AUTOINIT 4(vtkInteractionStyle,vtkRenderingFreeType,vtkRenderingFreeTypeOpenGL,vtkRenderingOpenGL)
#define vtkRenderingVolume_AUTOINIT 1(vtkRenderingVolumeOpenGL)
http://www.vtk.org/Wiki/VTK/VTK_6_Migration/Factories_now_require_defines


For VTK 7.x
VTK 7.x의 경우 OpenGL이 OpenGL2로 새롭게 바뀌었으며 빌드할 때 별도의 설정을 하지 않은 경우 OpenGL2로 설정이 되기때문에 VTK 6.x 에서 초기에 수행한 OpenGL 설정을 OpenGL2 로 변경을 해 주어야 한다. 그리고 vtkRenderingFreeTypeOpenGL 은 삭제되었다 한다.

#include "vtkAutoInit.h"
VTK_MODULE_INIT(vtkInteractionStyle);
VTK_MODULE_INIT(vtkRenderingFreeType);
VTK_MODULE_INIT(vtkRenderingOpenGL2);

#define vtkRenderingCore_AUTOINIT 3(vtkInteractionStyle,vtkRenderingFreeType,vtkRenderingOpenGL2)
http://www.visitusers.org/index.php?title=VTK_7.1_Upgrade

2016/10/04

wofstream을 이용하여 한글 출력하기

wchar_t 문자열을 그대로 텍스트 파일에 출력하기위해 wofstream 객체에 << 연산자를 이용하였다. 잘 되는가 싶었는데 한글을 포함하여 기대대로 동작을 하지 않았다. 그래서 방법을 찾아보니 locale 설정을 해 주어야 한다고 한다. 전역으로 설정하던지 아니면 wofstream을 생성하고 해당 객체에 대해서 imbue함수를 이용하여 locale을 설정해 주면 된다.
 std::locale::global(std::locale("Korean")); // 방법 #1
 std::locale::global(std::locale("")); // 방법 #2
 wofstream fsOut;
 fsOut.imbue(std::locale("Korean")); // 방법 #3
 fsOut.imbue(std::locale("")); // 방법 #4
 fsOut.open( L"Output File Path", std::ios::out );

Write and read unicode test using wfstream

fstream을 이용하여 유니코드 문자를 저장하려 시도하였다. 쉽게 "w"만을 붙여서 wofstream을 이용하고 wchar_t 또는 wstring을 출력만 하면 될 줄 알았으나 기대대로 동작을 하지 않았다. 문자열 인코딩 문제등등 여러가지 복잡한 문제가 있었다. 여러 정보를 취합해 나중에 도움이 될 수 있도록 코드를 남겼다.

class Unicodecvt : public std::codecvt<wchar_t, char, mbstate_t>
{
protected:
 virtual bool do_always_noconv() const
 {
  return true;
 }
};

// Writting
std::wofstream fOut(L"D:\\test.txt", std::ios_base::binary);
fOut.imbue(std::locale(std::locale(""), ::new Unicodecvt));
fOut << wchar_t(0xFEFF);  // write BOM (UTF-16LE)
fOut << L"유니코드 출력 테스트: " << 12345 << std::endl;
fOut.close();

// Reading
std::wifstream fIn(L"D:\\test.txt", std::ios_base::binary);
fIn.imbue(std::locale(std::locale(""), ::new Unicodecvt));
if ( fIn.is_open() )
{
 fIn.seekg(2); // Skip BOM
 while ( !fIn.eof() )
 {
  wchar_t wszBuf[1024] = { 0, };
  fIn.getline( (wchar_t*)wszBuf, _countof(wszBuf));
 }
}
fIn.close();


참조 문서
https://golbenge.wordpress.com/2009/12/24/stl을-이용한-unicode-텍스트-파일-출력 http://saneh.tistory.com/entry/STL-유니코드-저장읽기