Archive for October, 2007

정태영

오늘 밤도 가벼운 마음으로 www 를 헤메고 있습니다.

http://www.apple.com/macosx/guidedtour/

여기저기를 구경하다가 leopard 시연 영상까지 보게 됐네요. 예전 스티브 잡스의 키노트 때도 그랬지만 말도 천천히 해주고 어려운 단어도 별로 안쓰기 때문에 알아듣기가 참 좋아요. (leopard 나 spredsheet 발음이 우리가 하는거랑 참 많이 다르네요. 첨에 뭐라고 하나 했어요.)

하여튼 본 걸 간단히 정리해볼까 싶습니다.

Stack

Dock 모양이 3D 상 위에 아이콘이 올려진 모양으로 변경되었고, Stack 아이콘을 클릭하게 될 경우 최근에 Download 한 파일을 빠르게 확인 가능합니다.

말로 설명하기는 힘들고 위의 스크린 샷처럼 동작하며, 정렬 순서도 바꿀 수 있습니다. 저렇게 한 줄로 나오는게 싫다면 grid 형태로 보는 것도 가능합니다.

폴더를 dock 에 등록해둘 경우 저런 식으로 접근이 가능한 것 같아요.

Corver flow interface

Finder 에도 iTunes 에서와 같은 cover flow 가 가능한데, 이게 이미지 등에만 한정되지 않습니다. 키노트나 워드프로세서 파일들도 첫 페이지가 미리보기 형태로 표시됩니다.

게다가 conver flow 상태에서 동영상을 재생하는 것도 가능하네요.

Foldable category

파인더의 왼쪽에 표시되던 즐겨찾기 기능(?) 이 medias (디스크 드라이브), shared (네트웍으로 공유된 것들), places (home, Documents 등등), search result 등으로 분류가 되고 각각의 카테고리를 folding 할 수 있습니다.

게다가 spotlight 의 검색 결과를 저장해두는 기능이 추가되었네요.

Quick look

지금까지는 어떤 파일의 내용을 확인하기 위해선 preview 등을 이용해야 했는데, 이제는 finder 에서 바로 확인하는 것이 가능해졌습니다. 그냥 미리보기 창이 오버랩되서 보여지는데 시연용 맥이 빠른건지 프로그램 자체가 빠른건지는 모르겠네요.

Spotlight

Spotlight 를 이용해서 공유된 다른 맥에 있는 파일들도 빠르게 찾을 수 있고, time machine 과도 연계해서 사용할 수 있답니다. 설명을 길게 했으나 정리하고 나니 한 줄이네요.

Spaces

가상 데스크탑을 여러개 만들 수 있으며, 드래그앤 드롭을 통해 애플리케이션을 다른 가상 데스크탑으로 이동하는 것도 가능하고, 가상 데스크탑 순서를 재정렬하는 것도 가능합니다.

가상데스크탑 전환은 컨트롤+화살표, 컨트롤+숫자 등의 단축키를 이용할 수도 있고 spaces 아이콘을 클릭해서 할 수도 있습니다.

X11 계열에선 예전부터 많이 쓰이던 기능이지만 애플답게 멋지게 포장해냈습니다.

Sharing screen with iChat

iChat 을 통해 내가 보고 있는 화면을 공유하는 것이 가능합니다. 특정 애플리케이션의 출력만을 공유하는 것도 가능하고 데스크탑 전체를 공유하는 것도 가능합니다.

시연을 할 때는 iChat 을 통해 keynote 를 하는 것을 보여주고 있습니다.

그 외에도 menu bar 에서 아쿠아 룩이 점점 사라지고 있는 등 외관 상에서도 변화가 계속되고 있으며, time machine 이라거나 safari, mail 등과 관련된 얘기들도 있는데 관심이 없어서 여기까지만 후훗; -_-;;

사실 저번 wwdc 에서 발표된 정도라면 구지 업그레이드해야할 이유를 못느꼈었는데, 이거 시연 영상을 보니 혹하네요.

동영상 링크 누가 걸어놨었는지 -_- 아주 완전 당했습니다.

정태영

컴퓨터랑 침대 말고 그냥 편하게 묻혀 생각을 정리하기 위한 공간을 만들기 위해 ‘무지 푹신 소파’ 를 질러버렸습니다. 제품 이름이 ‘푹신 소파’ 이고 제조사가 ‘무지’ 인데 붙여써놓으니 뭔가 묘하네요.

