정태영

지난 주에는 SoC 아카데미에 잡혀있어야 했는데, 인터넷도 안되고 깔려있는 프로그램도 몇 가지 없어서 너무너무 심심하더군요. 흑;; 결국 지뢰찾기에 매진하게 되었고, 달인의 경지에 오를려는 찰나! ‘이 정도는 나도 만들 수 있겠다!’ 란 생각이 들었습니다.

바로 Visual Studio 를 실행시키고 -_-; 한 두 시간 정도 뚝딱뚝딱 거린 끝에 결국 콘솔용 지뢰찾기를 완성하기에 이르렀습니다. GUI 버젼으로도 만들어볼까 하는 생각이 있어서 게임 코어와 인터렉션 부분을 분리시켜 놓기는 했는데 구차니즘 말기인 요새 상황으로 볼때 GUI 버젼이 정말 나올까 하는 걱정이 조금 –;;

코드는 아래 url 로 가시면 볼 수 있고, Visual Studio 와 gcc (linux/Windows) 에서 정상적으로 컴파일되는 것을 확인했습니다. :) standard c function 을 제외하곤 별 다르게 사용한 게 없어서 아마 다른 플랫폼에서도 잘 실행될거라 생각합니다.

http://trac.unfix.net/browser/snippet/console_mine

p.s) 콘솔에 찍기에는 9×9 사이즈 이상은 너무나도 커져버려서 사이즈를 고정해놨는데 gui 로 옮기게 되면 저 부분에 관련해서 좀 업데이트를 해야겠네요.

정태영

sql injection 을 피하기 위해 single quote 를 escape 시켜주는 코드를 작성해야할 필요가 있었는데, 매번 하나하나에 대해 mysql_real_escape_string 을 호출해주는 건 너무나도 번거로웠다. 뭔가 간단하게 처리할 방법이 없을까 하고 찾아봤더니 왠걸! array_map 이라는 마법의 함수를 발견할 수 있었다.

function stripslashes_deep($var){ $var = is_array($var)? array_map('stripslashes_deep', $var) : stripslashes($var);   return $var; }   function mysql_real_escape_string_deep($var){ $var = is_array($var)? array_map('mysql_real_escape_string_deep', $var) : mysql_real_escape_string($var);   return $var; }   if( get_magic_quotes_gpc() ){ if( is_array($_POST) ) $_POST = array_map( 'stripslashes_deep', $_POST ); if( is_array($_GET) ) $_GET = array_map( 'stripslashes_deep', $_GET ); }   if( is_array($_POST) ) $_POST = array_map( 'mysql_real_escape_string_deep', $_POST ); if( is_array($_GET) ) $_GET = array_map( 'mysql_real_escape_string_deep', $_GET);

common function 들을 정의해놓은 파일 맨 아래 저 코드를 삽입해버리니 sql injection 따위 이제 두려워할 필요가 없어졌다. 움하하핫!!

p.s) 그냥 array_map 에 stripslashes 나 mysql_real_escape_string 을 사용하게 되면 array 가 넘어온 경우 문제가 생길 수 있어서 약간 수정을 했습니다.

정태영

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분동안 해야했습니다. -_ㅜ

정태영

어제 술을 꽤 많이 마신데다가 아침에 일이 있어서 잠을 좀 못잤더니 머리가 아프다.

데스크탑은 여전히 화면이 나오질 않고, A/S 를 받기 위해선 메인보드를 들어내야 할 것 같은데 너무나도 귀찮다. 내가 왜 이런 짓을 해야하는 생각이 들었고, 데스크탑 관련된 것들을 전부 팔아버리고 15인치급 x86 노트북을 사서 쓸까 하는 생각까지 들고 있다. 연구실 형 한 명이 맥북 프로를 사신 관계로 요새 간간히 맥북 프로를 구경해보고 있는데 역시나 매력적이다.

문제는 그걸 지를만한 여유자금이 있지는 않다는 거…

동기들 중에 벌써 컨퍼런스에 낼 논문을 쓰고 있는 사람들이 나오기 시작했다. 난 아직 실험도 채 다 못했는데… 정확하겐 아이디어 검증조차 –;;

왠지 뒤쳐지고 있는 것 같아서 조급해진다.

