← Back to Blog

[Machine Learning] Sum of Squared Differences with Depth Map

artificial intelligence > machine learning

2026-07-041 min read

#artificial-intelligence #machine-learning #computer-vision

양안 시차 (Binocular Disparity)

opencv-official-docs

이미지 출처: OpenCV official docs

양안 시차는 인간과 같은 양안 시각 시스템에서 두 눈이 약간 다른 각도에서 대상을 보는 데서 발생하는 시각적 차이를 의미한다. 가까운 사물일 수록 시차(Disparity)가 크고, 멀리에 있는 사물일 수록 시차가 작다.

disparity=xx=BfZdisparity = x - x^\prime = \frac{Bf}{Z}

xxxx^\prime: 3D 공간 상의 한 점(Scene Point)이 두 카메라에서 투영된 이미지 평면 상의 좌표 BB: 두 카메라 센터 간의 거리 (Baseline) ff: 카메라의 초점 거리(Focal Length) 깊이(Depth): 3D 공간 상의 한 점(Scene Point)에서 카메라까지의 거리

The Sum of Squared Differences (제곱 차 합)

기본 개념으로 왼쪽, 오른쪽 이미지가 유사하지 않을 수록 거리가 가깝고, 유사할 수록 거리가 멀다고 설명했다.

여기서 핵심은 "두 이미지 간 유사도" 라고 볼 수 있다.

필자는 이번에 MSE(평균제곱오차) 방식으로 유사도를 구하였다.

SSD(x,y,d)=i=B2B2j=B2B2(IL(x+i,y+j)IR(x+id,y+j))2SSD(x, y, d) = \sum_{i=-\frac{B}{2}}^{\frac{B}{2}} \sum_{j=-\frac{B}{2}}^{\frac{B}{2}} \left( I_L(x + i, y + j) - I_R(x + i - d, y + j) \right)^2

ILI_L: 왼쪽 이미지 IRI_R: 오른쪽 이미지 BB: Block size(블록 사이즈); 비교할 이미지 크기 dd: Disparity(깊이)

OpenCV로 구현

from matplotlib import pyplot as plt
import numpy as np
import cv2

# Load images
imgL = cv2.imread('./data/tsukuba_l.png',0)
imgR = cv2.imread('./data/tsukuba_r.png',0)

# Compute disparity
stereo = cv2.StereoBM_create(numDisparities=16, blockSize=15)
disparity = stereo.compute(imgL,imgR)

# Display the plots
plt.imshow(disparity,'inferno')
plt.show()

opencv-ssd

Numpy로 구현

import numpy as np
import matplotlib.pyplot as plt

def compute_disparity(imgL, imgR, num_disparities, block_size):
    """
    Computes the disparity map between a pair of rectified stereo images.

    Args:
        imgL (np.ndarray): Left grayscale image.
        imgR (np.ndarray): Right grayscale image.
        num_disparities (int): Maximum disparity range to search.
        block_size (int): Size of the square block for block matching.

    Returns:
        np.ndarray: Disparity map with the same dimensions as the input images.
    """
    # Ensure the images are numpy arrays and have float32 type
    imgL = np.asarray(imgL, dtype=np.float32)
    imgR = np.asarray(imgR, dtype=np.float32)

    # Get the dimensions of the images
    height, width = imgL.shape

    # Initialize the disparity map with zeros
    disparity_map = np.zeros((height, width), dtype=np.float32)

    # Calculate half of the block size for easier indexing
    half_block = block_size // 2

    # Loop over each pixel in the left image
    for y in range(half_block, height - half_block):
        for x in range(half_block, width - half_block):
            # Define the block region in the left image
            blockL = imgL[y - half_block:y + half_block + 1, x - half_block:x + half_block + 1]

            # Initialize variables for the best match
            min_ssd = float('inf')
            best_disparity = 0

            # Search for the best disparity in the range [0, num_disparities)
            for d in range(num_disparities):
                if x - d - half_block