OpenCV 3.2 버전부터 FreeType 모듈을 지원합니다. FreeType 모듈은 말 그대로 OpenCV에서 Freetype 라이브러리를 활용할 수 있게 도와주는 클래스이며, 이를 이용하면 영상에 다양한 폰트의 영문 및 한글을 적을 수 있습니다. 아래 그림은 lenna 영상에 바탕체 글꼴을 이용하여 영문과 한글 문자열을 출력한 예제입니다.



Freetype 모듈은 OpenCV Extra module에 정의되어 있기 때문에 opencv_contrib 소스 코드를 함께 빌드해야 사용할 수 있습니다. 그런데 Freetype 모듈은 opencv_contrib 소스 코드를 가지고 있다고 해서 자동으로 빌드가 되는 것이 아니라, Freetype과 HarfBuzz 라는 이름의 외부 라이브러리를 미리 빌드하고 설정해두어야 만들어집니다. 이 포스트에서는 OpenCV에서 Freetype 모듈을 빌드하는 방법과 실제로 사용하는 방법을 설명합니다. 본문의 순서는 다음과 같습니다.


(1) Freetype 라이브러리 빌드하기
(2) HarfBuzz 라이브러리 빌드하기
(3) Freetype 모듈을 포함한 OpenCV 라이브러리 빌드하기
(4) OpenCV에서 Freetype 모듈 사용하기


(1) Freetype 라이브러리 빌드하기


"FreeType is a freely available software library to render fonts."
Freetype은 폰트를 렌더링할 수 있는 소프트웨어 라이브러리 입니다. 즉, 폰트 파일을 해석하여 프로그램에서 사용할 수 있게 도와줍니다. Freetype 라이브러리의 홈페이지는 https://www.freetype.org/ 이고, 아래 링크에서 다양한 버전의 Freetype 소스 코드를 다운로드 받을 수 있습니다.


https://download.savannah.gnu.org/releases/freetype/


여러가지 버전 중에서 여기서 사용할 freetype 버전은 2.8.1 입니다. 현재 Freetype 최신 버전은 2.9 입니다만 2.9 버전 소개가 new 'minor' series 라고 되어 있는 것이 조금 찝찝해서 그 다음 최신 버전인 2.8.1을 사용했습니다. 아마도 리눅스 커널 버전처럼 홀수와 짝수를 구분하는 것과 같은 맥락일까요? 여하튼 위 링크에서 freetype-2.8.1.tar.bz2 파일을 다운로드 받으시면 됩니다.

일단 freetype 소스 코드를 다운로드 받았으면 빌드 작업을 수행하여 lib 파일을 생성해야 합니다. 이를 위해 폴더 구조를 다음과 같이 만들었습니다.


C:\freetype\build
           \freetype-2.8.1


위의 폴더 구조에서 freetype-2.8.1 폴더는 freetype-2.8.1.tar.bz2 압축을 풀면서 만들어진 폴더이고, build 폴더는 빌드 작업을 위해 직접 만든 폴더입니다. OpenCV 라이브러리를 빌드할 때와 마찬가지로 freetype 소스를 빌드하기 위해서는 Visual Studio 2017 솔루션 파일을 생성해야 합니다. 이 작업을 CMake GUI 버전 프로그램을 이용할 수도 있지만, 여기서는 좀 더 간단하게 command line 명령어를 사용하겠습니다. 일단 도스창(command window)을 실행한 후 C:\freetype\build 폴더로 이동합니다. 그리고 이 폴더에서 다음 명령어를 입력합니다. (CMake 폴더가 시스템 패스에 설정되어 있어야 합니다.)


cmake -DWITH_ZLIB=OFF -DWITH_BZip2=OFF -DWITH_PNG=OFF -G "Visual Studio 15 2017 Win64" ..\freetype-2.8.1



위 명령어에서 WITH_ZLIB, WITH_BZip2, WITH_PNG 항목을 OFF로 설정하지 않으면 나중에 OpenCV 라이브러리의 Freetype 모듈을 빌드할 때 에러가 발생합니다. 그러므로 위와 같이 명령어를 입력하여 freetype.sln 파일을 생성하였습니다. 이제 Visual Studio 2017에서 freetype.sln 파일을 불러와서 빌드 작업을 수행합니다.

빌드 작업은 Debug와 Release 모드로 각각 수행하고, 전체 솔루션 빌드를 하고 난 후에는 INSTALL 프로젝트만 또 따로 빌드합니다. 그러면 C:\Program Files\freetype\ 폴더 아래에 헤더 파일과 라이브러리 파일이 모이게 됩니다. 그리고 시스템 환경 변수에 FREETYPE_DIR 이름으로 C:\Program Files\freetype 폴더를 지정하세요.


