Autonomy Software C++ 24.5.1
Welcome to the Autonomy Software repository of the Mars Rover Design Team (MRDT) at Missouri University of Science and Technology (Missouri S&T)! API reference contains the source code and other resources for the development of the autonomy software for our Mars rover. The Autonomy Software project aims to compete in the University Rover Challenge (URC) by demonstrating advanced autonomous capabilities and robust navigation algorithms.
Loading...
Searching...
No Matches
ImageOperations.hpp
Go to the documentation of this file.
1
12#ifndef IMAGE_OPERATIONS_HPP
13#define IMAGE_OPERATIONS_HPP
14
16#include <opencv2/opencv.hpp>
17#include <sl/Camera.hpp>
18
20
21
29namespace imgops
30{
31
40 inline int GetSLToOpenCVMatType(const sl::MAT_TYPE slType)
41 {
42 // Create instance variables.
43 int nOpenCVType = -1;
44
45 // Map sl to cv mat type.
46 switch (slType)
47 {
48 case sl::MAT_TYPE::F32_C1: nOpenCVType = CV_32FC1; break;
49 case sl::MAT_TYPE::F32_C2: nOpenCVType = CV_32FC2; break;
50 case sl::MAT_TYPE::F32_C3: nOpenCVType = CV_32FC3; break;
51 case sl::MAT_TYPE::F32_C4: nOpenCVType = CV_32FC4; break;
52 case sl::MAT_TYPE::U16_C1: nOpenCVType = CV_16SC1; break;
53 case sl::MAT_TYPE::U8_C1: nOpenCVType = CV_8UC1; break;
54 case sl::MAT_TYPE::U8_C2: nOpenCVType = CV_8UC2; break;
55 case sl::MAT_TYPE::U8_C3: nOpenCVType = CV_8UC3; break;
56 case sl::MAT_TYPE::U8_C4: nOpenCVType = CV_8UC4; break;
57 default: break;
58 }
59
60 // Return new type.
61 return nOpenCVType;
62 }
63
64
73 inline sl::MAT_TYPE GetCVToOpenSLMatType(const int cvType)
74 {
75 // Create instance variables.
76 sl::MAT_TYPE slMatType = sl::MAT_TYPE::U8_C1;
77
78 // Map sl to cv mat type.
79 switch (cvType)
80 {
81 case CV_32FC1: slMatType = sl::MAT_TYPE::F32_C1; break;
82 case CV_32FC2: slMatType = sl::MAT_TYPE::F32_C2; break;
83 case CV_32FC3: slMatType = sl::MAT_TYPE::F32_C3; break;
84 case CV_32FC4: slMatType = sl::MAT_TYPE::F32_C4; break;
85 case CV_16SC1: slMatType = sl::MAT_TYPE::U16_C1; break;
86 case CV_8UC1: slMatType = sl::MAT_TYPE::U8_C1; break;
87 case CV_8UC2: slMatType = sl::MAT_TYPE::U8_C2; break;
88 case CV_8UC3: slMatType = sl::MAT_TYPE::U8_C3; break;
89 case CV_8UC4: slMatType = sl::MAT_TYPE::U8_C4; break;
90 }
91
92 // Return new type.
93 return slMatType;
94 }
95
96
106 inline cv::Mat ConvertSLMatToCVMat(sl::Mat& slInputMat)
107 {
108 // Since cv::Mat data requires a uchar* pointer, we get the uchar1 pointer from sl::Mat (getPtr<T>())
109 // cv::Mat and sl::Mat will share a single memory structure.
110 return cv::Mat(slInputMat.getHeight(),
111 slInputMat.getWidth(),
112 GetSLToOpenCVMatType(slInputMat.getDataType()),
113 slInputMat.getPtr<sl::uchar1>(sl::MEM::CPU),
114 slInputMat.getStepBytes(sl::MEM::CPU));
115 }
116
117
127 inline cv::cuda::GpuMat ConvertSLMatToGPUMat(sl::Mat& slInputMat)
128 {
129 // Since cv::Mat data requires a uchar* pointer, we get the uchar1 pointer from sl::Mat (getPtr<T>())
130 // cv::Mat and sl::Mat will share a single memory structure
131 return cv::cuda::GpuMat(slInputMat.getHeight(),
132 slInputMat.getWidth(),
133 GetSLToOpenCVMatType(slInputMat.getDataType()),
134 slInputMat.getPtr<sl::uchar1>(sl::MEM::GPU),
135 slInputMat.getStepBytes(sl::MEM::GPU));
136 }
137
138
148 inline sl::Mat ConvertCVMatToSLMat(cv::Mat& cvInputMat)
149 {
150 // Copy and convert the Mat and return.
151 return sl::Mat(cvInputMat.rows, cvInputMat.cols, GetCVToOpenSLMatType(cvInputMat.type()), cvInputMat.data, cvInputMat.step, sl::MEM::CPU);
152 }
153
154
164 inline sl::Mat ConvertGPUMatToSLMat(cv::cuda::GpuMat& cvInputMat)
165 {
166 // Copy and convert the Mat and return.
167 return sl::Mat(cvInputMat.rows, cvInputMat.cols, GetCVToOpenSLMatType(cvInputMat.type()), cvInputMat.data, cvInputMat.step, sl::MEM::GPU);
168 }
169
170
181 inline void SplitPointCloudColors(cv::Mat& cvInputPointCloud, cv::Mat& cvOutputColors)
182 {
183 // Initialize output color mat if necessary.
184 if (cvOutputColors.empty())
185 {
186 // Fill mat with zeros, same size as input point cloud, but with 4 char values in third dimension.
187 cvOutputColors = cv::Mat(cvInputPointCloud.rows, cvInputPointCloud.cols, CV_8UC4, cv::Scalar(0));
188 }
189 // Check if the given mat has the correct dimensions.
190 else if (cvOutputColors.rows != cvInputPointCloud.rows || cvOutputColors.cols != cvInputPointCloud.cols || cvOutputColors.channels() != 4)
191 {
192 // Submit logger error.
193 LOG_ERROR(logging::g_qSharedLogger,
194 "SplitPointCloudColors: The given point cloud cv::Mat and output colors cv::Mat do not have the same dimensions! Dimensions are: (height = {} and "
195 "{}) (width = {} and {}) (channels = {} and {})",
196 cvInputPointCloud.rows,
197 cvOutputColors.rows,
198 cvInputPointCloud.cols,
199 cvOutputColors.cols,
200 cvInputPointCloud.channels(),
201 cvOutputColors.channels());
202 }
203 // Attempt to split colors from point cloud normally.
204 else
205 {
206 // Loop through the color values of the point cloud and convert them to four char values instead of a float32.
207 for (int nY = 0; nY < cvInputPointCloud.rows; ++nY)
208 {
209 for (int nX = 0; nX < cvInputPointCloud.cols; ++nX)
210 {
211 // Get the current color value for the current pixel. Reinterpret case doesn't convert number, just copies bits.
212 unsigned int unColor = *reinterpret_cast<unsigned int*>(&cvInputPointCloud.at<cv::Vec4f>(nY, nX)[3]);
213 // Separate float32 BGRA values into four char values. Uses bitshift right and bitwise AND mask.
214 unsigned char ucB = (unColor >> 0) & 0xFF;
215 unsigned char ucG = (unColor >> 8) & 0xFF;
216 unsigned char ucR = (unColor >> 16) & 0xFF;
217 unsigned char ucA = (unColor >> 24) & 0xFF;
218
219 // Store char color values in the output mat.
220 cvOutputColors.at<cv::Vec4b>(nY, nX) = cv::Vec4b(ucB, ucG, ucR, ucA);
221 }
222 }
223 }
224 }
225
226
237 inline void CustomBilateralFilter(cv::Mat& cvInputFrame, ushort usDiameter, double dSigmaColor, double dSigmaSpace)
238 {
239 int rows = cvInputFrame.rows;
240 int cols = cvInputFrame.cols;
241
242 for (int y = 0; y < rows; y++)
243 {
244 for (int x = 0; x < cols; x++)
245 {
246 double sumIntensity = 0.0;
247 double sumWeight = 0.0;
248
249 uchar centerPixel = cvInputFrame.at<uchar>(y, x);
250
251 for (int j = -usDiameter; j <= usDiameter; j++)
252 {
253 for (int i = -usDiameter; i <= usDiameter; i++)
254 {
255 int neighborX = x + i;
256 int neighborY = y + j;
257
258 // Bound check
259 if (neighborX >= 0 && neighborX < cols && neighborY >= 0 && neighborY < rows)
260 {
261 uchar neighborPixel = cvInputFrame.at<uchar>(neighborY, neighborX);
262
263 // Calculate the spatial weight (Gaussian)
264 double spatialWeight = std::exp(-(i * i + j * j) / (2 * dSigmaSpace * dSigmaSpace));
265
266 // Calculate the intensity weight (Gaussian)
267 uchar colorDistance = std::abs(centerPixel - neighborPixel);
268 double intensityWeight = std::exp(-(colorDistance * colorDistance) / (2 * dSigmaColor * dSigmaColor));
269
270 // Calculate the bilateral weight
271 double bilateralWeight = spatialWeight * intensityWeight;
272
273 sumIntensity += bilateralWeight * neighborPixel;
274 sumWeight += bilateralWeight;
275 }
276 }
277 }
278
279 // Calculate the filtered pixel value
280 uchar filteredPixel = sumIntensity / sumWeight;
281 cvInputFrame.at<uchar>(y, x) = filteredPixel;
282 }
283 }
284 }
285
286
295 inline void ColorReduce(cv::Mat& cvFrame, int nDiv = 64)
296 {
297 // Number of lines.
298 int nLines = cvFrame.rows;
299 // Number of elements per line.
300 int nElements = cvFrame.cols * cvFrame.channels();
301
302 // Loop through each row of the image.
303 for (int nI = 0; nI < nLines; nI++)
304 {
305 // Get the address of row j.
306 uchar* chData = cvFrame.ptr<uchar>(nI);
307
308 // Loop through the elements and decrease precision.
309 for (int nJ = 0; nJ < nElements; nJ++)
310 {
311 // Process each pixel.
312 chData[nJ] = chData[nJ] / nDiv * nDiv + nDiv / 2;
313 }
314 }
315 }
316} // namespace imgops
317#endif
uchar * ptr(int i0=0)
uchar * data
int channels() const
_Tp & at(int i0=0)
MatStep step
bool empty() const
int type() const
int type() const
#define CV_32FC3
#define CV_32FC2
#define CV_32FC4
#define CV_32FC1
#define CV_16SC1
#define CV_8UC2
#define CV_8UC4
unsigned char uchar
#define CV_8UC1
#define CV_8UC3
unsigned short ushort
int rows
int cols
Namespace containing functions related to GENERAL operations on images or other large binary operatio...
Definition ImageOperations.hpp:30
sl::Mat ConvertCVMatToSLMat(cv::Mat &cvInputMat)
Convert an OpenCV cv::Mat object into a ZEDSDK sl::Mat object. This copies the mat from CPU memory to...
Definition ImageOperations.hpp:148
cv::cuda::GpuMat ConvertSLMatToGPUMat(sl::Mat &slInputMat)
Convert a ZEDSDK sl::Mat object into an OpenCV cv::cuda::GpuMat object. Keeps all Mat memory in GPU V...
Definition ImageOperations.hpp:127
sl::MAT_TYPE GetCVToOpenSLMatType(const int cvType)
Provides an easy method of mapping cv::Mat types to sl::Mat types.
Definition ImageOperations.hpp:73
void SplitPointCloudColors(cv::Mat &cvInputPointCloud, cv::Mat &cvOutputColors)
Given a cv::Mat containing X, Y, Z, and BGRA values for each pixel in the third dimension,...
Definition ImageOperations.hpp:181
sl::Mat ConvertGPUMatToSLMat(cv::cuda::GpuMat &cvInputMat)
Convert an OpenCV cv::Mat object into a ZEDSDK sl::Mat object. This copies the mat from CPU memory to...
Definition ImageOperations.hpp:164
void ColorReduce(cv::Mat &cvFrame, int nDiv=64)
Given an image and a divisor, divide the precision of the elements.
Definition ImageOperations.hpp:295
void CustomBilateralFilter(cv::Mat &cvInputFrame, ushort usDiameter, double dSigmaColor, double dSigmaSpace)
Custom implementation of bilateral filter (since openCV is slow)
Definition ImageOperations.hpp:237
int GetSLToOpenCVMatType(const sl::MAT_TYPE slType)
Provides an easy method of mapping sl::Mat types to cv::Mat types.
Definition ImageOperations.hpp:40
cv::Mat ConvertSLMatToCVMat(sl::Mat &slInputMat)
Convert a ZEDSDK sl::Mat object into an OpenCV cv::Mat object. This copies the mat from GPU memory to...
Definition ImageOperations.hpp:106