HCI 수업에서 벌써 과제가 하나 나왔다. 이미지를 읽어서 특정 각도만큼 돌리는 프로그램을 작성하는 것등 3D rotation 과 관련된 것들인데, 오랫만에 코드를 짜보니 재밌다. 물론 짜야했던 코드 양이 많지 않았고 (7줄 남짓; ) 에러 없이 한 번에 구현을 성공해서 더 재밌었는지도 모르겠다. 한동안 프로그래밍과 멀어져 있었는데 아직 녹슬지는 않은 거 같아서 다행이다.

임베디드 소프트웨어 수업과 내장형 시스템 수업에서는 ARM 의 conditional execution[1] 과 관련된 내용을 들었는데, 참 흥미롭다. Computer Architecture 상에서 Conditional branch 가 일어나게 되면 pipeline hazard 가 발생하게 되고, 실제 성능에 큰 악영향을 끼치게 되는데 conditional execution 을 통해 분기를 줄이는 동시에 더 적은 양의 코드로 똑같은 동작을 수행할 수 있도록 만드는 기법이 참 재밌어 보인다.

그 외에도 Havard Architecure 와 폰노이만 아키텍쳐의 차이 등 어설프게 알고 있던 내용들이 좀 정리되는 것 같어서 나름 재밌다. 컴퓨터 아키텍쳐에 관한 내 짧은 지식을 가지고 상상해봤던 내용들이 실제 구현되어 있는 것들과 나름 비슷하다는 사실이 너무나도 신기하다. 이 쪽으로 전공을 했어도 재밌었을 거 같다는 생각이 들기 시작한다.

그나저나 내장형 시스템이랑 임베디드 소프트웨어 이 두 과목이 모두 ARM 수업이다 보니 내용이 많이 겹친다. 월요일에 듣고 수요일에 리뷰 받는 기분이랄까 -_-; 뭐 엄한 시간표를 짠 대신 약간의 보상이라고 생각해야겠다.

그냥 심심해서 잡담겸 포스트… 오늘의 수다 끝!!!

[1] Conditional execution 의 예를 들어보면 아래와 같음.
pseudo code:
if( R0 == 0 ) R1 = 1; else R2 = 2;   Re=3;

Without conditional execution
cmp r0, 0 jnz IDX_ELSE mov r1, #1 jmp IDX_END IDX_ELSE: mov r2, #2 IDX_END: mov r3, #3

With conditional execution
cmp r0,0 movz r1, #1 movnz r2, #2 mov r3, #3

정태영

openGL 을 사용해서 2D 이미지 데이타를 화면에 뿌려주는 방법은 대강 다음과 같이 세가지로 분류할 수 있는 것 같다.

  1. glBegin(GL_POINTS); glColor3i(…);glVertex3d(x0,y0,0); …반복; glEnd();
  2. texture 로 올려주고, 해당 texture 가 입혀진 quad 을 그려줌
  3. glDrawPixels 를 이용

첫번째 방법이야 그냥 저렇게도 가능하다는거지 실제 저렇게 사용할 일은 없다고 생각되고, 실제 빠르게 화면에 2D 이미지를 그려주기 위해서는 2번째 방법이나 3번째 방법을 사용해야할텐데, 저 중에 어떤 걸 사용하는게 더 좋은 방법인지 확신이 들질 않는다.

우선 화면이 확대되었을 때 texture 를 사용할 경우 GL_LINEAR 등의 기본으로 제공되는 interpolation method 들이 있기 때문에 (약간 Blur 된 결과일지는 모르지만) 더 좋은 품질의 이미지를 얻을 수 있겠고, 화면이 다시 그려질 일이 있을 때 texture 데이타가 다시 전송될 필요가 없다는 장점이 있는 듯 싶지만, (texture 로 등록할 때 이미지 데이타는 비디오 메모리로 옮겨진다.) width 나 height 가 2^x 형태로 표현되어야 한다는 제약이 있다. 이게 만약 이미지가 크지 않다면 큰 문제가 되지 않겠지만 만약 HD Sequence 라면? 1920×1080 을 표현하기 위해 2048×2048 = 4MB 를 사용해야 하므로 반 정도의 공간이 낭비될 수밖에 없다.