위 사진에서 보이는 갈색 큐브 모양이 그 제품인데, 사람이 앉으면 거기에 따라 모양이 변형됩니다. 책꽂이 옆에 놓았더니 책 볼 때 참 좋네요. 암 생각 없이 앉아있기도 좋고, 앉아서 뭐를 읽기도 좋고 비싸다는 점만 제외하면 굉장히 맘에 듭니다. 히힛~

살림살이가 하나 둘 늘고 있고, 요리 실력도 일취월장하고 있으니 결혼 상대만 찾으면 되겠네요. (이게 쉽지 않으니 문제지만 -_-!)

p.s) 이젠 위시 리스트도 얼마 남지 않았습니다.

정태영

며칠 전부터 몸이 좀 좋지 않았는데, 그걸 핑계 삼을 생각하고 금요일에는 랩에 나가질 않았다. 사실 씻고 나가긴 했었는데 그날따라 왠지 발걸음이 너무 무거웠고, 결국 얼마가지 못해 집으로 돌아와버렸다. 목요일 저녁 읽어볼만한 논문들을 10개 정도 미리 뽑아놨기 때문에 집에서 혼자 조용히 논문들을 읽어보고 싶었는지도 모르겠다.

가끔씩 이런 일탈 행위를 통해 내 기분은 좀 나아지는 것 같다. 확실히 상태가 안좋을 땐 사랑스럽고 편안한 집에서 좀 쉬어줘야 한다.

요번 학기에 신청한 수업 중에는 Computer vision 수업 비중이 높기 때문에 관련된 내용들을 읽어보고 있는데, 역시 어렵다. SIFT 라는 유명한 알고리즘도 어떤 식으로 하겠다는 건지는 이해가 되는데, 라플라시안 관련해서 몇가지 notation 이 뭘 의미하는지 모르겠다. correlation 과 관련된 것 같기는 하지만 Random variable 쪽은 수업을 듣지도 않았고 관심가져본 적도 없어서 시작부터 난항이다. 문제는 그 노테이션이 import point 를 찾는데 사용되는 중요한 수식에 들어있기 때문에 이걸 이해하지 않고는 이 알고리즘을 구현해볼 수 없다는 것!

요 근래 재밌는게 너무 많고, 관련해서 찾아보고 있는 내용도 상당히 많기 때문에 누군가 나한테 뭘 전공하냐고 묻는다면 뭐라고 대답해야할 지 잘 모르겠다. 비젼 쪽도 어렵지만 재밌고, 컴퓨터 아키텍쳐 관련된 것들도 여전히 재밌으며, 그래픽스 관련 된 것들도 너무 흥미롭다. 학부생도 아니고 너무 이것저것 보고 있는 거 같아 좀 걱정되기까지 하는데, 뭐 어떻게든 되겠지… -_-;

하여튼 며칠 전 동기와 술을 마시며 얘기해본 결과 나만 이상한 사람이 아니라는 결론을 내렸고, 그 후로 내 상태곡선이 상승세를 그리기 시작했으며, 오늘 낮 상암동 홈에버를 방문! 신나게 쇼핑을 즐긴 이후 완전 기분 업 상태!!!

욕실용품 코너랑 주방용품 코너에 사고 싶은게 너무 많았지만, 요 근래 너무 많은 걸 질렀다는 생각에 모든 걸 다 지를 수 없었다는게 좀 아쉬울 뿐 후훗;

이제는 내가 다시 멋져질 시기~!

정태영

만약 서로 다른 2개의 (x,y) 쌍을 가지고 있다면 아래와 같은 직선의 방정식을 계산해낼 수 있습니다.

이를 아래와 같은 매트릭스 형태로 표현할 수도 있습니다.

그런데 (x,y) 값을 2 쌍보다 더 많이 알고 있다면, 해가 구해낼 수 없게됩니다. 이를 over constraint 라고 하며, over constraint 상태에서 가장 에러가 작은 직선의 방정식을 구해내는 것을 line fitting 이라고 부릅니다.

line fitting 을 하는 방법은 크게 2가지 방법이 있습니다. 첫번째는 에러를 최소화 하는 계수 a, b 를 찾기 위해 편미분을 이용하는 것이고, 두번째로는 pseudo inverse 를 이용하는 방법입니다.

