이 글은 영상 처리(Image Processing)을 전공하고자 하는 사람들을 위해 개인적인 생각을 적은 글이다. 필자는 대학원에서 영상 처리를 전공으로 하였으며, 학부 또는 석사 과정에서 이런 책들을 진작에 잘 읽고 공부해놨으면 더 편하고 빠르게 많은 것들을 습득할 수 있지 않았을까 하는 생각을 해본다. 이 글을 읽는 대상은 대학원에서 영상 처리를 전공하고자 하는 학부 2~4학년 학생으로 생각하도록 하겠다.

1. Advanced Engineering Mathematics, 9/E

쉽게 말해 공업수학이다. 수학이야 말로 공학을 공부함에 있어 가장 기초적이면서도 중요한 과목이 아닐 수 없다. 특히, 공업수학은 공대생들을 위한 수학적 내용들을 공대생들이 접할 수 있는 예제를 이용하여 공대생들에게 필요한 방향으로 설명을 해놓았기 때문에 반드시 충실히 읽어야 할 책이라고 할 수 있다. 아마존( http://www.amazon.com/ )에 가서 Advanced Engineering Mathematics 으로 검색을 해보면 아마 다수의 저자에 의해 쓰여진 동일한 제목의 책들이 많은 것을 발견할 수 있을 것이다. 그 중에서 Erwin Kreyszig 의 책이 본교(한양대)에서 사용하고 있는 책으로써, 널리 사용되고 있는 책으로 알고 있다. 이미 9th edition이 나와있을 정도로 역사도 깊은 책이다. 이 외에도 필자는 Peter V. O'Neil 의 책도 소장하고 있는데, 이 책은 미분기하쪽에 대한 내용이 더 자세히 나와있다는 장점이 있다.

2. Linear Algebra and Its Applications, 3/E

Gilbert Strang 이라는 말을 좀 더듬는 MIT 교수님께서 쓰신 책이다. 영상(Image)이란 어차피 쉽게 생각하면 2차원 배열이다. 배열과 벡터의 속성에 대해서 공부하는 학문이 바로 선형 대수(linear algebra)라고 할 수 있다. 아마 학부 2~3학년 과정에서 배우지 않을까 하는 과목이다. 이 책과 더불어, 조금 쉬운 책 Introduction to Linear Algebra, 3/E 도 추천하고자 한다. 특히, 이 책은 MIT Open Lecture 라는 이름으로 인터넷을 통해 화상 강의를 볼 수 있다는 장점이 있다. 그러나, 어차피 내용은 Linear Algebra and Its Applications 책에도 다 있는 것들이므로, 굳이 Introduction to Linear Algebra 책을 구입해서 가지고 있을 필요까지는 없어보인다. 물론 수업은 영어로 진행되지만, 약간은 어눌하면서 빠르지 않게 말을 하기 때문에 한번 도전해보기를 적극 권장한다. 주소는 아래와 같다.

http://ocw.mit.edu/OcwWeb/Mathematics/18-06Spring-2005/CourseHome/

3. C++ 기초플러스 (5판)


영어 원서 제목은 C++ Primer Plus 이고, 저자는 Stephen Prata 이다. 영상 처리란 결국 프로그램을 작성하여 새로운 알고리즘을 테스트해보고 그 결과를 분석하는 작업이 주를 이룬다. 그렇다면, 무엇으로 프로그램을 작성할 것인가? Matlab, C, Java 등의 많은 프로그래밍 언어가 존재하지만, 역시 C++ 이 가장 믿음직한 언어가 아닐까 싶다. 필자가 한 때 java 로 영상 처리 프로그램을 해보긴 했지만 아무래도 대세가 아님을 실감했다. Matlab 은 그 결과를 신뢰할 수 있다는 장점이 있으나, 속도와 범용성, 상용성에서 떨어진다. 그렇다고 C 언어로 모든 것을 하는 시대는 이미 지났다. 이미 객체 지향 패러다임이 전반적으로 깔려있는 상태에서 C 만은 고집하는 것은 시대에 뒤떨어지겠다는 얘기를 하고 있는 것과 다르지 않다고 본다. C++ 이라고 해서 단순히 클래스와 상속성 개념을 이야기하는 것이 아니라, 템플릿과 STL을 같이 공부해야 한다. STL에 대해서는 따로 더 좋은 책들이 나와 있으니 참고하기 바란다. 어찌되었건, 이 책이야말로 C++ 을 다뤄야 하는 학생으로써 반드시 소장하고 있어야 할 책이 아닌가 싶다.

4. Numerical Methods for Engineers 4/E

Chapra 외 1명이 지은 책이다. 수치해석이란 수학적인 문제를 프로그래밍 형태로 푸는 방법을 소개한 책이다. 방정식의 해를 구하는 방법, 미분 혹은 적분을 하는 방법, 행열을 다루는 방법, 최대/최소값을 구하는 방법 등 공대에서 반드시 공부해야 할 학문 중의 하나이다. 아무리 뛰어난 이론을 생각해냈다고 하더라도, 실제로 구현하여 사용할 수 없다면 아무짝에도 소용없는 짓이 되어버린다(적어도 공대에서는...). 이 책에 나온 내용들은 가급적 직접 C++ 로 코딩하여야 확실하게 머리속에 남게 됨을 명심하자.

5. Digital Image Processing, 3/E


Gonzalez 외 2명이 같이 쓴 책이지만, 보통 곤잘레스 책이라고 한다. 영상 처리의 바이블이라고 해도 될만한 책으로, 이 책을 가지고 있지 않은 영상 처리 전공자는 없지 않을까 싶다. 사실, 이 책 말고도 많은 영상 처리 관련 책들이 존재하지만, 학부 과정에서 소화할 정도의 내용을 충실히 담은 책이기 때문에 교과서로 애용되고 있지 않은가 싶다. 2002년 2판이 나왔고, 2007년에 3판이 새로 나왔다. Digital Image Processing using Matlab 이라는 책도 같이 출간되었는데, 이 책은 그다지 권하고 싶지는 않다. 최근 한글 번역서도 출간되어있지만, 가급적 영어 원서로 공부하는 습관을 들이길 바란다.

6. Pattern Classification, 2/E


이 책의 저자는 Duda, Richard O. 외 2명이고, 보통 duda 책이라고 부르기도 한다. 이 책은 대학원 석사 과정 학생에게 권하고 싶은 책이다. 영상 처리라는 학문이 영상의 화질 개선(image enhancement), 영상 기술(description), 각종 필터링(low pass, high pass, etc) 등을 포함하면서 궁극적으로는 인식(recognition)으로 결론을 내지 않을까 싶다. 제목은 패턴 분류라고 되어있지만, 분류(classification)이라는 것은 결국 인식(recognition)으로 이어지게 된다. 이 책은 1973년 1판이 발행되서 거의 이 분야의 바이블로 여겨지다가, 2000년에 2판이 새로 나왔다. 

7. 영상 처리 프로그래밍 by Visual C++


이 책은 필자가 직접 집필한 책이며 영상 처리 이론뿐만이 아니라 구현에 대한 내용까지 담고 있다. 앞서 소개한 Digital Image Processing 에 나오는 영상 처리에 관한 기본적인 이론뿐만 아니라 비등방성 확산 필터(anisotropic diffusion filter), 해리스 코너 검출기(Harris corner detector), 전통적 레이블링 기법(traditional labeling) 등에 대한 설명과 코드를 수록하고 있다. 또한 BMP 파일 구조에 대한 상세한 설명과 OpenCV와 연동하는 방법 등도 유용하다. 윈도우즈 환경에서 Visual C++ 2005 와 MFC를 함께 사용하여 하나의 완성된 영상 처리 프로그램을 만드는 과정에 대해 알고싶다면 이 책을 강력히 추천한다. 다만, 프로그래밍이 완전히 초보인 사람들에게는 설명이 다소 어렵게 느껴질 수도 있다.

대충 중요한 책에 대해서는 언급을 한 것 같다. 이 외에도 좋은 책들이 많지만, 그것들을 다 나열하기는 힘들 것 같고, 적어도 위에서 언급한 책들은 당장 보지 않더라도 책장에 꽂아두고 언제든 참고할만한 가치가 있는 책들이다. 위의 7권 모두 학생판 형태로 5만원 안쪽으로 구입할 수 있는 책들이므로, 가급적 복사본 또는 번역본을 사지 말고 원서로 구입할 것을 추천한다.

공부 열심히 하세요~ ^^
Posted by kkokkal
:
여기에 적혀있던 한글 용어들은 모두 "영상 처리 프로그래밍" 홈페이지 게시판으로 옮깁니다. 향후 업데이트는 "영상 처리 프로그래밍" 홈페이지에서만 이루어질 것임을 알려드립니다. 아래 링크를 클릭하시면 해당 게시판으로 이동합니다.

http://www.ippbook.co.kr/xe/223

Posted by kkokkal
:


Posted by kkokkal
:



공학에서 자주 쓰이는 그리스 문자 읽는 법을 정리해보았다. 새삼스럽게 알게된 점은 '파이'가 pi 와 phi 두 개가 존재했다는 것. 간혹 헷갈려했던 이유를 알게된게다.

아래는 텍스트 버젼.

Α α →알파(ALPHA)
Β β →베타(BETA)
Γ γ →감마(GAMMA)
Δ δ →델타(DELTA)
Ε ε →입실론(EPSILON)
Ζ ζ →제타(ZETA)
Η η →에타(ETA)
Θ θ →쎄타(THETA)
Ι ι →이오타(IOTA)
Κ κ →카파(KAPPA)
Λ λ →람다(LAMBDA)
Μ μ →뮤(MU)
Ν ν →뉴(NU)
Ξ ξ →크사이(XI)
Ο ο →오미크론(OMICRON)
Π π →파이(PI)
Ρ ρ →로우(RHO)
Σ σ →시그마(SIGMA)
Τ τ →타우(TAU)
Υ υ →웁실론(UPSILON)
Φ φ →화이(PHI)
Χ χ →카이(CHI)
Ψ ψ →프사이(PSI)
Ω ω →오메가(OMEGA)
Posted by kkokkal
:

GVF 코드는 http://iacl.ece.jhu.edu/projects/gvf/ 에서 matlab 으로 구현된 것을 구할 수 있다. 이를 C/C++ 형태로 변환하기 위해서는 matlab 코드를 분석할 수 있어야 하는데, 개인적으로 분석한 결과를 제시하려고 한다.

실제 gvf.m 코드는 매우 간략하다. 아래 코드는 코드 설명을 위해 여백을 추가하였을 뿐, 웹에서 다운받은 코드와 완전히 동일하다.


위의 코드에서 실제 iteration이 일어나는 부분의 코드에 대한 설명은 따로 하려고 한다. C. Xu의 논문을 보게 되면, Section III의 C. Numerical Implementation 에서 자세한 구현 방법을 설명해놓고 있다. 자세히 읽어보면 아마 무슨 내용인지는 알 수 있지 않을까.. 흠. Xu의 논문은 위 사이트에서 다운받을 수 있다. (C. Xu and J.L. Prince, "Snakes, Shapes, and Gradient Vector Flow", IEEE Transactions on Image Processing, 359-369, March, 1998 ) 식 (16)이 matlab 코드로 변환되는 과정을 살펴보도록 하자.


Posted by kkokkal
:
Matlab 의 gradient 함수와 del2 함수에 대한 분석 및 C 코드 변환은 GVF 의 Matlab 코드를 분석하는 과정에서 이루어졌다. GVF란 Gradient Vector Flow 의 약자로써, http://iacl.ece.jhu.edu/projects/gvf/ 에서 자세한 정보를 얻을 수 있다.

---------------------------------------------------------------------------------------

Matlab의 del2 는 Laplacian 연산을 의미한다.

>> help del2
DEL2 Discrete Laplacian.
L = DEL2(U), when U is a matrix, is a discrete approximation of
0.25*del^2 u = (d^2u/dx^2 + d^2/dy^2)/4. The matrix L is the same
size as U, with each element equal to the difference between an
element of U and the average of its four neighbors.

L = DEL2(U), when U is an N-D array, returns an approximation of
(del^2 u)/2/n, where n is ndims(u).

아래 코드 분석을 보자. 몇몇 설명은 아래 gradient 관련 글을 참고하기 바란다.



이 코드를 C/C++로 변환하면 다음과 같이 하면 될 듯 싶다. ^^;


void IEGvf::GvfLaplacian(IEFloatImage& img, IEFloatImage& lap)
{
	register int i, j;

	int w = img.GetWidth();
	int h = img.GetHeight();

	lap.SetPixels(0);

	float** pimg = img.GetPixels2D();
	float** plap = lap.GetPixels2D();

	// x 방향
	for( j = 0 ; j < h ; j++ )
	{
		plap[j][0]   = pimg[j][1]*2   - pimg[j][2];
		plap[j][w-1] = pimg[j][w-2]*2 - pimg[j][w-3];
	}

	for( j = 0 ; j < h   ; j++ )
	for( i = 1 ; i < w-1 ; i++ )
	{
		plap[j][i] = ((pimg[j][i+1] - pimg[j][i]) - (pimg[j][i] - pimg[j][i-1]))/2;
	}

	// y 방향
	for( i = 0 ; i < w ; i++ )
	{
		plap[0][i]   += pimg[1][i]*2   - pimg[2][i];
		plap[h-1][i] += pimg[h-2][i]*2 - pimg[h-3][i];
	}

	for( j = 1 ; j < h-1 ; j++ )
	for( i = 0 ; i < w   ; i++ )
	{
		plap[j][i] += ((pimg[j+1][i] - pimg[j][i]) - (pimg[j][i] - pimg[j-1][i]))/2;
	}

	for( j = 0 ; j < h ; j++ )
	for( i = 0 ; i < w ; i++ )
	{
		plap[j][i] /= 2;
	}
}


Posted by kkokkal
:
Matlab 의 gradient 함수와 del2 함수에 대한 분석 및 C 코드 변환은 GVF 의 Matlab 코드를 분석하는 과정에서 이루어졌다. GVF란 Gradient Vector Flow 의 약자로써, http://iacl.ece.jhu.edu/projects/gvf/ 에서 자세한 정보를 얻을 수 있다.

---------------------------------------------------------------------------------------

Matlab 에서 'help gradient' 라고 치면 다음과 같이 출력된다.

>> help gradient
GRADIENT Approximate gradient.
    [FX,FY] = GRADIENT(F) returns the numerical gradient of the
    matrix F. FX corresponds to dF/dx, the differences in the
    x (column) direction. FY corresponds to dF/dy, the differences
    in the y (row) direction. The spacing between points in each
    direction is assumed to be one. When F is a vector, DF = GRADIENT(F)
    is the 1-D gradient.
    (이하 생략)

뭐... 대충 읽어보면 입력 F를 받아서 그것의 x 방향, y 방향으로의 미분값을 각각 구하여 FX와 FY에 저장한다는 내용이다. 아래 Matlab 코드를 보자.


위의 코드를 C/C++ 로 변환하는 것은 쉽다. 위의 빨간색 글씨를 쓰는, 그런 코드 이해가 어려운 거시지 이해만 했다면 C 코드 쓰는 것이야 어려울 턱이 있나.. ^^;

코드는 다음과 같다. 대충 보고 이해하기를...

void Gradient(IEFloatImage& img, IEFloatImage& fx, IEFloatImage& fy)
{
        register int i, j;

        int w = img.GetWidth();
        int h = img.GetHeight();

        fx.CreateImage(w, h);
        fy.CreateImage(w, h);

        float** pimg = img.GetPixels2D();
        float** pfx  = fx.GetPixels2D();
        float** pfy  = fy.GetPixels2D();

        // x 방향 그래디언트 fx 계산
        for( j = 0 ; j < h ; j++ )
        {
                pfx[j][0]   = pimg[j][1]   - pimg[j][0];
                pfx[j][w-1] = pimg[j][w-1] - pimg[j][w-2];
        }

        for( j = 0 ; j < h   ; j++ )
        for( i = 1 ; i < w-1 ; i++ )
        {
                pfx[j][i] = (pimg[j][i+1] - pimg[j][i-1])/2.f;
        }

        // y 방향 그래디언트 fy 계산
        for( i = 0 ; i < w ; i++ )
        {
                pfy[0][i]   = pimg[1][i]   - pimg[0][i];
                pfy[h-1][i] = pimg[h-1][i] - pimg[h-2][i];
        }

        for( j = 1 ; j < h-1 ; j++ )
        for( i = 0 ; i < w   ; i++ )
        {
                pfy[j][i] = (pimg[j+1][i] - pimg[j-1][i])/2.f;
        }
}
Posted by kkokkal
: