본문 바로가기

개발자/Computer Vision

Dense Optical flow by block matching

반응형

Block Matching 알고리즘을 사용하여 Dense Optical Flow를 계산하면서, 가우시안 피라미드(Gaussian Pyramid)를 5 레벨로 구성하여 성능을 개선하는 방법을 구현할 수 있습니다. 가우시안 피라미드는 이미지의 여러 레벨에서의 흐름을 계산하여 보다 정확한 Optical Flow를 추정하는 데 도움이 됩니다.

아래는 Block Matching 방법을 사용하여 Dense Optical Flow를 계산하고, 가우시안 피라미드를 5 레벨로 구성하는 Python 코드입니다. OpenCV의 cv2.calcOpticalFlowBM을 사용하여 각 피라미드 레벨에서 Optical Flow를 계산한 후, 상위 레벨로의 흐름을 보간하여 최종 Optical Flow를 생성합니다.

### **Python 코드 예제**

```python
import cv2
import numpy as np

def build_gaussian_pyramid(image, levels=5):
    pyramid = [image]
    for i in range(1, levels):
        image = cv2.pyrDown(image)
        pyramid.append(image)
    return pyramid

def calculate_block_matching_optical_flow(prev_pyramid, next_pyramid):
    # Initialize flow with zeros
    h, w = next_pyramid[0].shape
    flow = [np.zeros((h, w, 2), np.float32) for _ in range(len(prev_pyramid))]
    
    # Compute flow from the lowest resolution to the highest
    for level in reversed(range(len(prev_pyramid) - 1)):
        prev_img = prev_pyramid[level]
        next_img = next_pyramid[level]
        
        if level < len(prev_pyramid) - 1:
            flow_up = cv2.pyrUp(flow[level + 1])
            flow_up = cv2.resize(flow_up, (next_img.shape[1], next_img.shape[0]))
            flow[level] = flow_up
        
        # Calculate Optical Flow at this level
        flow[level] = cv2.calcOpticalFlowBM(prev_img, next_img, blockSize=15, maxLevel=4,
                                            criteria=(cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT, 30, 0.01))
        
    return flow[0]

def visualize_flow(flow):
    magnitude, angle = cv2.cartToPolar(flow[..., 0], flow[..., 1])
    hue = angle * 180 / np.pi / 2
    saturation = np.ones_like(hue) * 255
    value = cv2.normalize(magnitude, None, 0, 255, cv2.NORM_MINMAX)
    
    hsv_img = np.zeros((flow.shape[0], flow.shape[1], 3), dtype=np.uint8)
    hsv_img[..., 0] = hue
    hsv_img[..., 1] = saturation
    hsv_img[..., 2] = value
    
    bgr_img = cv2.cvtColor(hsv_img, cv2.COLOR_HSV2BGR)
    
    return bgr_img

# 비디오 또는 이미지 로드
cap = cv2.VideoCapture('video.mp4')  # 비디오 파일 또는 웹캠 사용

# 첫 번째 프레임 읽기
ret, prev_frame = cap.read()

if not ret:
    print("비디오를 읽는 데 실패했습니다.")
    cap.release()
    cv2.destroyAllWindows()
    exit()

prev_gray = cv2.cvtColor(prev_frame, cv2.COLOR_BGR2GRAY)

# 비디오의 모든 프레임에 대해 Optical Flow 계산
while cap.isOpened():
    ret, next_frame = cap.read()
    
    if not ret:
        break
    
    next_gray = cv2.cvtColor(next_frame, cv2.COLOR_BGR2GRAY)
    
    # Build Gaussian pyramids
    prev_pyramid = build_gaussian_pyramid(prev_gray, levels=5)
    next_pyramid = build_gaussian_pyramid(next_gray, levels=5)
    
    # Optical Flow 계산
    flow = calculate_block_matching_optical_flow(prev_pyramid, next_pyramid)

    # Optical Flow를 시각화
    flow_vis = visualize_flow(flow)
    
    # 결과 표시
    cv2.imshow('Dense Optical Flow', flow_vis)
    
    if cv2.waitKey(30) & 0xFF == 27:  # ESC 키를 누르면 종료
        break
    
    prev_gray = next_gray

cap.release()
cv2.destroyAllWindows()
```



### **코드 설명**

1. **`build_gaussian_pyramid` 함수**:
   - 입력 이미지를 가우시안 피라미드를 구성합니다. 각 레벨에서 이미지의 크기를 줄여가며 피라미드를 생성합니다.
   - `cv2.pyrDown`을 사용하여 이미지를 다운샘플링합니다.

2. **`calculate_block_matching_optical_flow` 함수**:
   - 피라미드의 가장 낮은 레벨부터 가장 높은 레벨까지 Optical Flow를 계산합니다.
   - `cv2.calcOpticalFlowBM`을 사용하여 각 피라미드 레벨에서 Optical Flow를 계산합니다.
   - 상위 레벨로 이동하면서 흐름을 보간하고, 최종 Optical Flow를 추정합니다.

3. **`visualize_flow` 함수**:
   - Optical Flow를 HSV 색상 공간으로 변환하여 시각화합니다.
   - 흐름의 크기와 방향을 색상으로 변환하고, HSV 이미지를 BGR 이미지로 변환하여 시각화합니다.

4. **비디오 읽기 및 결과 표시**:
   - 비디오 파일을 열고, 각 프레임에 대해 가우시안 피라미드를 사용하여 Block Matching Optical Flow를 계산하고 시각화하여 화면에 표시합니다.
   - ESC 키를 눌러 프로그램을 종료합니다.

이 코드는 가우시안 피라미드를 사용하여 블록 매칭 기반의 Dense Optical Flow를 계산합니다. 이 방법은 다양한 스케일에서의 흐름을 고려하여 더 정확한 Optical Flow를 추정할 수 있습니다.

반응형