line fitting with differencial equation

편미분을 통해 최적의 직선을 찾아내기 위해 우선 Error 를 아래와 같이 정의해 봅시다.

2차 곡선의 최소값은 기울기가 0이 되는 지점에 있으므로 a, b 각각에 대해 편미분을 한 뒤 기울기가 0 이 되는 지점을 찾습니다.

위 식을 정리하면 아래와 같은 매트릭스로 표현이 가능하며,

역함수를 양 변에 곱해주게 되면 간단히 계수 a, b 를 구할 수 있게 됩니다.

line fitting with pseudo inverse

지금까지 편미분을 이용한 line fitting 을 알아봤는데, 이 경우는 손으로 계산해야하는 것들이 많았지만 pseudo inverse 를 이용하면 계산을 모두 컴퓨터에게 맡길 수 있기 때문에 훨씬 쉽게 직선의 방정식을 구할 수 있습니다.

pseudo inverse 를 이용한 방법을 알아보기 앞서 위 매트릭스를 간단히 아래와 같이 표현하기로 하겠습니다.

X 에 대한 inverse 를 계산할 수 있다면 간단하게 계수 a, b 를 구할 수 있겠지만 불행히도 X 는 inverse 를 가지지 못하기 때문에 X 에 자신의 transpose 를 곱해준 뒤 역행렬을 구하는 방법을 사용하게 되며, 이런 식으로 역행렬을 구해내는 방법을 pseudo inverse 라고 합니다.

식을 정리하고 나니 아래와 같은 간단한(?) 행렬 연산을 통해 계수 a, b 를 계산해낼 수 있겠습니다.

Result

아래 그래프는 (1.1,0.7), (2.1,1.0), (4.3,3.2), (-1.2,-1.1), (-2.4,-2.1), (-3.5,-3.4) 이렇게 6개의 점에 대한 line fitting 결과를 gnuplot 을 이용해서 그래프로 만든 것이며, 6개의 점 사이를 지나는 직선이 구해진 것을 쉽게 확인할 수 있겠습니다.

p.s) 매트릭스 관련된 오퍼레이션들을 다 짜놨더니 이거이거 이런 간단한 것들 돌려보는건 일도 아니네요. 요 근래 뭔가 조급해하고 있었는데, 맘잡고 기초부터 탄탄히 해놓는게 나을 거 같다는 생각이 들어서. 욕심을 줄이고 있습니다. 후훗

정태영

며칠 전 Perspective Projection 을 정리해놓은 김에 3D Image Rotation 도 정리를 해볼까 싶습니다.

Rotation Matrix

3D 이미지 회전은 아래와 같은 행렬을 통해 새로운 좌표를 계산할 수 있습니다. 또한 이 행렬들은 모두 unitary matrix 이기 때문에 Transpose 를 취해줌으로 역행렬을 쉽게 구할 수 있습니다.

z축 기준: (xy 평면에서의 회전)

y축 기준: (zx 평면에서의 회전)

x축 기준: (yz 평면에서의 회전)

Implementation of Image Rotation

처음에는 3차원 공간을 3차원 배열을 사용하여 모델링한 뒤 실제 3차원 좌표를 모두 뒤지며 forward/backward mapping 하는 방법을 통해 3D image rotation 을 구현해보았습니다. 3차원 배열을 이용 512×512 사이즈의 lena image 를 회전시키려면 (512*1.414)^3 만큼의 공간이 필요하게 되고, 저 공간을 모두 뒤지려면 계산 복잡도가 엄청나더군요.

실제 이 방법을 통해 이미지를 회전 시키는 데 ‘분’ 단위 시간이 필요했던 것으로 기억합니다. 게다가 변환을 반복할 수록 이미지의 디그라데이션이 심해졌기 때문에 이건 아니라는 생각이 들더군요. 이런 경우 이미 잘 설계되어 있는 그래픽 라이브러리를 참고하는 것이 좋기 때문에 OpenGL 의 인터페이스를 살펴보며 어떤 식으로 구현하면 좋을 지 생각하기 시작했습니다.

