비디오 처리 및 컴퓨터 비전 분야에서 움직임을 추적하는 것은 매우 중요한 작업입니다. 이 과정에서 주로 사용하는 알고리즘 중 두 가지는 Lucas-Kanade 방법과 Farneback 방법입니다. 이 글에서는 각각의 방법에 대해 자세히 설명하고, 각각의 장단점과 실제 사용 예제를 비교해 보겠습니다.
1. Lucas-Kanade 방법
Lucas-Kanade는 Optical Flow의 일종으로, 짧은 시간 간격 동안의 이미지에서의 픽셀 이동을 추정하는 기법입니다. 이 방법은 주로 아주 작은 움직임을 추적하는 데 유용합니다. Lucas-Kanade 방법은 다음과 같은 가정을 기반으로 합니다:
- 인접한 픽셀에서의 밝기 변화는 크게 변하지 않는다.
- 작은 움직임에 대해 서로 인접한 픽셀의 속도가 비슷하다.
1.1 이론적 배경
Lucas-Kanade 방법은 이미지에서의 미분을 이용하여 밝기 변화와 픽셀 이동 사이의 관계를 수학적으로 표현합니다. 이 관계는 다음과 같은 형태로 표현될 수 있습니다:
∂I/∂x * u + ∂I/∂y * v + ∂I/∂t = 0
여기서 I는 이미지 밝기, u와 v는 각 픽셀에서의 x, y 방향 속도를 나타냅니다.
1.2 OpenCV를 이용한 Lucas-Kanade 구현
OpenCV에서는 Lucas-Kanade 방법을 쉽게 구현할 수 있는 함수인 cv2.calcOpticalFlowFarneback
을 제공합니다. 다음은 파이썬을 사용하여 Lucas-Kanade Optical Flow를 구현하는 예제입니다:
import cv2
import numpy as np
# 비디오 캡처
cap = cv2.VideoCapture('input_video.mp4')
# 첫 번째 프레임 읽기
ret, old_frame = cap.read()
old_gray = cv2.cvtColor(old_frame, cv2.COLOR_BGR2GRAY)
# 특성 포인트 찾기
p0 = cv2.goodFeaturesToTrack(old_gray, mask=None, maxCorners=100, qualityLevel=0.3, minDistance=7, blockSize=7)
# 마스크 생성
mask = np.zeros_like(old_frame)
while True:
ret, frame = cap.read()
if not ret:
break
frame_gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
# Lucas-Kanade 방법으로 Optical Flow 계산
p1, st, err = cv2.calcOpticalFlowPyrLK(old_gray, frame_gray, p0, None)
# 추적된 포인트를 그리기
if p1 is not None:
for i, (new, old) in enumerate(zip(p1, p0)):
a, b = new.ravel()
c, d = old.ravel()
mask = cv2.line(mask, (a, b), (c, d), (0, 255, 0), 2)
frame = cv2.circle(frame, (a, b), 5, (0, 0, 255), -1)
img = cv2.add(frame, mask)
cv2.imshow('Frame', img)
old_gray = frame_gray.copy()
p0 = p1[st == 1]
if cv2.waitKey(30) & 0xFF == 27:
break
cap.release()
cv2.destroyAllWindows()
2. Farneback 방법
Farneback 방법은 Optical Flow를 계산하는 또 다른 기법으로, 이미지 블록 분석을 통해 밀집한 흐름을 찾습니다. 이 방법은 각 픽셀에 대해 입력 이미지의 다항식을 맞추고, 이를 통해 흐름 벡터를 계산하는 방식입니다.
2.1 이론적 배경
Farneback 방법은 각 이미지 블록의 다항식逼近을 사용하여 흐름 벡터를 계산합니다. 이 방법의 핵심은 이미지 간의 변화를 매우 세밀하게 추적할 수 있다는 점입니다.
2.2 OpenCV를 이용한 Farneback 구현
OpenCV의 cv2.calcOpticalFlowFarneback
함수를 사용하여 Farneback Optical Flow를 쉽게 구현할 수 있습니다. 다음은 Farneback Optical Flow를 계산하는 예제입니다:
import cv2
import numpy as np
# 비디오 캡처
cap = cv2.VideoCapture('input_video.mp4')
# 첫 번째 프레임 읽기
ret, old_frame = cap.read()
old_gray = cv2.cvtColor(old_frame, cv2.COLOR_BGR2GRAY)
# 마스크 생성
h, w = old_gray.shape
mask = np.zeros_like(old_frame)
while True:
ret, frame = cap.read()
if not ret:
break
frame_gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
# Farneback 방법으로 Optical Flow 계산
flow = cv2.calcOpticalFlowFarneback(old_gray, frame_gray, None, 0.5, 3, 15, 3, 5, 1.2, 0)
# 벡터화 처리
for y in range(0, h, 10):
for x in range(0, w, 10):
fx, fy = flow[y, x]
cv2.arrowedLine(mask, (x, y), (int(x + fx), int(y + fy)), (0, 255, 0), 1, tipLength=0.3)
img = cv2.add(frame, mask)
cv2.imshow('Frame', img)
old_gray = frame_gray.copy()
if cv2.waitKey(30) & 0xFF == 27:
break
cap.release()
cv2.destroyAllWindows()
3. Lucas-Kanade vs Farneback: 비교
이 두 방법은 각기 다른 상황에서 강점과 약점을 가집니다. 다음은 두 방법의 비교입니다:
특징 | Lucas-Kanade | Farneback |
---|---|---|
속도 | 빠름, 작은 영역에 적합 | 느림, 전체 영역에 적합 |
정확도 | 작은 움직임에 더 정확함 | 복잡한 움직임, 전체 흐름에서 정확함 |
사용 용도 | 특징 점 추적 등 | 밀도 추적, 전체 흐름 시각화 등 |
4. 결론
Lucas-Kanade와 Farneback 방법 모두 Optical Flow를 계산하는 데 유용하지만, 각자의 장단점이 있습니다. Lucas-Kanade 방법은 속도와 작은 움직임에 더 적합하고, Farneback 방법은 더 복잡한 움직임을 다루는 데 강점을 가지고 있습니다. 사용자들은 상황에 맞게 각각의 방법을 선택하여 사용할 수 있습니다.
이러한 Optical Flow 기법을 사용하여 비디오 분석, 객체 추적, 움직임 기반 인터페이스 등을 구현할 수 있습니다. OpenCV의 강력한 기능을 활용하여 다양한 프로젝트에 적용해 보며 컴퓨터 비전의 재미를 느껴보시길 바랍니다.