glDrawPixels 는 다시 화면을 그려줘야할 때마다 이미지 데이타를 메인메모리->비디오메모리 로 복사해줘야 하는 문제가 있지만 만약 동영상 플레이어등을 만들 때 처럼 빠르게 화면이 전환되는 경우라면 이는 큰 문제가 되지 않을 듯 싶기는 하다. 물론 화면이 멈춰있는 상태라면 얘기가 다를 지 모르겠다. 또 이미지를 실제 크기보다 더 크게 표현할 경우 glPixelZoom 을 이용해 간단히 구현할 수 있지만 실제로는 픽셀 크기만 커지는 효과이지 interpolation 은 일어나지 않으므로 화질은 texture 를 사용할 때에 비해 떨어진다고 할 수 있을 듯…

뭐 하튼 뭘 사용하는게 더 좋은건지 인터넷을 열심히 찾아봤지만 뭐가 더 좋은지에 대한 정확한 답은 찾을 수가 없다. -_-!

p.s) yuv2rgb 변환 같은 것은 cg 를 이용해서 처리할 수 있는 것 같은데… 이 경우 texture 를 사용해야지만 가능 한 듯…

openGL 에 이미 4×4 matrix multiplication 은 구현되어 있으므로 color_matrix 를 사용해서 yuv2rgb 변환을 빨리할 수 있지 않을까 하는 생각도 해봤지만 실제 결과는 참담…

정태영

저번 주에 개인적으로 de-interlacing 관련된 발표를 준비하느라 논문에 있는 de-interlacing 기법들을 구현해서 실험을 했었는데, 맥에서 돌아가는 yuv player 를 못찾는 바람에 결과는 윈도우로 옮겨서 확인해야하는 불편이 있었다.

랩에 이미 충분히 쓸만한 yuvplayer 가 있기는 하지만 윈도우 전용이고, 내가 예전 신입생 과제를 하면서 만들었던 플레이어 역시 윈도우용;; 뭐 하튼 플레이어를 구현하는데 필요한 기반 테크닉은 다 갖추고 있었기 때문에 MFC + OpenGL 로 구현해봤던 것을 똑같이 Cocoa+OpenGL 로 구현해봤다.

메뉴를 이용해서 size 와 color format, frame rate 등을 준비할 수 있도록 만들었는데, size 와 frame rate 를 사용자가 직접 입력하는 것은 귀찮은 관계로 나중에 -_-;;

뭐 하튼 Zoom 하고 Drag And Drop 과 관련된 코드만 추가하고 나면 내가 구현하고 싶었던 모든 기능이 다 들어가는 거 같다. (Zoom 이야 glPixelZoom 을 사용하면 한방에 오케이니 흐흣)

XCode + Interface Builder 를 이용한 첫 결과물인데, 굉장히 오래전에 이미 나와있던 프로그래밍 인터페이스인데도 불구하고 굉장히 편리하게 프로그래밍이 가능해서 감탄을 해버렸다. 물론 MS 진영도 Visual Studio 2005 로 오면서 편리한 기능들이 꽤 많이 추가되긴 했지만, GUI Application 을 만들기 위한 IDE 로는 XCode + 인터페이스 빌더 쪽이 한 수 위인 듯…

MFC 나 Cocoa 나 진입 장벽이 꽤 높지만… 기본적인 테크닉을 익히고 나면 굉장히 강력하게 사용이 가능한 것 같다. 그리고 C 에 능숙하다면 다른 언어를 접하는 데도 그리 큰 어려움을 느끼지 않는 것 같다. 학부 시절 C++, Java 등에 눈길을 뺐기지 않고 주력 언어로 C 를 선택했던 게 탁월한 선택이었던 듯…

p.s) 코드를 좀 정리하고 sourceforge 등에 자리를 틀어볼까 싶네요. :)

정태영

화상처리기초 수업 과제 때문에 처음으로 wavelet transform 을 구현해보았습니다. 아래 이미지는 wavelet 으로 변환된 512×512 사이즈의 lena

histogram 을 보면, 값들이 낮은 값들로 집중되어 있는걸 확인할 수 있습니다. 역시 이미지 압축을 위해 사용할만 하네요. ;)