'2008/12'에 해당되는 글 16건
- [박병훈(18기)] Otical Mouse Scanner - Software part | 2008/12/31
- [이정훈(18기)] 입출력 구조의 이해와 SSES의 위치 | 2008/12/31
- [조일용(17기)] Introduction to 손글씨 A2Z | 2008/12/31
- [이정훈(18기)] Bio 구조체에 관한 이야기 | 2008/12/31
- [오영일(18기)] OpenGL을 활용한 Modeling과 glBegin() | 2008/12/30
- [김혜진(18기)] Marker Recognition Algorithm | 2008/12/29
- [김혜진(18기)] Introduction & Setting of AR | 2008/12/29
- [김혜진(18기)] Augmented Reality | 2008/12/29
- [관리자] Gesture Recognition Using WPF | 2008/12/27
- [최영특(18기)] Debian GNU/Linux Packaging | 2008/12/26
Otical Mouse Scanner - Software part :: 2008/12/31 18:58 by 박병훈(18기)
안녕하세요~
Optical Mouse Scanner 프로젝트에서 소프트웨어를 담당하고 있는 박병훈입니다.
저희 프로젝트 현재 각종 기기의 소형화와 기능의 복합화 트렌드를 이어받아 마우스와 스캐너를 하나로
만들어 보고자 했습니다.
기본 원리는 광마우스의 센서를 이용해서 바닥에 있는 부분을 스캔하는 것입니다. 그리고 더나아가 스캔된
이미지에 문자가 있으면 문자를 추출하고 Open API를 이용한 네이버 사전을 연동해서 뜻을 검색할 수 있도록
만들었습니다. 그럼 제가 담당한 문자인식, 이미지프로세싱를 소개하겠습니다.
1. Tesseract OCR Engine
프로젝트를 계획 할 때 문자인식을 직접 개발하려 했으나 짧은 일정과 문자인식 자체만으로도
큰 프로젝트이기 때문에 대안으로 오픈 소스인 Tesseract OCR 엔진을 선택했습니다.
그래서 문자를 인식하는 부분만 오픈 소스를 이용하고 나머지 부분( 이미지 프로세싱 )을 직접
구현하였습니다.
Tesseract OCR 엔진은 문자인식을 위한 엔진으로서 HP에서 개발된 엔진으로 현재는 Google Code의
지원을 받을 받으며 계속 개발 중에 있습니다. 이 엔진은 binary, 흑백, 컬러 이미지에서 문자를 추출할 수
있고 uncompressed TIFF 이미지를 읽을 수 있는 tiff 리더가 포함되어 있으며, compressed 이미지를
읽기위해 libtiff를 추가할 수도 있습니다. 문자 인식 과정은 다음과 같습니다.
1. 스캔된 이미지에서 각종 선들을 읽습니다.
2. 읽어선 선의 검정색 픽셀들을 픽셀보다 더작은 점 단위로 쪼갭니다.
3. 쪼갠 점들로부터 윤곽을 추출하기 위해 처리를 합니다.
4. 윤곽과 연속된 쪼갠 점들로 부터 문자의 외곽선을 추출합니다.
5. 점들을 문자 단위로 구분합니다.
6. 구분된 모든 문자의 특징들을 파악합니다.
7. 저장되어 있는 문자셋과 그 특징들을 비교 분석합니다.
8. 가장 적합한 문자를 뽑아 냅니다.
위와 같은 과정을 거치면 문자가 나오게 되는데 하지만 정확도가 뛰어 나려면 문자의 기울기, 선명도,
노이즈 등 과 같은 많은 부분을 고려해야합니다. 그런 부분을 교정하기 위해 이미지 전처리 과정을
거치게 되는데 어떤 방법으로 전처리를 했는지 보여드리겠습니다.
2. 이미지 전처리
이미지의 노이즈를 제거 하기위해 이진화와 모폴로지 기법을 사용했고 기울기를 조절했으며 작은 글씨
를 인식하기 위해 확대 및 축소 기능을 추가 하였습니다. 각종 기법들을 차례로 보겠습니다.
■ 이진화
이진 영상은 0과 1의 값만 갖는 2레벨 영상입니다. 다른말로는 1비트 영상이라고도 하는데요, 명암도
영상은 0 ~ 255까지의 256레벨을 가지는데 다음과 같은 공식응 적용해서 이진화 영상을 만들게
됩니다.
binary_image[x][y] │
└ 0 else if gray_image[x][y] ≤ threshold

