def write_ply(fn, verts, colors):
 
	verts = verts.reshape(-1, 3)
	colors = colors.reshape(-1, 3)
	verts = np.hstack([verts, colors])
	
	with open(fn, 'wb') as f:
		f.write((ply_header % dict(vert_num=len(verts))).encode('utf-8'))
		np.savetxt(f, verts, fmt='%f %f %f %d %d %d ')
def main():
 
	print('loading images...')
	
	imgL = cv2.imread("/workspace/dataset/processed/left/000100.jpg", 0)
	imgR = cv2.imread("/workspace/dataset/processed/right/000100.jpg", 0)
	
	imgL = cv2.resize(imgL, (500, 500))
	imgR = cv2.resize(imgR, (500, 500))
	
	# disparity range is tuned for 'aloe' image pair
	window_size = 3
	min_disp = 16
	num_disp = 112-min_disp
	
	stereo = cv2.StereoSGBM_create(
		minDisparity = min_disp,
		numDisparities = num_disp,
		blockSize = 16,
		P1 = 8*3*window_size**2,
		P2 = 32*3*window_size**2,
		disp12MaxDiff = 1,
		uniquenessRatio = 10,
		speckleWindowSize = 100,
		speckleRange = 32
	)
	
	print('computing disparity...')
	disp = stereo.compute(imgL, imgR).astype(np.float32) / 16.0
	
	print('generating 3d point cloud...',)
	h, w = imgL.shape[:2]
	f = 0.8*w # guess for focal length
	Q = np.float32(
		[[1, 0, 0, -0.5*w],
		[0,-1, 0, 0.5*h], # turn points 180 deg around x-axis,
		[0, 0, 0, -f], # so that y-axis looks up
		[0, 0, 1, 0]]
	)
	points = cv2.reprojectImageTo3D(disp, Q)
	colors = cv2.cvtColor(imgL, cv.COLOR_BGR2RGB)
	mask = disp > disp.min()
	out_points = points[mask]
	out_colors = colors[mask]
	out_fn = 'out.ply'
	
	write_ply(out_fn, out_points, out_colors)
	print('%s saved' % out_fn)
	
	cv2.imshow('left', imgL)
	cv2.imshow('disparity', (disp-min_disp)/num_disp)
	cv2.waitKey()
	
	print('Done')