참고로 Windows 환경에서 freetype 라이브러리를 직접 사용하는 방법은 SoEn 사이트의 강좌를 참고하세요. http://soen.kr/ 사이트에서 왼쪽 강좌 메뉴의 [라이브러리]를 선택한 후, 오른쪽 상단 메뉴 중에서 [FreeType] 메뉴를 선택하여 한 번 읽어보시기를 권장합니다.


(2) Harfbuzz 라이브러리 빌드하기


"HarfBuzz is an OpenType text shaping engine."
HarfBuzz는 오프타입 테스트 쉐이핑 엔진이며, 홈페이지 주소는 https://www.freedesktop.org/wiki/Software/HarfBuzz/ 입니다. HarfBuzz 소스 코드는 다음 링크에서 다운로드 받을 수 있습니다.


https://www.freedesktop.org/software/harfbuzz/release/


여기에 나열된 소스 파일 중에서 우리는 harfbuzz-1.7.2.tar.bz2 파일을 사용할 것입니다. HarfBuzz 1.7.3 이상 버전을 가지고 CMake 작업을 하려고 하면 이상한 에러가 발생하기 때문입니다. 사실 OpenCV에서는 아주 단순한 기능만을 사용할 것이기 때문에 굳이 최신 버전의 freetype & harfbuzz 소스 코드를 사용하지 않아도 된다고 생각합니다. 그래도 너무 옛날 것을 사용하는 것은 좀 찜찜하니까 그나마 제가 동작을 확인한 최신 소스(harfbuzz-1.7.2.tar.bz2)를 사용할 것을 권장합니다.


Harfbuzz 소스 코드도 아래와 같은 폴더 구조를 만들어서 압축을 해제합니다.


c:\harfbuzz\build
           \harfbuzz-1.7.2


Harfbuzz 소스 코드에 대해 Visual Studio 2017 솔루션 파일을 만드는 작업은 CMake GUI 버전을 사용하겠습니다. CMake-GUI 프로그램에서 "Where is the source code:" 항목에는  c:\harfbuzz\harfbuzz-1.7.2 폴더를 지정하고, "Where to build the binaries:" 항목은 c:\harfbuzz\build 폴더를 지정하세요. 그리고 하단의 [Configure] 버튼을 클릭하면 다음과 같은 화면이 나타납니다.



여러가지 항목 중에서 HB_HAVE_FREETYPE 항목을 선택하세요. 나머지는 기본값을 그대로 사용할 것입니다. 그리고 다시 한 번 [Configure] 버튼을 클릭합니다. 그러면 위 그림에서 빨간색으로 표시되는 것들이 모두 흰색 배경 글씨로 바뀌게 됩니다. 이 상태에서 상단의 [Advanced] 항목을 체크하면 아래와 같이 freetype 관련 폴더가 자동으로 설정이 되는 것을 확인할 수 있습니다.



위와 같이 설정이 되었다면 추가로 변경할 것이 없으므로 그대로 [Generate] 버튼을 클릭하셔도 됩니다. CMake 창 맨 아래에 "Generating done" 메시지가 나타나면 [Open Project] 버튼을 클릭하여 Visual Studio 2017이 자동으로 실행되게 하십시오. 그리고 앞서 freetype 라이브러리를 빌드할 때와 마찬가지로 Debug & Release 모드로 각각 솔루션 빌드를 수행하고, 또한 INSTALL 프로젝트에 대해서만 따로 빌드 작업을 수행하세요.


그러면 C:\Program Files\harfbuzz\ 폴더 아래에 HarfBuzz 관련 헤더 파일과 라이브러리 파일이 생성됩니다. (혹시 INSTALL 프로젝트 빌드 시 권한 관련 에러가 발생한다면 Visual Studio 2017을 관리자 권한으로 실행하여 작업을 수행하세요.)


이제 시스템 환경변수에 HARFBUZZ_DIR 변수를 등록하고, 그 값을 C:\Program Files\harfbuzz 폴더로 지정하십시오.



(3) Freetype 모듈을 포함한 OpenCV 라이브러리 빌드하기


이제 OpenCV를 (새로) 빌드할 차례입니다. 혹시 OpenCV 빌드를 해본 적이 없거나 빌드 방법에 대해 익숙하지 않다면 먼저 아래 포스팅을 먼저 보고 빌드 방법을 익히신 후 따라하시기 바랍니다.