<처리 전> <처리 후>
위 그림 처럼 왼쪽의 그림의 명암도가 오른쪽 그림처럼 사라진것을 알수가 있습니다. 따라서 좀더 나은 문자
인식을 위한 그림을 얻게 됩니다.
■ 모폴로지
모폴로지는 영상 내 객체의 형태적인 면을 표현 또는 서술하는 관계로, 영상의 전처리 작업인 영상내
객체 분류 등과 같은 과정을 거쳐 객체를 뚜렷이 하는 데 이용합니다. 저는 그 중에서는 침식 연산과
팽창 연산 순으로 조합하는 열림 연산 모폴로지 기법을 사용했습니다. 아래와 같은 경우에는 희미한
글자들의 빈공간을 채우면서 글씨가 더욱 또려해 지는 효과를 얻을 수 있습니다.

<처리 전> <처리 후>
■ 확대
일반적으로 이미지를 확대하면 아래의 그림과 같은 방법으로 합니다.

그림에서 2배 확대에 대한 것이 두 가지로 나뉜 것을 볼 수 있는데, 이것은 첫 인덱스가 (0,0)이냐 아니면
(1, 1)이냐에 따라 구분한 것입니다. 전자의 경우 C, Java 계열에서 주로 쓰이고 후자는 Visual Basic, MATLAB
등에서 쓰여집니다. 그러므로 2배 확대한다는 공식자체는 불변한데, 인덱스 처리 방법이 다른 관계로 프로그래
밍 언어별로 실제 코딩 내용이 달라질 수 있음에 유의해여합니다. 확대 공식은 아래와 같습니다.
y_target_pixel = scale * y_source_pixel
Target_image[x][y] = Source_image[x*scale][y*scale]
x_target_pixel과 y_target_pixel은 목적 영상의 화소 위치, x_source_pixel과 y_source_pixel은 원 영상의 위치,
scale은 확대 비율을 가리킵니다.
그런데 그림에보면 확대함으로써 새로운 공간이 생기는데 이 화소를 가르켜 hole이라고 합니다. 이런 홀에는
어떤값을 넣어야 할까요? 네~ 적당한 값;;을 채워 넣어야지요. 바로 이 적당한 값을 채워 넣는 방법이 보간법
입니다. 저는 보간법 중에서는 양선형 보간법을 사용했는데 원리는 아래와 같습니다.

양선형 보간법은 보간 대상 위치 주변에 있는 주어진 4개 화소를 이용하여 2차례 보간법으로 보간한 값을 구하
여 사상하는 것입니다. 다시 간략히 양선형 보간법 과정을 표현하면 아래와 같습니다.

■ 회전
회전은 원 영상을 원하는 각도만큼 변환하는 것을 가르키는데 공식은 다음과 같습니다.
y' = x·sinθ - y·cosθ y'= (x - centerX)·sinθ - ( y - centerY)·cosθ
화소의 위치와 cos(), sin() 함수를 연계하여 얻은 값이 실수인 관계로 목적 영상의 화소에 정확히 사상되지
않기 때문입니다. 또한 영상은 비트맵 방식이라는 한계를 가지고 있기 때문에 이런 현상이 나타납니다. 따라서
이를 위한 해결책으로는 아까 위에서 언급한 보간법이나 영상 개선 알고리즘을 적용해야 합니다.
입출력 구조의 이해와 SSES의 위치 :: 2008/12/31 02:49 by 이정훈(18기)
해당 프로젝트를 수행하기 위해서 무엇보다도 커널의 입출력 구조를 명확하게 이해 하고 있어야 합니다.
커널의 입출력 구조는 단순하 구조가 아닌 복잡한 구조로 되어 있고, 이것의 이해를 바탕으로, 개발된 모듈을 원
하는 입출력 구조의 부분에 위치 시키므로서 얻고자 하는 효과를 얻을 수 있습니다.
SSES의 대략적인 위치를 그림으로 나타 내어 보면 다음과 같습니다.

