장원영이 되는 주파수

장원영 얼굴 뺏는 주파수라는 밈이 있다. 이 주파수를 잘 때 틀어 놓으면 장원영의 얼굴을 뺏어올 수 있고, 오래 틀수록 성공 확률이 높아지며, 한번 들으면 본인 얼굴로는 다시 못 돌아온다는 무시무시한 경고까지 붙어 있다. 이재용 금전운 뺏는 주파수, 도화살 주파수 같은 류의 친척들도 있다.

이 밈을 보자마자 푸리에 변환이 떠올랐다. 진짜로 주파수로 장원영이 될 수 있지 않나? 푸리에 변환을 쓰면 말이다.

푸리에 변환, 그리고 1차원 버전

푸리에 변환은 어떤 신호든 다양한 주파수 성분, 그러니까 사인과 코사인의 합으로 분해할 수 있게 해 준다. 이걸 2차원으로 확장하면 각각의 주파수 성분을 하나의 원운동으로 이해할 수 있고, 여러 개의 원운동이 중첩되면서 하나의 형상이 만들어진다. 회전하는 화살표들이 빙글빙글 돌며 외곽선을 그려나가는, 그 익숙한 영상이 바로 이거다.

사실 나는 이전에 이 방식으로 ‘장원영이 되는 주파수’를 한 번 만든 적이 있다. 장원영의 사진에서 윤곽선을 따 하나의 긴 곡선으로 만들고, 그 곡선에 푸리에 변환을 걸어 수많은 원운동의 합으로 장원영의 외곽선을 그려내는 것이었다.

그런데 사진을 곡선으로 바꾸는 순간, 이미지는 이미 ‘선’이 되어 버린다. 장원영의 얼굴이 가진 명암과 질감, 면(面)은 다 버리고 외곽선만 남기는 셈이다. 그래서 이번에는 이걸 2차원으로 확장했다. 선이 아니라 이미지 그 자체를 분해하기로 한 것.

2차원으로 확장하기

1차원 곡선의 푸리에 변환이 신호를 원운동의 합으로 쪼갠다면, 2차원 이미지의 푸리에 변환은 이미지를 물결무늬의 합으로 쪼갠다. 이렇게 뽑아낸 각 주파수 성분은 원이 아니라, 특정 방향으로 흐르는 흑백 줄무늬(평면파)다. 수식으로 쓰면 이런 한 장의 줄무늬다.

\[\cos\big(2\pi(u\,s + v\,t) + \phi\big)\]

여기서 $s = x/W$, $t = y/H$는 이미지 안의 정규화된 좌표이고, $(u, v)$는 가로·세로로 몇 번 출렁이는지를 나타내는 정수다. $u$가 크면 가로로 촘촘하고, $v$가 크면 세로로 촘촘하다. 결국 방향과 촘촘함만 다른 줄무늬들인 셈이다.

평면파 예시

2차원 이산 푸리에 변환은 이미지를 이런 줄무늬들의 강도와 위상으로 분해해 준다.

\[F(u,v) = \sum_{x=0}^{W-1}\sum_{y=0}^{H-1} I(x,y)\, e^{-2\pi i\left(\frac{ux}{W} + \frac{vy}{H}\right)}\]

각 $F(u,v)$의 크기 $\lvert F(u,v) \rvert$는 그 줄무늬의 밝기(진폭)를, 위상 $\angle F(u,v)$는 줄무늬를 어디로 밀어 놓을지를 알려준다. 아래 왼쪽이 원본, 오른쪽이 이렇게 구한 주파수의 지도(로그 크기 스펙트럼)다. 가운데 밝은 점이 저주파, 바깥으로 갈수록 고주파다.

원본과 스펙트럼

그래서 나는 장원영의 사진에 2D 푸리에 변환을 적용해 약 4만 3천 개의 주파수 성분을 얻고, 반지름 주파수 $r = \sqrt{u^2 + v^2}$ 가 작은 것부터, 즉 저주파부터 고주파 순으로 줄 세웠다. 낮은 주파수는 큰 덩어리 같은 명암을, 높은 주파수는 머리카락이나 눈매 같은 디테일을 담당한다.

실제로 저주파부터 차곡차곡 더해 보면, 흐릿한 얼룩이 점점 또렷한 장원영이 되어 가는 걸 볼 수 있다.

저주파에서 고주파로 누적 복원

결국 겹쳐 쌓는다는 건 이런 합이다.

\[I(s,t) = \sum_{(u,v)} A_{u,v}\, \cos\big(2\pi(u\,s + v\,t) + \phi_{u,v}\big)\]

쌓여서 장원영이 되는 과정

이걸 그냥 한 번에 합쳐 버리면 재미가 없으니, 쌓여 가는 과정을 볼 수 있게 만들었다. 화면은 두 개의 평면으로 되어 있다.

위쪽은 누적 평면. 지금까지 더해진 주파수들로 복원된 장원영이 점점 또렷해지는 곳이다. 아래쪽은 임시 평면. 지금 막 더해지려는 단 하나의 주파수가 흑백 줄무늬로 떠올랐다가, 위로 솟아올라 누적 평면에 스르륵 스며들며 사라진다. 그러고는 곧바로 다음 주파수를 등장한다.

구현에서 가장 마음에 드는 부분은, 주파수를 더할 때 공간 위에서 줄무늬를 일일이 그려 합치지 않는다는 점이다. 주파수 도메인에 해당 성분(과 그 켤레)을 점으로 꽂아 넣고 역푸리에 변환을 한 번만 돌리면, 곧바로 복원된 이미지가 튀어나온다. 덕분에 4만 개가 넘는 주파수를 전부 켜도 조금도 무겁지 않다. 푸리에의 세계에서는, 줄무늬 한 장을 더하는 일이 그냥 점 하나를 켜는 일이다.

마무리

1차원에서 원운동으로 외곽선을 그렸다면, 2차원에서는 물결로 면을 채운다. 같은 사람을, 한 차원 더 늘려 다시 받아쓴 셈이다.

인터넷에 떠도는 장원영이 되는 주파수는 과학적 근거가 없지만, 적어도 여기 이 주파수들은 진짜로 쌓일수록 장원영이 된다. 말 그대로, 장원영이 되는 주파수를 만든 셈이다.

다만 틀어 놓는다고 내 얼굴이 장원영이 되진 않는다. 아쉽게도.