cv2.StereoSGBM_create ํŒŒ๋ผ๋ฏธํ„ฐ

  • minDisparity
    • ๊ฐ€๋Šฅํ•œ ์ตœ์†Œํ•œ์˜ disparity ๊ฐ’
    • ๋ณดํ†ต 0์œผ๋กœ ์„ค์ •ํ•˜์ง€๋งŒ ์กฐ์ • ์•Œ๊ณ ๋ฆฌ์ฆ˜์ด ์ด๋ฏธ์ง€๋ฅผ ์ด๋™์‹œํ‚ฌ ์ˆ˜ ์žˆ์–ด์„œ ์•Œ๋งž๊ฒŒ ์กฐ์ •ํ•ด์•ผํ•จ
  • numDisparities
    • Disparity ์˜ ๋ฒ”์œ„ ์„ค์ •
    • 16 ๋ฐฐ์ˆ˜์—ฌ์•ผ ํ•˜๋ฉฐ, ์ตœ์†Œ Disparity ์—์„œ ์ตœ๋Œ€ Disparity ๊นŒ์ง€์˜ ๋ฒ”์œ„
  • blockSize
    • ๋งค์นญ์„ ์ˆ˜ํ–‰ํ•  ๋•Œ ์‚ฌ์šฉํ•˜๋Š” ๋ธ”๋ก(ํŒจ์น˜)์˜ ํฌ๊ธฐ ์ง€์ •

      collapse: true
      - ๋ธ”๋ก ๋งค์นญ
          - ๋‘ ์ด๋ฏธ์ง€์—์„œ ์œ ์‚ฌํ•œ ๋ธ”๋ก์„ ์ฐพ์•„ Disparity ๋ฅผ ๊ณ„์‚ฐํ•˜๋Š” ๊ณผ์ •
          - ์ž‘์„์ˆ˜๋ก ๋” ์„ธ๋ฐ€ํ•œ ๋งค์นญ์„ ๊ฐ€๋Šฅํ•˜๊ฒŒ ํ•˜์ง€๋งŒ, ๋…ธ์ด์ฆˆ์— ๋ฏผ๊ฐํ•  ์ˆ˜ ์žˆ์Œ
    • ํ™€์ˆ˜์—ฌ์•ผ ํ•˜๋ฉฐ, ์ผ๋ฐ˜์ ์œผ๋กœ 3~11 ์‚ฌ์ด์˜ ๊ฐ’ ์‚ฌ์šฉ

  • P1
    • Disparity map ์„ ์ƒ์„ฑํ•  ๋•Œ ์‚ฌ์šฉ๋˜๋Š” Smoothness ๋ฅผ ์กฐ์ ˆํ•˜๋Š” ํŒŒ๋ผ๋ฏธํ„ฐ
    • ์ผ๋ฐ˜์ ์œผ๋กœ 8 * # of channels * blockSize ** 2 ๋กœ ์„ค์ •
  • P2
    • Smoothness ๋ฅผ ์กฐ์ ˆํ•˜๋Š” ๋‘ ๋ฒˆ์งธ ํŒŒ๋ผ๋ฏธํ„ฐ
    • ์ผ๋ฐ˜์ ์œผ๋กœ 32 * # of channels * blockSize ** 2 ๋กœ ์„ค์ •
  • disp12MaxDiff
    • ์ขŒ์šฐ Disparity map ์˜ ์ตœ๋Œ€ ํ—ˆ์šฉ ์ฐจ์ด
    • 0 ๋˜๋Š” ์Œ์ˆ˜๋กœ ์„ค์ •ํ•  ๊ฒฝ์šฐ ํ•ด๋‹น ๊ฒ€์‚ฌ ์ƒ๋žต
  • uniquenessRatio
    • 1๋“ฑ ๋งค์น˜์™€ 2๋“ฑ ๋งค์น˜๊ฐ„์˜ ๋งˆ์ง„์„ ํผ์„ผํŠธ๋กœ ๋‚˜ํƒ€๋‚ธ ๊ฐ’
    • ์ผ๋ฐ˜์ ์œผ๋กœ 5~15 ์‚ฌ์ด ๊ฐ’
  • speckleWindowSize
    • ์ž‘์€ ์  ๋…ธ์ด์ฆˆ (Speckle) ๋ฅผ ์ œ๊ฑฐํ•˜๊ธฐ ์œ„ํ•œ ์ฐฝ์˜ ํฌ๊ธฐ
    • 0์œผ๋กœ ์„ค์ •ํ•˜๋ฉด ํ•ด๋‹น ๊ฒ€์‚ฌ ์ƒ๋žต
    • ์ผ๋ฐ˜์ ์œผ๋กœ 5~200 ์‚ฌ์ด ๊ฐ’
  • speckleRange
    • Speckle ์ œ๊ฑฐ๋ฅผ ์œ„ํ•œ Disparity ๋ฒ”์œ„๋ฅผ ์„ค์ •
      • Speckle ๋‚ด ๋ชจ๋“  Disparity ๋Š” ์ด ๊ฐ’์„ ์ดˆ๊ณผํ•˜์ง€ ์•Š์•„์•ผ ํ•จ
    • 0์œผ๋กœ ์„ค์ •ํ•˜๋ฉด ํ•ด๋‹น ๊ฒ€์‚ฌ ์ƒ๋žต
    • ์ผ๋ฐ˜์ ์œผ๋กœ 1, 2
  • preFilterCap
    • ์ž…๋ ฅ ์ด๋ฏธ์ง€์˜ ์‚ฌ์ „ ํ•„ํ„ฐ๋ง์„ ์œ„ํ•œ ์ตœ๋Œ€ ๊ฐ’
    • ์ผ๋ฐ˜์ ์œผ๋กœ 31
  • mode
    • cv2.STEREO_SGBM_MODE_SGBM
    • cv2.STEREO_SGBM_MODE_HH
    • cv2.STEREO_SGBM_MODE_SGBM_3WAY
    • cv2.STEREO_SGBM_MODE_HH4