User Application단에서 Read 또는 Write 요청이 일어나게 되면, 해당 요청들은 VFS단으로 흘러 들어 오게 됩
니다. 이 VFS는 가상 파일 시스템의 약자로, 다른 파일시스템을 가지고 있는 장치 들의 파일 시스템을 추상적으
로 나타낸것으로, 다른 파일시스템을 마운트 하여 사용 할수 있다는것을 의미 합니다.
VFS를 거쳐, 각장치의 파일시스템을 통해 Read, Write의 요청이 있게 되고 , 각장치의 IO가 발생하게 되면 기본
적으로는 I/O Scheduler에 등록이 되어 처리를 기다리게 됩니다. 이 I/O Scheduler의 역할은 상대적으로 속도
가 느린 입출력 장치의 처리를 위해, 한꺼번에 관련된 데이터를 모아서 처리를 하는 형태를 취하게 되어, 한번의
Access로 많은 데이터를 처리 할수 있는 기반을 만들어 주게 됩니다.
해당 시스템은 I/O Scheduler의 위쪽에 위치하여 입출력을 Hooking하는과정을 통해 Read, Write를 할 Target
을 제어 하게 됩니다. 제어를 통해 필요한 Page정보들을 외부 장치에 해당하는 NAND로 흘러 들어가거나, 아니
면 기존의 HDD로의 제어를 유지하게 됩니다.
좀더 세부적인 구조를 나타내어 보도록 하겠습니다.
세부적인 구조는 커널소스상에서 불려지는 함수 레벨 까지의 분석을 도식화 하였습니다.
먼저 SSES의 위치적인 내용은 위쪽 그림에서는 I/O Scheduler의 상위에 위치한다고 적었습니다. 하지만 실제
적으로 Hooking을 하는 부분은 그 밑부분의 HDD에서 Request를 처리 하는 부분입니다.
장치디바이스에 Access할때, 각 장치 디바이스를 위한 큐가 존재하게 되는데 이때의 큐에 흘러 들어온
Request를 가져와 해당 Page 정보가 흘러 들어갈 Target의 위치를 수정하고, 다시 I/O Scheduler에 등록을 하
게 되면, 변환된 Target설정으로 인해, 다른 목적지로 데이터가 흘러 들어가게 됩니다.
다른곳에서는 외부장치에 흘러 들어가는 Data들의 메타데이터를 유지하여 관리하고, 관리된 정보들을 통해 어
느곳을 Target으로 정할 것인지를 결정 하게 됩니다.
이런 과정을 통해 IO입출력의 흐름을 제어 하게 됩니다.
Introduction to 손글씨 A2Z :: 2008/12/31 02:37 by 조일용(17기)
안녕하십니까 16년동안 손글씨만 써온 손글씨의 달인 악필 조일용입니다.
우리 악필팀은 17기 조일용과 18기 김정훈 두명이구요 손글씨 A2Z 프로젝트를 진행하고 있습니다.
이번 포스팅에선 손글씨 A2Z를 소개하도록 하겠습니다.
우선 시작발표회때 사용한 PPT를 보시겠습니다.
간단히 말해 프로젝트의 목적은 사름의 손글시를 컴퓨터상의 폰트로 만들어 주는 프로그램을 작성하는 것입니다.
현재 폰트를 만드는 프로세스는 폰트 디자이너의 각고의 수작업을 통한 노력끝에 하나의 폰트가 만들어지기까지 수주에서 길게는 몇 달이 걸리는데, 우리는 누구든지 자기 글씨를 쉽고 빠르게 폰트로 만들수 있게끔 하고 싶었고 이 프로젝트는 이런 목적을 가지고 시작되었습니다.
프로젝트가 완료되면 다음의 과정을 통해 폰트를 만들 수 있습니다.
1. 손글씨 서식 출력
우선은 자신의 글씨를 종이에 써야겠죠? 사용자는 아래 프로그램을 이용하여 손글씨 서식을 출력한 후 그 위에 글씨를 씁니다.
2. 스캔
서식을 완성 했으면 스캐너를 이용하여 이미지파일을 만듭니다.
이제 이미지 파일이 완성되었으면 '손글씨 A2Z' 프로그램이 본격적으로 사용자의 손글씨를 폰트로 변환합니다.
아래 그림은 '손글씨 A2Z'의 구성을 보여줍니다. 음영으로 진하게 표시된 부분은 포스팅을 하는 현재까지 진행된 상태를 나타냅니다.
3. 이미지 프로세싱
우선은 스캔한 이미지에서 사용자의 글씨와 문자코드를 이미지프로세싱을 하여 추출해냅니다. 서식에는 약간의 트릭이 있는데 바로 글씨를 써야하는 박스는 파란색, 문자코드는 빨간색으로 출력하고 사용자의 글씨는 검정색으로 쓰도록 합니다. 이는 색상값을 이용하여 각각을 구분할 수 있으므로 이미지 프로세싱 과정을 상당히 단순화시켜 줍니다.
이미지 프로세싱과 글립분석은 아래 순서로 진행됩니다.
위의 모식도에서 푸른색은 글씨가 쓰여진 의 영역을 찾는 부분이고 붉은색은 문자코드를 확인하는 부분입니다. 회색은 사용자가 쓴 글씨를 추출해내는 부분입니다. 마지막으로 녹색은 글립의 형태를 분석하고 완성하는 부분입니다.
각각에 대한 자세한 설명은 추후 따로 포스팅을 하겠습니다.
4. 폰트파일 생성
트루타입폰트 파일은 폰트를 정의하는 여러개의 테이블로 구성되어 있습니다. Microsoft와 Adobe에서 표준화하고 유지하고 있는 트루타입스팩에 따르면 모든 트루타입 폰트는 11개의 필수 테이블을 정의하고 있어야 하며 그 외에 추가적으로 옵션테이블을 가질 수 있습니다.
아래 테이블은 트루타입 폰트에 반드시 포함되어야 할 11개의 필수 테이블 목록입니다.
Required Tables
|
Tag |
Name |
|
cmap |
character to glyph mapping |
|
glyf |
glyph data |
|
head |
font header |
|
hhea |
horizontal header |
|
hmtx |
horizontal metrics |
|
loca |
index to location |
|
maxp |
maximum profile |
|
name |
naming table |
|
post |
PostScript information |
|
OS/2 |
OS/2 and Windows specific metrics |
필수 테이블 중 가장 중요한 테이블은 역시 글립을 구성하는 베지어 곡선을 정의하는 glyf 테이블입니다. 포스팅을 하고 있는 현재 스팩의 기준에 따라 glyf 테이블을 구현하고 있는 중입니다.
필수테이블에 대해서는 추후 따로 포스팅을 통해 더 자세히 설명하도록 하겠습니다.
5. 폰트를 사용
폰트가 완성되었다면 이제 사용하는 일만 남았습니다. 다음달 과제가 완료되면 아래 그럼처럼 응용프로그램에서 자유롭게 자신의 글씨를 사용하는 기쁨을 누릴 수 있을 것입니다.
손글씨 A2Z의 소개가 제대로 됐는지 모르겠습니다. 여튼 이번 포스팅은 여기서 마치겠습니다.
다음 포스팅에서는 각각의 세부 기술에 대해서 심도있게 다루도록 하겠습니다.
Bio 구조체에 관한 이야기 :: 2008/12/31 02:28 by 이정훈(18기)
이번 프로젝트를 진행하면서 가장 기본이 되는 것은 Linux에서의 입출력 구조를 이해하는 것입니다.
이 구조를 이해하는데 있어서 가장 중요한것은 어떤 단위로 시스템이 운용되는지를 알고, 해당 단위를 나타내기
위한 구성방법을 이해하고 한단계 더 낳아가 그 단위를 개선 하는 것입니다.

SSES에서는 시스템 내 모든 블록 장치에 대한 요청을 다루는 커널 구성 요소인 블록 계층의 핵심 자료구조인
Bio 구조체를 를 다루면서 동작합니다.
Bio 구조체는 입출력이 진행 중인 블록 장치의 연산 디스크립터로, 대략적인 구조는 Figure 1의 형태로 구성이
되어 있습니다. 이를 자세히 살펴 본다면, 디스크 저장 영역을 위한 식별자와 입출력 연산에 개입된 메모리 영
역을 기술하는 하나 이상의 세그먼트를 포함해 구성됩니다.
이는 Bio구조체로 구현되며, 이 안에서 메모리 영역을 기술하는 각각의 세그먼트들이 bio_vec라는 필드를 통
해 연결됩니다. bio_vec 구조체는 또한 실제 메모리 상의 페이지 구조체 내에서의 섹터 위치를 표시합니다.
각각 Bio 구조체에는 여러개의 Page단위의 데이터를 가지고 있어, 이를 한 Bio 구조체에서 관리 함으로서 한번
의 Access에서 다수개의 Page 단위에 접근이 가능 하도록 하고습니다.
결국 입출력 작업의 최소 단위는 bio_vec 구조체가 가리키는 특정 페이지 단위가 되기 때문에, 하나의 bio_vec
구조체가 가리키는 page를 최소 단위로 해 SSES의 모든 작업을 하는 것이 바람직 하게 됩니다.