뭐 어짜피 화면이나 이미지로 보여주기 위해선 2D 평면에 projection 하는 것이 필요하므로 매 번 이미지 자체를 돌리기 보다 축을 회전시키고, 마지막에 그 축을 이용해서 원래 이미지를 새로운 좌표 공간으로 매핑시켜주면 되겠다는 결론을 얻었습니다.

우선 x, y, z 좌표를 identity matrix 로 표현한 뒤 R^T * AXIS 를 통해 새로운 축 AXIS’ 를 구할 수 있고, 회전을 시키고 싶은 만큼 위 연산을 반복해준 뒤 forward mapping 을 해주는 것으로 빠르고 훌륭한 품질을 보여주도록 구현하는걸 성공했습니다.

위 이미지는 512×512 사이즈의 lena 이미지를 z축을 기준으로 45도만큼 회전시킨 결과입니다. 왼 쪽은 단순히 forward mapping 을 해준 것이고 오른쪽은 weighted sum 을 이용해서 forward mapping 을 개선해준 것입니다.

결과적으로 Photoshop 등을 이용한 만큼 훌륭한 이미지를 얻어낼 수 있는 것을 확인할 수 있습니다.

Other Results

아래 이미지는 x 축, y축, z축을 기준으로 순서대로 30도씩 회전시킨 이미지입니다. 이런 식으로 계산을 하려면 순서를 뒤집어서 z축, y축, x 축 기준으로 30도씩 회전을 시켜주면 됩니다.

다음은 x축으로 30도, y축으로 60도 만큼 돌린 결과

실제 구현 코드에 관심이 있으신 분들은 아래 링크를 방문하시면 되겠습니다. 이런 걸 하나하나 구현해볼 때마다 느끼는 거지만 openGL 같은 라이브러리를 설계하신 분들은 상상하기 힘들 정도로 똑똑한 것 같아요.

소스:
http://trac.unfix.net/browser/snippet/rotation_3d

정태영

HCI 과제 덕에 심심찮게 프로그래밍을 하게 되네요. 첫 과제 였던 3D rotation 관련을 구현하는 것도 상당히 흥미로웠지만, 두번째 과제인 Perspective Projection 를 구현하는 것은 정말 멋진 경험이었다고 생각합니다.

지난 며칠간 꽤나 재밌게 프로그래밍을 했던 관계로 블로그에도 살짝 정리해보는게 어떨까 하는 생각이 들었는데, 막상 쓸려니 내용이 잘 전해질지 의문이네요.

What is the Perspective Projection?

Perspective Projection 이란 아래의 왼쪽 이미지를 오른쪽 이미지 처럼 변화시키는 것을 얘기합니다. 꼭 저렇게 비뚜러진 이미지를 바로잡는것은 아니고, 이미지가 투영되는 면을 변화시키는 것이라고 생각하시면 됩니다.

이해를 돕기 위해 wikipedia 에서 이미지를 하나 가져왔습니다. 아래 이미지의 연보라색 면이 상이 맺히는 곳이라고 할 때, perspective transform 은 그 보라색 면을 이동시킨 것 같은 효과를 주기 위해 사용합니다.

How to get a projection matrix.

기본 적으로 Perspective Transform 을 위한 식은 다음과 같습니다.

homogenious coordinate 를 사용하고 있으니 x’ 와 y’ 에 관한 식은 아래와 같이 바꿔쓸 수 있습니다.

이를 정리하면 다음과 같은 꼴로 만들 수 있고,

우리가 값을 알고 싶은 변수들은 a, b, c, d, e, f, g, h 이렇게 8 개이므로, (x, y) 와 그에 대응되는 (x’, y’) 쌍을 4개만 알고 있으면 projection matrix 를 구할 수 있습니다. 이를 구하기 위한 매트릭스는 아래와 같습니다.

남은 건 8×8 matrix 의 inverse matrix 를 구한 뒤 뒤 쪽의 매트릭스에 곱해주는 것 뿐이군요.

Implementation of Perspective projection

이제까지 Perspective Transform 을 위한 매트릭스에 대해 알아봤습니다. 이제는 실제 구현을 해보는 것만 남았네요. 위에서 알아봤듯이 Perspective matrix 를 구하려면 matrix multiplication 과 inverse 를 위한 인터페이스가 필요합니다.

