본문 바로가기
TouchDesigner/GLSL

[GLSL] Tracking Object Color with GLSL

by HungryK 2025. 6. 24.

공부용으로 작성되는 페이지입니다. 틀린 부분이나 환경에 따라 오류가 발생할 수 있습니다. 

 


최종 결과물 미리보기

테스트는 웹캠으로 했지만 외부 카메라나 어플을 사용해서도 충분히 가능하다.

 

 

 

만들것? 

TD 관련 영상을 뒤적거리던 도중...제법 멋있는 영상을 발견했다. 

 

 

처음에는 Kinect 센서 중심으로 사용하는 싶었는데, 영상을 시청해보니 따로 뎁스나 스켈레톤을 추적하는게 아니라 GLSL과 Feedback만으로 구성된 아주 간단한 프로젝트였다! 신기하고 재밌어보여서 시도해보았다. 

 

원리 : Feedback과 HSV 변환 

튜토리얼에서는 키넥트 센서를 사용하긴 했지만 언급했다싶이 Depth나 Skeleton을 사용하지 않기 때문에 내장 웹캠이나 싸구려 캠으로도 충분하다. 

이 프로젝트의 핵심은 바로 'Feedback'이다. TouchDesigner 내에서 Feedback은 이전 프레임이 다음 프레임에 영향을 미칠 수 있게 해주는 노드로, 보통은 opacity 조절을 통해 잔상 효과를 만들 때 많이 쓰인다.

 

 

내가 예전에 TD로 만들었던 작업물. 희미하게 보이는 잔상은 Feedback 효과로 만들었다.

 

 

해당 프로젝트에서는 프레임 중 색상 변화를 추적하여 특정 조건에 따라 피드백 효과를 적용해서 마치 오브젝트를 추적하는 것 처럼 보이는 결과물을 만들어내는 것이다. 이 때 GLSL의 역할은 바로 색상 변화와 관련되어있는데, RGB 값을 HSV(Hue, Saturation, Value)로 변환하는 역할을 한다. 

 

 

RGB색공간을 HSV색공간으로 변환하는 이유

RGB 색 공간은 빨강,초록, 파랑이라는 세 가지 색의 적절한 조합으로 한 가지 색을 표현한다. 하지만 세 가지 색의 조합으로는 색상, 채도, 명도를 알 수 없기 때문에 특정 색상만 추출하기 힘들다

velog.io

 

세 가지 색의 조합으로 최종적으로 한 가지 색을 표현하는 RGB 색공간과 달리 HSV 색공간은 색을 색상(Hue), 채도(Saturation), 명도(value) 조합으로 표현하기 때문에 특정 색을 정의하기 쉬워서 특정 색을 추출하거나 추적할 때 사용하기 유용하다. 

 

GLSL 코드 뜯어보기 : HSV 변환 중심으로 

vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);
vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g));
vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r));
float d = q.x - min(q.w, q.y);
float e = 1.0e-10;
return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);

 

 

나도 완전히 이해하고 작성한 것은 아니므로 틀린 내용이 있을 수 있다. 

 

vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);

 

 

RGB를 HSV로 변환하는 데 필요한 보정 상수들이다.

이 값들은 GPU에서 조건 없이 계산을 최적화하려는 테크닉의 일환입니다.

K = (0.0, -1/3, 2/3, -1.0)는 Hue 계산에서의 분기 처리를 단순화하는 데 사용됩니다.

 

vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g));
 
vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r));
 
 

vec4 p에서는 RGB 간의 채널 크기 비교를 통해, 어떤 채널이 가장 크고 어떤 채널이 가장 작은지 계산한다. step(c.b, c.g)는 c.b <= c.g면 1, 아니면 0을 반환하므로 c.b > c.g인 경우와 아닌 경우에 따라 mix 함수가 p 값을 달리 계산한다. 이 수식은 R,G,B 중 어떤 색이 가장 큰지 판단하는 역할을 한다.

 

vec4 q에서는 RGB채널의 조합에 따라 색상을 정확한 위치를 구하는데 사용된다. 

 

float d = q.x - min(q.w, q.y);

 

 

d는 RGB 중 최댓값 - 최솟값으로, HSV의 채도(s) 계산에 필요하다. 색상이 선명할수록 채도는 커지고, 흰색이나 회색에 가까울수록 채도는 0에 가까워진다. 즉, d = 0이면 무채색, d > 0이면 채도가 높은 선명한 색.

 

 
 
float e = 1.0e-10;

 

0으로 나누어지는 것을 방지하는 역할을 한다. Hue나 Saturation 계산 시 분모가 0이 되는 경우가 발생하면 NaN이 발생한다.

= 에러를 미연에 방지하기 위한 수식이다. 

 
 if( #원하는 HSV, RGB 조건 작성 ){
        currentFrame = lastFrame;
    }

 

if() 안쪽은 어떤 오브젝트를 Tracking 할 것인가에 따라 다르게 작성해주면 된다.

그리고 조건을 만족하면 currentFrame과 lastFrame이 일치되어 이미지의 이전 위치가 기록되는 Feedback이 작동하게 된다.  

한계

결과물. 참고로 동작이 겹친 부분은 덮어씌워지기 때문에 지워진다. 매우 천천히 동작해야함을 의미.

 

색상 조건에 따라 잔상을 남기는 원리이므로 주변 환경이나 물건이 추적하려는 색상과 색/채/명도가 유사하다면 기대하지 않은 값들의 잔상도 함께 출력된다. 특히 채도가 높은 색상 물건을 포착하기가 쉽다. 내 경우에는 하필 주변에 굴러다니는 물건 중에 채도 높은 물건이 없어서 상당히 힘들었다. 예시로 사용한 피규어와 피부색이 자꾸 같이 출력되는 문제가 있었다.

 

아무래도 Mediapipe의 Object tracking을 사용하는게 정확도는 더 높겠지만, 그래도 색상만으로도 어느정도 추적(처럼 보이는 표현)이 가능하단걸 알 수 있어서 좋은 공부가 됐다. 

 

 

참고자료

 

 

[GLSL] HSV, RGB 변환 셰이더 및 사용처

1234567891011121314151617vec3 rgb2hsv(vec3 c){     vec4 K =&...

blog.naver.com

 

'TouchDesigner > GLSL' 카테고리의 다른 글

[GLSL] Mosaic Effect  (0) 2025.06.22
[GLSL] RGB Shift  (0) 2025.06.15
[GLSL] GLSL 내장함수 : step, Mix  (0) 2025.05.30
[GLSL] Zoom Effect  (0) 2025.05.29
[GLSL] Graphics pipeline과 Vector4  (0) 2025.03.19