Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
hackassin
GitHub Repository: hackassin/learnopencv
Path: blob/master/Depth-Perception-Using-Stereo-Camera/cpp/obstacle_avoidance.cpp
3142 views
1
#include <opencv2/opencv.hpp>
2
#include <opencv2/calib3d/calib3d.hpp>
3
#include <opencv2/highgui/highgui.hpp>
4
#include <opencv2/imgproc/imgproc.hpp>
5
#include <stdio.h>
6
#include <iostream>
7
#include "opencv2/imgcodecs.hpp"
8
#include <iomanip>
9
10
// initialize values for StereoSGBM parameters
11
int numDisparities = 8;
12
int blockSize = 5;
13
int preFilterType = 1;
14
int preFilterSize = 1;
15
int preFilterCap = 31;
16
int minDisparity = 0;
17
int textureThreshold = 10;
18
int uniquenessRatio = 15;
19
int speckleRange = 0;
20
int speckleWindowSize = 0;
21
int disp12MaxDiff = -1;
22
float M = 0.0;
23
24
25
cv::Mat imgL;
26
cv::Mat imgR;
27
cv::Mat imgL_gray;
28
cv::Mat imgR_gray;
29
cv::Mat disp, disparity, depth_map;
30
cv::Mat output_canvas;
31
32
// These parameters can vary according to the setup
33
float max_depth = 400.0; //maximum distance the setup can measure (in cm)
34
float min_depth = 50.0; //minimum distance the setup can measure (in cm)
35
float depth_thresh = 100.0; // Threshold for SAFE distance (in cm)
36
37
// function to sort contours from largest to smallest
38
bool compareContourAreas ( std::vector<cv::Point> contour1, std::vector<cv::Point> contour2 ) {
39
double i = fabs( cv::contourArea(cv::Mat(contour1)) );
40
double j = fabs( cv::contourArea(cv::Mat(contour2)) );
41
return ( i > j );
42
}
43
44
void obstacle_avoid()
45
{
46
cv::Mat mask, mean, stddev, mask2;
47
48
// Mask to segment regions with depth less than safe distance
49
cv::inRange(depth_map, 10, depth_thresh, mask);
50
double s = (cv::sum(mask)[0])/255.0;
51
double img_area = double(mask.rows * mask.cols);
52
53
std::vector<std::vector<cv::Point>> contours;
54
std::vector<cv::Vec4i> hierarchy;
55
56
// Check if a significantly large obstacle is present and filter out smaller noisy regions
57
if (s > 0.01*img_area)
58
{
59
// finding conoturs in the generated mask
60
cv::findContours(mask, contours, hierarchy, cv::RETR_TREE, cv::CHAIN_APPROX_SIMPLE);
61
62
// sorting contours from largest to smallest
63
std::sort(contours.begin(), contours.end(), compareContourAreas);
64
65
// extracting the largest contour
66
std::vector<cv::Point> cnt = contours[0];
67
68
// Check if detected contour is significantly large (to avoid multiple tiny regions)
69
double cnt_area = fabs( cv::contourArea(cv::Mat(cnt)));
70
if (cnt_area > 0.01*img_area)
71
{
72
cv::Rect box;
73
74
// Finding the bounding rectangle for the largest contour
75
box = cv::boundingRect(cnt);
76
77
// finding average depth of region represented by the largest contour
78
mask2 = mask*0;
79
cv::drawContours(mask2, contours, 0, (255), -1);
80
81
// Calculating the average depth of the object closer than the safe distance
82
cv::meanStdDev(depth_map, mean, stddev, mask2);
83
84
// Printing the warning text with object distance
85
char text[10];
86
std::sprintf(text, "%.2f cm",mean.at<double>(0,0));
87
88
cv::putText(output_canvas, "WARNING!", cv::Point2f(box.x + 5, box.y-40), 1, 2, cv::Scalar(0,0,255), 2, 2);
89
cv::putText(output_canvas, "Object at", cv::Point2f(box.x + 5, box.y), 1, 2, cv::Scalar(0,0,255), 2, 2);
90
cv::putText(output_canvas, text, cv::Point2f(box.x + 5, box.y+40), 1, 2, cv::Scalar(0,0,255), 2, 2);
91
92
}
93
}
94
else
95
{
96
// Printing SAFE if no obstacle is closer than the safe distance
97
cv::putText(output_canvas, "SAFE!", cv::Point2f(200,200),1,2,cv::Scalar(0,255,0),2,2);
98
}
99
100
101
// Displaying the output of the obstacle avoidance system
102
cv::imshow("output_canvas",output_canvas);
103
}
104
105
int main()
106
{
107
// Creating an object of StereoBM algorithm
108
cv::Ptr<cv::StereoBM> stereo = cv::StereoBM::create();
109
110
// Reading the stored the StereoBM parameters
111
cv::FileStorage cv_file = cv::FileStorage("../data/depth_estimation_params_cpp.xml", cv::FileStorage::READ);
112
cv_file["numDisparities"] >> numDisparities;
113
cv_file["blockSize"] >> blockSize;
114
cv_file["preFilterType"] >> preFilterType;
115
cv_file["preFilterSize"] >> preFilterSize;
116
cv_file["preFilterCap"] >> preFilterCap;
117
cv_file["minDisparity"] >> minDisparity;
118
cv_file["textureThreshold"] >> textureThreshold;
119
cv_file["uniquenessRatio"] >> uniquenessRatio;
120
cv_file["speckleRange"] >> speckleRange;
121
cv_file["speckleWindowSize"] >> speckleWindowSize;
122
cv_file["disp12MaxDiff"] >> disp12MaxDiff;
123
cv_file["M"] >> M;
124
125
// updating the parameter values of the StereoBM algorithm
126
stereo->setNumDisparities(numDisparities);
127
stereo->setBlockSize(blockSize);
128
stereo->setPreFilterType(preFilterType);
129
stereo->setPreFilterSize(preFilterSize);
130
stereo->setPreFilterCap(preFilterCap);
131
stereo->setTextureThreshold(textureThreshold);
132
stereo->setUniquenessRatio(uniquenessRatio);
133
stereo->setSpeckleRange(speckleRange);
134
stereo->setSpeckleWindowSize(speckleWindowSize);
135
stereo->setDisp12MaxDiff(disp12MaxDiff);
136
stereo->setMinDisparity(minDisparity);
137
138
//Initialize variables to store the maps for stereo rectification
139
cv::Mat Left_Stereo_Map1, Left_Stereo_Map2;
140
cv::Mat Right_Stereo_Map1, Right_Stereo_Map2;
141
142
// Reading the mapping values for stereo image rectification
143
cv::FileStorage cv_file2 = cv::FileStorage("../data/stereo_rectify_maps.xml", cv::FileStorage::READ);
144
cv_file2["Left_Stereo_Map_x"] >> Left_Stereo_Map1;
145
cv_file2["Left_Stereo_Map_y"] >> Left_Stereo_Map2;
146
cv_file2["Right_Stereo_Map_x"] >> Right_Stereo_Map1;
147
cv_file2["Right_Stereo_Map_y"] >> Right_Stereo_Map2;
148
cv_file2.release();
149
150
// Check for left and right camera IDs
151
// These values can change depending on the system
152
int CamL_id{2}; // Camera ID for left camera
153
int CamR_id{0}; // Camera ID for right camera
154
155
cv::VideoCapture camL(CamL_id), camR(CamR_id);
156
157
// Check if left camera is attched
158
if (!camL.isOpened())
159
{
160
std::cout << "Could not open camera with index : " << CamL_id << std::endl;
161
return -1;
162
}
163
164
// Check if right camera is attached
165
if (!camL.isOpened())
166
{
167
std::cout << "Could not open camera with index : " << CamL_id << std::endl;
168
return -1;
169
}
170
171
cv::namedWindow("disparity",cv::WINDOW_NORMAL);
172
cv::resizeWindow("disparity",600,600);
173
174
while (true)
175
{
176
// Capturing and storing left and right camera images
177
camL >> imgL;
178
camR >> imgR;
179
180
// copy left image to display text message for the obstacle avoidance system
181
imgL.copyTo(output_canvas);
182
183
// Converting images to grayscale
184
cv::cvtColor(imgL, imgL_gray, cv::COLOR_BGR2GRAY);
185
cv::cvtColor(imgR, imgR_gray, cv::COLOR_BGR2GRAY);
186
187
// Initialize matrix for rectified stero images
188
cv::Mat Left_nice, Right_nice;
189
190
// Applying stereo image rectification on the left image
191
cv::remap(imgL_gray,
192
Left_nice,
193
Left_Stereo_Map1,
194
Left_Stereo_Map2,
195
cv::INTER_LANCZOS4,
196
cv::BORDER_CONSTANT,
197
0);
198
// Applying stereo image rectification on the right image
199
cv::remap(imgR_gray,
200
Right_nice,
201
Right_Stereo_Map1,
202
Right_Stereo_Map2,
203
cv::INTER_LANCZOS4,
204
cv::BORDER_CONSTANT,
205
0);
206
207
// Calculating disparith using the StereoBM algorithm
208
stereo->compute(Left_nice,Right_nice,disp);
209
210
// NOTE: compute returns a 16bit signed single channel image,
211
// CV_16S containing a disparity map scaled by 16. Hence it
212
// is essential to convert it to CV_16S and scale it down 16 times.
213
214
// Converting disparity values to CV_32F from CV_16S
215
disp.convertTo(disparity,CV_32F, 1.0);
216
217
// Scaling down the disparity values and normalizing them
218
disparity = (disparity/(float)16.0 - (float)minDisparity)/((float)numDisparities);
219
220
// Calculating disparity to depth map using the following equation
221
// || depth = M * (1/disparity) ||
222
depth_map = (float)M/disparity;
223
224
// Updating the output of the obstacle avoidance system
225
obstacle_avoid();
226
227
// Displaying the disparity map
228
cv::imshow("disparity",disparity);
229
230
// Close window using esc key
231
if (cv::waitKey(1) == 27) break;
232
233
}
234
235
return 0;
236
}
237
238