Python과 OpenCV – 46 : 스트레오 이미지로부터 깊이 맵(Depth Map) 생성하기

이 글의 원문은 https://opencv-python-tutroals.readthedocs.io/en/latest/py_tutorials/py_calib3d/py_depthmap/py_depthmap.html 입니다.

이전 글에서는, Epipolar 제약조건과 이와 관련된 용어들에 대한 기본 개념을 살펴 보았습니다. 동일한 장념에 대한 2개의 이미지를 가지고 있다면, 이를 이용해 직감적으로 깊이에 대한 정보를 얻을 수 있다는 것을 알 수 있습니다. 아래의 이미지는 이런 직관을 간단한 수학적인 수식으로 나타내고 있습니다.

위의 그림에 비례하는 삼각형들이 있습니다. 비례하는 삼각형들간의 관계를 통해 다음 공식을 얻을 수 있습니다. (disparity = 차이)

x와 x’는 장면 3D 포인트(X)가 이미지 평면에 표시되는 위치와 이를 촬영한 카메라의 중심 사이의 거리입니다. B는 두 카메라 사이의 거리이며 f는 카메라의 초점거리입니다. B와 f는 이미 알고 있는 값입니다. 위의 공식은 장면에서 포인트의 깊이는 이미지 포인트와 이를 촬영한 카메라 중심 사이의 거리 차이에 반비례한다는 것을 나타냅니다. 이러한 정보를 통해, 이미지에서 모든 픽셀의 깊이를 얻을 수 있습니다.

이에 대한 OpenCV에 대한 예제를 살펴 보면 다음과 같습니다.

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

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

stereo = cv2.StereoBM_create(numDisparities=16, blockSize=15)
disparity = stereo.compute(imgL,imgR)
plt.imshow(disparity,'gray')
plt.show()

tsukuba_l.png 파일과 tsukuba_r.png는 각각 동일한 장면에 대해 왼쪽과 오른쪽 방향에서 촬영한 이미지로 각각 아래와 같습니다.

위의 코드를 실행하면 그 결과는 다음과 같습니다.

카메라로부터 가까운 픽셀은 밝고, 멀어질 수록 어둡게 표시됩니다. 결과 이미지에는 잘못된 잡음이 섞여 있는데, 이를 조정하기 위해 numDisparities와 blockSize 값을 조정해 개선할 수 있습니다.

“Python과 OpenCV – 46 : 스트레오 이미지로부터 깊이 맵(Depth Map) 생성하기”에 대한 5개의 댓글

  1. 글에 대한 이해가 잘 안되서 그런데 저기서 정확히 시차를 측정하는 방식이 무엇인지 알려주실 수 있나요?
    또 저기서 blocksize를 조절하는것으로 잡음을 개선할 수 있다고 하셨는데 blocksize를 조절하면 disparity 에 어떤 변화가 생기나요?

    1. 안녕하세요.
      저도 이 기능에 대한 세세한 구현방법은 모릅니다.
      오픈소스인 OpenCV에 블랙박스화되어 있으니 분석해 보시기 바랍니다.
      그리고 잡음이 어떻게 감쇄되는지도 blockSize 값의 변경하시면서 확인하는게 가장 정확할 것입니다.
      알고리즘을 이해하지 못한 상태인지라 이게 제 한계입니다.

  2. 안녕하세요 그냥 웹캠으로도 사용가능할까요??
    뎁스카메라가 따로 필요한지 궁금함니다!!ㄷ

    1. 스트레오 이미지를 촬영이 가능하면 웹캡도 가능하겠죠… 그런 웹캠이 있을까.. 싶습니다.. 눈깔이 하나일테니..

  3. 카메라의 working distance나 물리적인 거리가 공식에 있으나, 첨부하신 opencv 코드에는 물리적인 입력변수가 함수에 적용되지 않는것 같습니다.
    그렇다면 opencv에는 다른 거리 추정방식을 쓴것으로 추정이 되는데, 조금 혼선이 있군여.

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다