matrix multiplication 의 경우 서로 곱할 수 있는 형식인지를 체크한 뒤 단순한 계산을 하면 되고, inverse 는 gauss elimination 을 이용 reduced row echelon form 으로 만들어주는 것을 통해 쉽게(?) 구해낼 수 있습니다.

위의 두 가지까지 구현했다면, 이제 warping 만을 구현하면 되겠습니다. 이 warping 은 크게 두가지 방법을 통해 구현할 수 있습니다.

forward mapping

forward mapping 은 말 그대로 src 의 x, y 좌표에 대하 dst 의 x’, y’ 를 계산 한 뒤 값을 채워주는 방식입니다. 간단히 pseudo code 로 표현하면 다음과 같이 표현할 수 있겠네요.

for( y = 0 ; y < height ; y++ ){ for( x = 0 ; x < width ; x++ ){ x' = (ax+by+c) / (gx+hy+1); y' = (dx+ey+f) / (gx+hy+1);   dst[y'][x'] = src[y][x]; } }

근데 막상 구현을 해놓고 보면 pixel 이 정수단위이기 때문에 아래와 같이 hole 이 발생하는 것을 확인할 수 있습니다.

backward mapping

위에서 얘기한 hole 을 방지하기 위한 방법 중 하나로 backward warping 이란 것이 있습니다. forward warping 에서 src 의 좌표를 기준으로 dst 의 좌표를 계산했다면, backward warping 에서는 dst 의 좌표를 기준으로 src 의 좌표를 계산하게 됩니다.

간단하게 pseudo code 로 표현하면 아래와 같이 되겠습니다.

for( y' = 0 ; y' < height ; y'++ ){ for( x' = 0 ; x' < width ; x'++ ){ x = (ax'+by'+c) / (gx'+hy'+1); y = (dx'+ey'+f) / (gx'+hy'+1);   dst[y'][x'] = src[y][x]; } }

간단히 코드만 봐도 예상할 수 있겠지만 backward_warping 을 해주게 되면 hole 은 확실하게 없앨 수 있습니다. 결과 이미지는 아래와 같은데, 아주 깔끔한 결과가 나오지는 않았습니다.

forward (or backward) warping with interpolation

forward warping 을 하게 되면 hole 이 생기게 되고, 단순한 backward warping 을 하게 되면 이미지의 화질 저하가 발생하게 되는데, interpolation 을 사용하게 되면 이를 조금 더 개선할 수 있습니다.

전 linear-interpolation 을 사용해보았는데, 설명하기는 복잡하니 관심있으신 분은 저 아래 첨부할 소스를 참고해보시면 좋겠습니다. 결과는 아래와 같이 나옵니다.

우선 interpolation 을 이용한 forward warping 입니다. 복잡하게 하기는 귀찮고 해서 대강 구현했더니, hole 이 줄기는 했지만 여전히 존재하고 있습니다.

다음은 backward warping 에 linear interpolation 을 적용한 결과입니다. hole 도 없고, 보기에 상당히 괜찮아진 것을 확인할 수 있습니다.

소스코드:
http://trac.unfix.net/browser/snippet/image_projection/

참고자료:
http://en.wikipedia.org/wiki/Perspective_%28graphical%29
http://en.wikipedia.org/wiki/Gaussian_elimination

p.s) 부동 소숫점 연산에서 x - x/x*x = 0 이라는 것이 보장되질 않더군요. 코드 한 줄 줄일려다가 디버깅을 30분동안 해야했습니다. -_ㅜ

정태영

무기력에서 빠져나올 의지가 생겼다. 지난 며칠간 (비록 과제를 위해서였지만) 오랫만에 많은 양의 코드를 작성했고, 워닝이나 에러 없이 한 번에 matrix multiplication, gauss elimination, matrix inverse 등을 위한 코드를 작성할 수 있는 걸 보니 녹슬진 않은 것 같다.

이젠 정말 벌여놨던 일들을 마무리할 시점이 아닌가 싶다. 얼른얼른 마무리하고 새로운 일들을 또 벌여봐야겠다. 꺄홋! 하여튼 요번 주 내로 생각해놓은 두 가지 아이디어관련해서도 실험을 걸어놓고, 진행 중인 아이템들도 다 마무리하자! 아자!!!

흠 그나저나 HCI 수업 관련해서 정리해서 블로그에 포스팅해보고 싶은 내용이 많은데, 이노무 귀차니즘은…