Bio 구조체는 여러개의 메모리 영역 기술 세그먼트를 나타내는 bio_vec 구조체들을 bi_io_vec 필드를 통해 갖
는다고 이야기 했으며, 이 필드가 가리키는 배열의 각 bio_vec 구조체를 입출력 요청의 각 단위로 규정, 처리한
다고 이야기 했습니다.
bio_vec 구조체를 최소 단위로 구현하는 데 있어서 매번 bio_vec 구조체 내부로 들어가 모든 작업을 하는 것 보
다는 한개의 bio_vec 구조체를 가지는 bio에 대해 작업 하는 것이 보다 독립적이고 호환성이 좋을 것이다.
이런 이유로 SSES는 bio 구조체를 쪼개서 페이지 단위의 여러 개의 bio 구조체로 만들고, 이렇게 쪼개진 하나
하나의 bio 구조체에 대해 처리합니다.
기존의 Bio구조체를 쪼개는 과정은 다음과 같습니다.
클라이언트 시스템으로부터 입출력 요청에 의해 bio 구조체가 전해져 올 때, bio 구조체를 Hooking을 하게 됩
니다. 가로챈 bio 구조체의 bi_io_vec 필드가 가리키는 bio_vec 구조체의 배열들을 하나하나 돌아가면서, 매번
새로운 bio 구조체를 하나 생성한 후, 새로운 bio 구조체의 bi_io_vec 필드가 가리키는 값으로 기존 bio 구조체
의 bio_vec 구조체의 배열 값을 하나씩 넣어주게 됩니다.
즉, bi_io_vec 필드가 가리키는 bio_vec 구조체 배열이 한개짜리인 bio 구조체를 인위적으로 만드는 것이다.
이를 통해서 최소의 접근 단위가 Page단위가 되게 하여, Page단의 Tracking을 비롯한 Read, Write의 관리를 진
행 할수 있게 됩니다. 이방법의 장접은 원하는 데이터 단위로 조작을 할수 있다는 점이지만, 추가적인 과정으로
인해 오버로드의 발생 문제가 예상 되고 있습니다.
OpenGL을 활용한 Modeling과 glBegin() :: 2008/12/30 00:00 by 오영일(18기)
저는 이번 프로젝트에서 김현수(18기) 회원이 취득한 데이터를 가지고 3D Image를 구현하는 부분을 맡았습니다.
입력으로 받아진 것은 2D Image, 각 Image들간의 접합을 위한 기울기값 그리고 각각의 Depth값입니다. 일단 이렇게 받아진 데이터는 계산하여 한 차원의 3D 좌표값이 되겠습니다. 그러나 이 좌표값을 안다고 해서 그 좌표값들을 무조건 연결한다고 하면 아무런 의미없는 선들이 난무할 것 입니다.(기껏 계산되어 나온 값을 가지고 그런다면 여러가지로 낭비겠죠?...;;)
이럴 때 가장 중요한 것이 여러가지가 있겠지만 가장 기본이 되는 것은 Modeling이 될 것입니다. 그럼 간단한 예를 통하여 가장 기초적인 modeling의 기본이 될 삼각법과 사각법등을 glBegin()과 설명하겠습니다.
OpenGL에서 화면상에 점과 선, 그리고 면을 그리는 것은 아주 쉽습니다. 먼저 코드를
살펴보기 전에 알고 있어야 할 것은 OpenGL의 좌표체계는 3차원 직각좌표를 기본으로 하고 있으며 왼쪽에서 오른쪽으로 그
X좌표의 값이 증가하며 아래에서 위쪽으로 Y좌표의 값이 증가한다는 점, 그리고 모니터 화면의 바깥쪽으로 Z값이 증가한다는 점입니다.
또한 폴리곤은 한마디로 안이 채워진 도형이며 면(Face)이라는 것입니다. 이것을 항상 염두에 둔다면 이해하기 쉬울것이라 생각 됩니다.
이 포스팅의 목표는 일단 화면에 3차원의 정육면체를 나타내는 것입니다. 그리고 아래는 정육면체의 3차원 좌표를 화면에 찍은 것입니다.
8개의 점을 찍어 보았는데 점들이 잘 안보여서 사진을 크게 하였습니다.
(절대 분량 늘리려고 한 건 아닙니다.ㅡ.ㅡ;;)
위 사진의 코드 또한 아래와 같습니다.
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
glBegin(GL_POINTS);
// Front Side
glVertex3f( 1.0f, 1.0f, 1.0f);
glVertex3f(-1.0f, 1.0f, 1.0f);
glVertex3f(-1.0f, -1.0f, 1.0f);
glVertex3f( 1.0f, -1.0f, 1.0f);
// Back Side
glVertex3f(-1.0f, -1.0f, -1.0f);
glVertex3f(-1.0f, 1.0f, -1.0f);
glVertex3f( 1.0f, 1.0f, -1.0f);
glVertex3f( 1.0f, -1.0f, -1.0f);
// Top Side
glVertex3f( 1.0f, 1.0f, 1.0f);
glVertex3f( 1.0f, 1.0f, -1.0f);
glVertex3f(-1.0f, 1.0f, -1.0f);
glVertex3f(-1.0f, 1.0f, 1.0f);
// Bottom Side
glVertex3f(-1.0f, -1.0f, -1.0f);
glVertex3f( 1.0f, -1.0f, -1.0f);
glVertex3f( 1.0f, -1.0f, 1.0f);
glVertex3f(-1.0f, -1.0f, 1.0f);
// Right Side
glVertex3f( 1.0f, 1.0f, 1.0f);
glVertex3f( 1.0f, -1.0f, 1.0f);
glVertex3f( 1.0f, -1.0f, -1.0f);
glVertex3f( 1.0f, 1.0f, -1.0f);
// Left Side
glVertex3f(-1.0f, -1.0f, -1.0f);
glVertex3f(-1.0f, -1.0f, 1.0f);
glVertex3f(-1.0f, 1.0f, 1.0f);
glVertex3f(-1.0f, 1.0f, -1.0f);
glEnd();
OpenGL에서는 각 면들을 나타내기 위하여 6면에 점들을 찍어줍니다.
그리고 이것은 선긋기들을 활용한 예입니다.
![]() | ![]() |
위의 코드와 다른 부분은 glBegin()의 매크로인데 위의 선긋기는 glBegin(GL_LINES)입니다.

위의 그림은 glBegin(GL_TRIANGLES)로 한 삼각법의 예입니다.