http://kkokkal.tistory.com/1315


OpenCV 라이브러리를 빌드하는 전체적인 방법은 위 링크의 동영상 설명을 그대로 따릅니다. 다만 이번 포스팅에서 사용하는 OpenCV 버전이 3.4.0이라는 점이 바뀌었고, 또한 Freetype 모듈 빌드를 위해 추가적인 작업이 필요하다는 점만 주의하시면 됩니다.


일단 github 사이트에서 opencv-3.4.0.zip 파일과 opencv_contrib-3.4.0.zip 파일을 다운로드 받고, 폴더 구조를 아래와 같이 설정합니다. (이전 포스팅에서는 build 대신 mybuild 폴더명을 사용했습니다만, 이제는 build 라는 폴더 이름을 사용합니다.)


c:\opencv\build
         \opencv-3.4.0
         \opencv_contrib-3.4.0


이후 CMake GUI 프로그램에서 수행할 작업은 http://kkokkal.tistory.com/1315 포스트에 있는 동영상과 크게 다르지 않습니다. 사실 변경점이 아예 없다고 봐도 됩니다. 다만 CMake 프로그램으로 작업을 하기 전에 freetype 모듈과 관련된 CMakeList.txt 파일을 일부 수정해야합니다. 일단 c:\opencv\opencv_contrib-3.4.0\modules\freetype\ 폴더에 있는 CMakeLists.txt 파일을 텍스트 편집기로 열어서 아래와 같이 수정합니다. (freetype 모듈의 CMakeLists.txt 수정 방법은 다음 링크를 참고했습니다: https://gist.github.com/UnaNancyOwen/14c72a3f10a46d41c359ab6ea307a1d2)



실제로 제가 사용한 CMakeLists.txt 파일을 아래에 첨부하였으니 참고하세요.

CMakeLists.txt


이후에 OpenCV 라이브러리를 빌드하는 작업은 앞서 소개한 포스팅의 동영상과 동일하게 진행하시면 됩니다. 다만 CMake 화면을 잘 살펴보면 아래 그림과 같이 BUILD_opencv_freetype 항목이 선택되어 있는 것을 확인하실 수 있습니다.



(4) OpenCV에서 Freetype 모듈 사용하기

이제 OpenCV 라이브러리에 포함된 Freetype 모듈을 사용하는 예제를 만들어보겠습니다. Freetype 모듈에서 핵심이 되는 클래스는 cv::freetype::FreeType2 클래스이며, 이 클래스에 대한 자세한 설명은 아래 링크를 참고하세요.

https://docs.opencv.org/master/d9/dfa/classcv_1_1freetype_1_1FreeType2.html


위 링크에 있는 내용을 참고하여 만든 예제 프로젝트의 소스 코드는 다음과 같습니다.


#include "opencv2/opencv.hpp"
#include "opencv2/freetype.hpp"
#include <iostream>

using namespace cv;
using namespace cv::freetype;
using namespace std;

int main(void)
{
	Mat src = imread("lenna.bmp", IMREAD_COLOR);

	if (src.empty()) {
		cerr << "Image load failed!" << endl;
		return -1;
	}

	// FreeType2 객체 생성
	Ptr<Freetype2> ft2 = createFreeType2();

	// 바탕체 글꼴 불러오기
	ft2->loadFontData("c:\\windows\\fonts\\batang.ttc", 0);

	// 문자열 출력
	ft2->putText(src, u8"Hello?", Point(50, 50), 50, Scalar(255, 255, 255), -1, LINE_AA, false);
	ft2->putText(src, u8"안녕하세요!", Point(50, 120), 50, Scalar(0, 255, 255), -1, LINE_AA, false);

	imshow("src", src);
	waitKey(0);
	return 0;
}



위 코드는 매우 단순해서 OpenCV 코딩을 해보신 분이라면 그리 어렵지 않게 해석하실 수 있을 겁니다. 다만 출력할 문자열 "안녕하세요!" 앞에 UTF-8 인코딩을 의미하는 리터럴 u8을 붙여서 u8"안녕하세요!" 라고 입력한 것을 주의깊게 살펴보시면 될 것 같습니다. 이 소스 코드를 빌드하여 실행한 결과는 아래와 같습니다. (Visual Studio에서 OpenCV 소스 코드를 빌드하는 방법은 다른 블로그 또는 https://youtu.be/ptvnUCT7wEQ 링크의 동영상 뒷부분 내용을 참고하세요.)



이로써 이제 OpenCV에서도 이쁜 폰트를 이용하여 한글, 일어, 중국어 등을 출력할 수 있게 되었습니다. 설정이 조금 복잡하다고 느낄 수도 있습니다만, 그리 어렵지 않으니 한번 테스트해보시기 바래요~~ :-)


