Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
hackassin
GitHub Repository: hackassin/learnopencv
Path: blob/master/Depth-Perception-Using-Stereo-Camera/python/obstacle_avoidance.py
3142 views
1
import numpy as np
2
import cv2
3
4
5
# Check for left and right camera IDs
6
# These values can change depending on the system
7
CamL_id = 2 # Camera ID for left camera
8
CamR_id = 0 # Camera ID for right camera
9
10
11
CamL= cv2.VideoCapture(CamL_id)
12
CamR= cv2.VideoCapture(CamR_id)
13
14
# Reading the mapping values for stereo image rectification
15
cv_file = cv2.FileStorage("../data/stereo_rectify_maps.xml", cv2.FILE_STORAGE_READ)
16
Left_Stereo_Map_x = cv_file.getNode("Left_Stereo_Map_x").mat()
17
Left_Stereo_Map_y = cv_file.getNode("Left_Stereo_Map_y").mat()
18
Right_Stereo_Map_x = cv_file.getNode("Right_Stereo_Map_x").mat()
19
Right_Stereo_Map_y = cv_file.getNode("Right_Stereo_Map_y").mat()
20
cv_file.release()
21
22
disparity = None
23
depth_map = None
24
25
# These parameters can vary according to the setup
26
max_depth = 400 # maximum distance the setup can measure (in cm)
27
min_depth = 50 # minimum distance the setup can measure (in cm)
28
depth_thresh = 100.0 # Threshold for SAFE distance (in cm)
29
30
# Reading the stored the StereoBM parameters
31
cv_file = cv2.FileStorage("../data/depth_estmation_params_py.xml", cv2.FILE_STORAGE_READ)
32
numDisparities = int(cv_file.getNode("numDisparities").real())
33
blockSize = int(cv_file.getNode("blockSize").real())
34
preFilterType = int(cv_file.getNode("preFilterType").real())
35
preFilterSize = int(cv_file.getNode("preFilterSize").real())
36
preFilterCap = int(cv_file.getNode("preFilterCap").real())
37
textureThreshold = int(cv_file.getNode("textureThreshold").real())
38
uniquenessRatio = int(cv_file.getNode("uniquenessRatio").real())
39
speckleRange = int(cv_file.getNode("speckleRange").real())
40
speckleWindowSize = int(cv_file.getNode("speckleWindowSize").real())
41
disp12MaxDiff = int(cv_file.getNode("disp12MaxDiff").real())
42
minDisparity = int(cv_file.getNode("minDisparity").real())
43
M = cv_file.getNode("M").real()
44
cv_file.release()
45
46
# mouse callback function
47
def mouse_click(event,x,y,flags,param):
48
global Z
49
if event == cv2.EVENT_LBUTTONDBLCLK:
50
print("Distance = %.2f cm"%depth_map[y,x])
51
52
53
cv2.namedWindow('disp',cv2.WINDOW_NORMAL)
54
cv2.resizeWindow('disp',600,600)
55
cv2.setMouseCallback('disp',mouse_click)
56
57
output_canvas = None
58
59
# Creating an object of StereoBM algorithm
60
stereo = cv2.StereoBM_create()
61
62
def obstacle_avoid():
63
64
# Mask to segment regions with depth less than threshold
65
mask = cv2.inRange(depth_map,10,depth_thresh)
66
67
# Check if a significantly large obstacle is present and filter out smaller noisy regions
68
if np.sum(mask)/255.0 > 0.01*mask.shape[0]*mask.shape[1]:
69
70
# Contour detection
71
contours, _ = cv2.findContours(mask, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
72
cnts = sorted(contours, key=cv2.contourArea, reverse=True)
73
74
# Check if detected contour is significantly large (to avoid multiple tiny regions)
75
if cv2.contourArea(cnts[0]) > 0.01*mask.shape[0]*mask.shape[1]:
76
77
x,y,w,h = cv2.boundingRect(cnts[0])
78
79
# finding average depth of region represented by the largest contour
80
mask2 = np.zeros_like(mask)
81
cv2.drawContours(mask2, cnts, 0, (255), -1)
82
83
# Calculating the average depth of the object closer than the safe distance
84
depth_mean, _ = cv2.meanStdDev(depth_map, mask=mask2)
85
86
# Display warning text
87
cv2.putText(output_canvas, "WARNING !", (x+5,y-40), 1, 2, (0,0,255), 2, 2)
88
cv2.putText(output_canvas, "Object at", (x+5,y), 1, 2, (100,10,25), 2, 2)
89
cv2.putText(output_canvas, "%.2f cm"%depth_mean, (x+5,y+40), 1, 2, (100,10,25), 2, 2)
90
91
else:
92
cv2.putText(output_canvas, "SAFE!", (100,100),1,3,(0,255,0),2,3)
93
94
cv2.imshow('output_canvas',output_canvas)
95
96
97
while True:
98
retR, imgR= CamR.read()
99
retL, imgL= CamL.read()
100
101
if retL and retR:
102
103
output_canvas = imgL.copy()
104
105
imgR_gray = cv2.cvtColor(imgR,cv2.COLOR_BGR2GRAY)
106
imgL_gray = cv2.cvtColor(imgL,cv2.COLOR_BGR2GRAY)
107
108
# Applying stereo image rectification on the left image
109
Left_nice= cv2.remap(imgL_gray,
110
Left_Stereo_Map_x,
111
Left_Stereo_Map_y,
112
cv2.INTER_LANCZOS4,
113
cv2.BORDER_CONSTANT,
114
0)
115
116
# Applying stereo image rectification on the right image
117
Right_nice= cv2.remap(imgR_gray,
118
Right_Stereo_Map_x,
119
Right_Stereo_Map_y,
120
cv2.INTER_LANCZOS4,
121
cv2.BORDER_CONSTANT,
122
0)
123
124
# Setting the updated parameters before computing disparity map
125
stereo.setNumDisparities(numDisparities)
126
stereo.setBlockSize(blockSize)
127
stereo.setPreFilterType(preFilterType)
128
stereo.setPreFilterSize(preFilterSize)
129
stereo.setPreFilterCap(preFilterCap)
130
stereo.setTextureThreshold(textureThreshold)
131
stereo.setUniquenessRatio(uniquenessRatio)
132
stereo.setSpeckleRange(speckleRange)
133
stereo.setSpeckleWindowSize(speckleWindowSize)
134
stereo.setDisp12MaxDiff(disp12MaxDiff)
135
stereo.setMinDisparity(minDisparity)
136
137
# Calculating disparity using the StereoBM algorithm
138
disparity = stereo.compute(Left_nice,Right_nice)
139
# NOTE: compute returns a 16bit signed single channel image,
140
# CV_16S containing a disparity map scaled by 16. Hence it
141
# is essential to convert it to CV_16S and scale it down 16 times.
142
143
# Converting to float32
144
disparity = disparity.astype(np.float32)
145
146
# Normalizing the disparity map
147
disparity = (disparity/16.0 - minDisparity)/numDisparities
148
149
depth_map = M/(disparity) # for depth in (cm)
150
151
mask_temp = cv2.inRange(depth_map,min_depth,max_depth)
152
depth_map = cv2.bitwise_and(depth_map,depth_map,mask=mask_temp)
153
154
obstacle_avoid()
155
156
cv2.resizeWindow("disp",700,700)
157
cv2.imshow("disp",disparity)
158
159
if cv2.waitKey(1) == 27:
160
break
161
162
else:
163
CamL= cv2.VideoCapture(CamL_id)
164
CamR= cv2.VideoCapture(CamR_id)
165