[OpenCV] 07-4. Depth Map from Stereo Images
🐍Python/OpenCV

[OpenCV] 07-4. Depth Map from Stereo Images

728x90
반응형

< 7-4. Depth Map from Stereo Images >

이번 세션에서는

  • 스테레오 이미지로부터 depth map(깊이)를 생성하는 것을 배워볼 것이다.

Basics

이전 세션에서, epipolar constraints와 다른 관련된 용어들의 기초 개념을 봤다. 그리고 같은 장면의 두 개의 이미지를 가지고 있다면, 직관적인 방법으로 깊이 정보를 얻을 수 있다는 것 또한 봤었다. 아래의 이미지와 간단한 수식들은 이 직관을 증명해준다.



위의 도형은 등가 삼각형(각이 전부 60도)이다. 이 등가식을 적는 것은 다음과 같은 결과를 도출해내게 한다.


disparity=xx=BfZ

x x는 3D 포인트에 해당하는 이미지 평면에서의 점과 해당 카메라 중심 사이의 거리이다.(x,y축으로 생각) B는 두 카메라간의 거리이고 f는 카메라의 focal length이다. 요약하자면, 위의 등식은 3D에서 점의 깊이(Z)가 해당 이미지와 해당 카메라 중심의 거리 차이(xx)에 반비례한다고 말한다. (Z가 증가하면 xx의 값이 줄어들기 때문) 그래서 이 정보들로, 이미지에서 모든 픽셀의 깊이를 알아낼 수 있다.

그래서 두 이미지 사이에서 일치하는 매치들을 찾는다. 우리는 이미 epiline constraint가 어떻게 이 기능을 빠르고 정확하게 만드는지 봤었다. 일단 매치를 찾으면, 그 차이(불일치)를 발견하게 된다. OpenCV와 함께 보자!

Code

아래 코드 조각은 disparity map을 생성하는 과정을 간단하게 보여준다.

이미지는 OpenCV Github에서~

튜토리얼 코드가 아닌 더 자세한 코드로 리뷰해볼 것이다.

일단 기존 튜토리얼 코드와 결과를 먼저 보자

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

imgL = cv2.imread("./images/eiffel1.jpg",0)
h,w = imgL.shape
imgR = cv2.imread("./images/eiffel2.jpg",0)
imgR = cv2.resize(imgR,(w,h))

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


depth를 나타내는 이미지들이 discrete한 모습을 볼 수 있다. 속도는 SGBM보다 빠르지만 성능이 좋지 못한 것(노이즈)을 볼 수 있다. 그래도 하이퍼파라미터를 조정해가면서 품질을 높일 수 있다. 물론 원본 이미지의 각도 차이도 큰 영향을 미치긴 할 것이다.

이제 속도는 좀 느리지만 성능은 더 나은 SGBM 방법을 보자.

Reference : http://timosam.com/python_opencv_depthimage

import numpy as np
import cv2
import matplotlib.pyplot as plt
from sklearn.preprocessing import normalize

imgL = cv2.imread("./images/eiffel1.jpg",0)
h,w = imgL.shape
imgR = cv2.imread("./images/eiffel2.jpg",0)
imgR = cv2.resize(imgR,(w,h))

window_size = 3 

left_matcher = cv2.StereoSGBM_create(minDisparity=0,numDisparities = 160,
                                  blockSize = 25,
                                  P1=8*3*window_size **2,
                                  P2=32*3*window_size **2,
                                  disp12MaxDiff = 1,
                                  uniquenessRatio = 15,
                                  speckleWindowSize=0,
                                  speckleRange=2,
                                  preFilterCap=63,
                                  mode=cv2.STEREO_SGBM_MODE_SGBM_3WAY)

right_matcher = cv2.ximgproc.createRightMatcher(left_matcher)

lmbda = 80000
sigma = 1.2
visual_multiplyer = 1.0

# Weighted Least Squares(WLS) filter는 모서리를 보존하는 smoothing 기술로 잘 알려져있다
# 하지만 가중치는 이미지의 gradients에 크게 의존한다는 단점이 있다. 
# isotropy와 gradients를 기준으로 하는 것이 픽셀의 smoothing 가중치를 계산하는데 도움이 된다. 

wls_filter = cv2.ximgproc.createDisparityWLSFilter(matcher_left = left_matcher)
wls_filter.setLambda(lmbda)
wls_filter.setSigmaColor(sigma)

disp_left = left_matcher.compute(imgL,imgR)
disp_right = right_matcher.compute(imgR,imgL)
disp_left = np.int16(disp_left)
disp_right = np.int16(disp_right)

# 여기에 imgL을 넣는 것이 중요!
filteredImg = wls_filter.filter(disp_left,imgL,None,disp_right)

filteredImg = cv2.normalize(src=filteredImg, dst=filteredImg,
                            beta = 0, alpha = 255, norm_type=cv2.NORM_MINMAX)
filteredImg = np.uint8(filteredImg)
cv2.imwrite("filtered.jpg",filteredImg)

cv2.imshow("Left Image",imgL)
cv2.imshow("st_Disparity Map",filteredImg)

cv2.waitKey()
cv2.destroyAllWindows()

cv2.StereoSGBM_create의 파라미터들을 살펴보자

  • minDisparity : 가능한 최소한의 disparity 값이다. 보통 0으로 설정하지만 조정 알고리즘이 이미지를 이동시킬 수 있어서 이 파라미터는 알맞게 조정되어야 한다.
  • numDisparities : 최대 disparity 빼기 최소 disparity. 항상 0보다 큰 값을 갖는다.
  • blockSize : 매칭된 블록 사이즈이다. 1보다 큰 홀수여야한다. 보통 3~11의 값을 갖는다.
  • P1 : diparity smoothness를 조절하는 첫 파라미터이다.
  • P2 : diparity smoothness를 조절하는 두 번째 파라미터이다. 값이 커지면, 더 부드러워진다. P1은 인접 픽셀 사이를 +1 or -1로 바꿔주는 disparity 패널티이다(P1 is the penalty on the disparity change by plus or minus 1 between neighbor pixels). P2는 인접 픽셀 사이에서 1보다 크게 변화하는 것에 대한 패널티이다.(P1 is the penalty on the disparity change by plus or minus 1 between neighbor pixels). P2 > P1이어야 한다.
  • disp12MAxDiff : 좌-우 disparity 체크에서 허용된 최대 차이이다. 비활성화 하려면 음수를 설정하면 된다.
  • uniquenessRatio : 보통 5~15의 값을 갖는게 좋다. 1등 매치(cost function 비교)와 2등 매치간의 마진을 퍼센트로 나타낸 것이다.
  • speckleWindowSize : 노이즈 반점(speckle) 및 무효화를 고려하는 smooth disparity 영역의 최대 크기이다. 0로 두면 실행 안함. 보통 50-200의 범위를 가진다
  • speckleRange : 각 연결된 요소들 내에서 최대 disparity 변동이다. speckle 필터링을 한다면, 양수로 설정하고, 이는 16과 곱해질 것이기다. 보통 1,2면 좋다.
  • preFilterCap : 필터링된 이미지 픽셀을 위한 Truncation(절단) 값이다.
  • mode : cv2.STEREO_SGBM_MODE_HH를 사용하여 전체 스케일에 대해 동적 프로그래밍 알고리즘을 실행한다. 이는 기본값이다.


원본 이미지


위 코드 결과



blocksize = 27 / MODE_HH


blocksize = 27 / MODE_HH4


blocksize = 27 / MODE_SGBM_3WAY



728x90
반응형