Posted by kkokkal

댓글을 달아 주세요

  1. Favicon of https://astronomian.tistory.com Yellowly 2019.09.23 06:23 신고 Address Modify/Delete Reply

    질문이 있어 올립니다. 마지막 부분의 문자열 출력에서 u8"" 사이의 텍스트 말고 변수를 넣으려면 어떻게 해야하나요? object가 변수명일때 u8object는 당연히? 안되더라구요 ^^;;

    • Favicon of https://kkokkal.tistory.com kkokkal 2019.09.23 17:08 신고 Address Modify/Delete

      "문자열" 앞에 u8이 붙은 것은 UTF-8 문자열이라는 의미입니다. 아래 링크를 참고하기 바라구요..

      https://en.cppreference.com/w/cpp/language/string_literal
      https://docs.microsoft.com/ko-kr/cpp/cpp/string-and-character-literals-cpp?view=vs-2019

      구글링을 하면 한글 설명도 많이 찾을 수 있을 겁니다.

      질문한 사항은 단순히 아래처럼 변수를 선언하면 됩니다.

      const char* s1 = u8"안녕하세요.";
      string s2 = u8"hello 한글테스트";

    • Favicon of https://astronomian.tistory.com Yellowly 2019.09.23 17:51 신고 Address Modify/Delete

      텍스트 파일에서 읽어오는 변수 name을 넣고 싶은데 알려주신건 변수가 아닌 "" 꼴을 변수 정의하셔서 넣은 것 같습니다.

  2. Favicon of https://astronomian.tistory.com Yellowly 2019.09.23 17:51 신고 Address Modify/Delete Reply

    텍스트 파일에서 읽어오는 변수 name을 넣고 싶은데 알려주신건 변수가 아닌 "" 꼴을 변수 정의하셔서 넣은 것 같습니다.

    • Favicon of https://kkokkal.tistory.com kkokkal 2019.09.23 19:27 신고 Address Modify/Delete

      일반 변수에 저장된 문자열을 u8 형태로 변환하는 것은 안될 것 같은데요..

      UTF-8 형식으로 파일을 읽어오는 방법을 찾아보거나, 또는 미리 u8 문자열을 여러 개 만들어놓고 if 조건문과 name 문자열 비교를 통해 여러 u8 문자열 중에서 선택하여 사용하는 등의 편법을 사용해야 할 것 같습니다.

  3. Favicon of https://goodsmell.tistory.com 좋은향기 2019.10.29 16:48 신고 Address Modify/Delete Reply




    블로그 내용 참고해서 한글 출력까지는 여차저차 성공했습니다.
    잘 정리된 포스팅 감사드립니다.~

    그런데, 텍스트의 사이즈를 계산해서 이미지의 중앙에 배치하려고 하는데,
    ft2->getTextSize() 호출시 height가 제대로 계산이 안되네요...
    0 혹은 실제 크기보다 많이 작은 숫자가 리턴됩니다.

    freetype이랑 harfbuzz 다른 버전도 컴파일해 봤는데 동일한 문제로 한참 삽질 중이네요.
    리눅스에서 돌리는 건 잘 돌아가는데 윈도우즈 버전만 그러네요.

    혹시 getTextSize()도 정상적인 값을 리턴하던가요?
    딱히 물어볼곳도 없고, 해볼만한 삽질은 대충 해본것 같아 염치 불구하고 여쭤봅니다.

    • Favicon of https://kkokkal.tistory.com kkokkal 2019.11.08 19:37 신고 Address Modify/Delete

      한글에 대해서 getTextSize()가 제대로 계산이 되지 않는다는 건가요?
      저는 딱히 테스트를 해보지는 않았습니다만, 제대로 계산이 되지 않을 수도 있을 것 같습니다. 처음부터 한글을 고려하지는 않을 것 같으니까요.

  4. 해피뉴이어 2021.06.18 14:20 Address Modify/Delete Reply

    블로그를 통해서 한글출력과 freetype 연동은 성공했습니다!

    댓글에 있는 내용처럼 저도 ft2->getTextSize() 값이 영어든 한글이든 잘 계산이 안되는거 같은데
    맞는건지 모르겠네요ㅠㅠ
    일단 따로 계산해서 맞춰서 하는데 이부분에 대해서 혹시 아시는게 있는지 여쭤봅니다