Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
hackassin
GitHub Repository: hackassin/learnopencv
Path: blob/master/Depth-Perception-Using-Stereo-Camera/python/disparity2depth_calib.py
3142 views
1
import numpy as np
2
import cv2
3
import matplotlib
4
import matplotlib.pyplot as plt
5
6
7
# Check for left and right camera IDs
8
# These values can change depending on the system
9
CamL_id = 2 # Camera ID for left camera
10
CamR_id = 0 # Camera ID for right camera
11
12
CamL= cv2.VideoCapture(CamL_id)
13
CamR= cv2.VideoCapture(CamR_id)
14
15
# Reading the mapping values for stereo image rectification
16
cv_file = cv2.FileStorage("../data/stereo_rectify_maps.xml", cv2.FILE_STORAGE_READ)
17
Left_Stereo_Map_x = cv_file.getNode("Left_Stereo_Map_x").mat()
18
Left_Stereo_Map_y = cv_file.getNode("Left_Stereo_Map_y").mat()
19
Right_Stereo_Map_x = cv_file.getNode("Right_Stereo_Map_x").mat()
20
Right_Stereo_Map_y = cv_file.getNode("Right_Stereo_Map_y").mat()
21
cv_file.release()
22
23
# These parameters can vary according to the setup
24
# Keeping the target object at max_dist we store disparity values
25
# after every sample_delta distance.
26
max_dist = 230 # max distance to keep the target object (in cm)
27
min_dist = 50 # Minimum distance the stereo setup can measure (in cm)
28
sample_delta = 40 # Distance between two sampling points (in cm)
29
30
Z = max_dist
31
Value_pairs = []
32
33
disp_map = np.zeros((600,600,3))
34
35
36
# Reading the stored the StereoBM parameters
37
cv_file = cv2.FileStorage("../data/depth_estmation_params_py.xml", cv2.FILE_STORAGE_READ)
38
numDisparities = int(cv_file.getNode("numDisparities").real())
39
blockSize = int(cv_file.getNode("blockSize").real())
40
preFilterType = int(cv_file.getNode("preFilterType").real())
41
preFilterSize = int(cv_file.getNode("preFilterSize").real())
42
preFilterCap = int(cv_file.getNode("preFilterCap").real())
43
textureThreshold = int(cv_file.getNode("textureThreshold").real())
44
uniquenessRatio = int(cv_file.getNode("uniquenessRatio").real())
45
speckleRange = int(cv_file.getNode("speckleRange").real())
46
speckleWindowSize = int(cv_file.getNode("speckleWindowSize").real())
47
disp12MaxDiff = int(cv_file.getNode("disp12MaxDiff").real())
48
minDisparity = int(cv_file.getNode("minDisparity").real())
49
M = cv_file.getNode("M").real()
50
cv_file.release()
51
52
# Defining callback functions for mouse events
53
def mouse_click(event,x,y,flags,param):
54
global Z
55
if event == cv2.EVENT_LBUTTONDBLCLK:
56
if disparity[y,x] > 0:
57
Value_pairs.append([Z,disparity[y,x]])
58
print("Distance: %r cm | Disparity: %r"%(Z,disparity[y,x]))
59
Z-=sample_delta
60
61
62
63
cv2.namedWindow('disp',cv2.WINDOW_NORMAL)
64
cv2.resizeWindow('disp',600,600)
65
cv2.namedWindow('left image',cv2.WINDOW_NORMAL)
66
cv2.resizeWindow('left image',600,600)
67
cv2.setMouseCallback('disp',mouse_click)
68
69
# Creating an object of StereoBM algorithm
70
stereo = cv2.StereoBM_create()
71
72
while True:
73
74
# Capturing and storing left and right camera images
75
retR, imgR= CamR.read()
76
retL, imgL= CamL.read()
77
78
# Proceed only if the frames have been captured
79
if retL and retR:
80
imgR_gray = cv2.cvtColor(imgR,cv2.COLOR_BGR2GRAY)
81
imgL_gray = cv2.cvtColor(imgL,cv2.COLOR_BGR2GRAY)
82
83
# Applying stereo image rectification on the left image
84
Left_nice= cv2.remap(imgL_gray,
85
Left_Stereo_Map_x,
86
Left_Stereo_Map_y,
87
cv2.INTER_LANCZOS4,
88
cv2.BORDER_CONSTANT,
89
0)
90
91
# Applying stereo image rectification on the right image
92
Right_nice= cv2.remap(imgR_gray,
93
Right_Stereo_Map_x,
94
Right_Stereo_Map_y,
95
cv2.INTER_LANCZOS4,
96
cv2.BORDER_CONSTANT,
97
0)
98
99
# Setting the updated parameters before computing disparity map
100
stereo.setNumDisparities(numDisparities)
101
stereo.setBlockSize(blockSize)
102
stereo.setPreFilterType(preFilterType)
103
stereo.setPreFilterSize(preFilterSize)
104
stereo.setPreFilterCap(preFilterCap)
105
stereo.setTextureThreshold(textureThreshold)
106
stereo.setUniquenessRatio(uniquenessRatio)
107
stereo.setSpeckleRange(speckleRange)
108
stereo.setSpeckleWindowSize(speckleWindowSize)
109
stereo.setDisp12MaxDiff(disp12MaxDiff)
110
stereo.setMinDisparity(minDisparity)
111
112
# Calculating disparity using the StereoBM algorithm
113
disparity = stereo.compute(Left_nice,Right_nice)
114
# NOTE: compute returns a 16bit signed single channel image,
115
# CV_16S containing a disparity map scaled by 16. Hence it
116
# is essential to convert it to CV_16S and scale it down 16 times.
117
118
# Converting to float32
119
disparity = disparity.astype(np.float32)
120
121
# Scaling down the disparity values and normalizing them
122
disparity = (disparity/16.0 - minDisparity)/numDisparities
123
124
# Displaying the disparity map
125
cv2.imshow("disp",disparity)
126
cv2.imshow("left image",imgL)
127
128
if cv2.waitKey(1) == 27:
129
break
130
131
if Z < min_dist:
132
break
133
134
else:
135
CamL= cv2.VideoCapture(CamL_id)
136
CamR= cv2.VideoCapture(CamR_id)
137
138
# solving for M in the following equation
139
# || depth = M * (1/disparity) ||
140
# for N data points coeff is Nx2 matrix with values
141
# 1/disparity, 1
142
# and depth is Nx1 matrix with depth values
143
144
value_pairs = np.array(Value_pairs)
145
z = value_pairs[:,0]
146
disp = value_pairs[:,1]
147
disp_inv = 1/disp
148
149
# Plotting the relation depth and corresponding disparity
150
fig, (ax1,ax2) = plt.subplots(1,2,figsize=(12,6))
151
ax1.plot(disp, z, 'o-')
152
ax1.set(xlabel='Normalized disparity value', ylabel='Depth from camera (cm)',
153
title='Relation between depth \n and corresponding disparity')
154
ax1.grid()
155
ax2.plot(disp_inv, z, 'o-')
156
ax2.set(xlabel='Inverse disparity value (1/disp) ', ylabel='Depth from camera (cm)',
157
title='Relation between depth \n and corresponding inverse disparity')
158
ax2.grid()
159
plt.show()
160
161
162
# Solving for M using least square fitting with QR decomposition method
163
coeff = np.vstack([disp_inv, np.ones(len(disp_inv))]).T
164
ret, sol = cv2.solve(coeff,z,flags=cv2.DECOMP_QR)
165
M = sol[0,0]
166
C = sol[1,0]
167
print("Value of M = ",M)
168
169
170
# Storing the updated value of M along with the stereo parameters
171
cv_file = cv2.FileStorage("../data/depth_estmation_params_py.xml", cv2.FILE_STORAGE_WRITE)
172
cv_file.write("numDisparities",numDisparities)
173
cv_file.write("blockSize",blockSize)
174
cv_file.write("preFilterType",preFilterType)
175
cv_file.write("preFilterSize",preFilterSize)
176
cv_file.write("preFilterCap",preFilterCap)
177
cv_file.write("textureThreshold",textureThreshold)
178
cv_file.write("uniquenessRatio",uniquenessRatio)
179
cv_file.write("speckleRange",speckleRange)
180
cv_file.write("speckleWindowSize",speckleWindowSize)
181
cv_file.write("disp12MaxDiff",disp12MaxDiff)
182
cv_file.write("minDisparity",minDisparity)
183
cv_file.write("M",M)
184
cv_file.release()
185