79 lines
		
	
	
		
			2.2 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			79 lines
		
	
	
		
			2.2 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable File
		
	
	
	
	
| #!/usr/bin/env python
 | |
| 
 | |
| '''
 | |
| Simple example of stereo image matching and point cloud generation.
 | |
| 
 | |
| Resulting .ply file cam be easily viewed using MeshLab ( http://meshlab.sourceforge.net/ )
 | |
| '''
 | |
| 
 | |
| # Python 2/3 compatibility
 | |
| from __future__ import print_function
 | |
| 
 | |
| import numpy as np
 | |
| import cv2
 | |
| 
 | |
| ply_header = '''ply
 | |
| format ascii 1.0
 | |
| element vertex %(vert_num)d
 | |
| property float x
 | |
| property float y
 | |
| property float z
 | |
| property uchar red
 | |
| property uchar green
 | |
| property uchar blue
 | |
| end_header
 | |
| '''
 | |
| 
 | |
| 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 ')
 | |
| 
 | |
| 
 | |
| if __name__ == '__main__':
 | |
|     print('loading images...')
 | |
|     imgL = cv2.pyrDown( cv2.imread('../data/aloeL.jpg') )  # downscale images for faster processing
 | |
|     imgR = cv2.pyrDown( cv2.imread('../data/aloeR.jpg') )
 | |
| 
 | |
|     # 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, cv2.COLOR_BGR2RGB)
 | |
|     mask = disp > disp.min()
 | |
|     out_points = points[mask]
 | |
|     out_colors = colors[mask]
 | |
|     out_fn = 'out.ply'
 | |
|     write_ply('out.ply', out_points, out_colors)
 | |
|     print('%s saved' % 'out.ply')
 | |
| 
 | |
|     cv2.imshow('left', imgL)
 | |
|     cv2.imshow('disparity', (disp-min_disp)/num_disp)
 | |
|     cv2.waitKey()
 | |
|     cv2.destroyAllWindows()
 | 
