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
TensorflowTagDetection.hpp
1
12#ifndef TENSORFLOW_TAG_DETECTION_HPP
13#define TENSORFLOW_TAG_DETECTION_HPP
14
15#include "../../util/vision/YOLOModel.hpp"
16
19#include <opencv2/opencv.hpp>
20#include <vector>
21
23
24
33{
34
43 {
44 public:
45 // Declare public struct member attributes.
46 cv::Point2f CornerTL; // The top left corner of the bounding box.
47 cv::Point2f CornerTR; // The top right corner of the bounding box.
48 cv::Point2f CornerBL; // The bottom left corner of the bounding box.
49 cv::Point2f CornerBR; // The bottom right corner of bounding box.
50 double dConfidence = 0.0; // The detection confidence of the tag reported from the tensorflow model.
51 double dStraightLineDistance = 0.0; // Distance between the tag and the camera.
52 double dYawAngle = 0.0; // This is the yaw angle so roll and pitch are ignored.
53 };
54
55
65 {
66 // Average of the four corners
67 cv::Point2f cvCenter(0, 0);
68
69 // Add each tag x, y to the center x, y.
70 cvCenter.x += stTag.CornerBL.x + stTag.CornerBR.x + stTag.CornerTL.x + stTag.CornerTR.x;
71 cvCenter.y += stTag.CornerBL.y + stTag.CornerBR.y + stTag.CornerTL.y + stTag.CornerTR.y;
72 // Divide by number of corners.
73 cvCenter.x /= 4;
74 cvCenter.y /= 4;
75
76 // Return a copy of the center point of the tag.
77 return cvCenter;
78 }
79
80
94 inline std::vector<TensorflowTag> Detect(const cv::Mat& cvFrame,
95 yolomodel::tensorflow::TPUInterpreter& tfTensorflowDetector,
96 const float fMinObjectConfidence = 0.40f,
97 const float fNMSThreshold = 0.60f)
98 {
99 // Check if the input frame is in RGB format.
100 if (cvFrame.channels() != 3)
101 {
102 // Submit logger message.
103 LOG_ERROR(logging::g_qSharedLogger, "Detect() requires a RGB image.");
104 return {};
105 }
106
107 // Declare instance variables.
108 std::vector<TensorflowTag> vDetectedTags;
109
110 // Check if the tensorflow TPU interpreter hardware is opened and the model is loaded.
111 if (tfTensorflowDetector.GetDeviceIsOpened())
112 {
113 // Run inference on YOLO model with current image.
114 std::vector<std::vector<yolomodel::Detection>> vOutputTensorTags = tfTensorflowDetector.Inference(cvFrame, fMinObjectConfidence, fNMSThreshold);
115
116 // Repackage detections into tensorflow tags.
117 for (std::vector<yolomodel::Detection> vTagDetections : vOutputTensorTags)
118 {
119 // Loop through each detection.
120 for (yolomodel::Detection stTagDetection : vTagDetections)
121 {
122 // Create and initialize new TensorflowTag.
123 TensorflowTag stDetectedTag;
124 stDetectedTag.dConfidence = stTagDetection.fConfidence;
125 stDetectedTag.CornerTL = cv::Point2f(stTagDetection.cvBoundingBox.x, stTagDetection.cvBoundingBox.y);
126 stDetectedTag.CornerTR = cv::Point2f(stTagDetection.cvBoundingBox.x + stTagDetection.cvBoundingBox.width, stTagDetection.cvBoundingBox.y);
127 stDetectedTag.CornerBL = cv::Point2f(stTagDetection.cvBoundingBox.x, stTagDetection.cvBoundingBox.y + stTagDetection.cvBoundingBox.height);
128 stDetectedTag.CornerBR = cv::Point2f(stTagDetection.cvBoundingBox.x + stTagDetection.cvBoundingBox.width,
129 stTagDetection.cvBoundingBox.y + stTagDetection.cvBoundingBox.height);
130
131 // Add TensorflowTag to return vector.
132 vDetectedTags.emplace_back(stDetectedTag);
133 }
134 }
135 }
136 else
137 {
138 // Submit logger message.
139 LOG_WARNING(logging::g_qSharedLogger,
140 "TensorflowDetect: Unable to detect tags using YOLO tensorflow detection because hardware is not opened or model is not initialized.");
141 }
142
143 // Return the detected tags.
144 return vDetectedTags;
145 }
146
147
159 inline void DrawDetections(cv::Mat& cvDetectionsFrame, const std::vector<TensorflowTag>& vDetectedTags)
160 {
161 // Check if the given frame is a 1 or 3 channel image. (not BGRA)
162 if (!cvDetectionsFrame.empty() && (cvDetectionsFrame.channels() == 1 || cvDetectionsFrame.channels() == 3))
163 {
164 // Loop through each detection.
165 for (TensorflowTag stTag : vDetectedTags)
166 {
167 // Draw bounding box onto image.
168 cv::rectangle(cvDetectionsFrame, stTag.CornerTL, stTag.CornerBR, cv::Scalar(255, 255, 255), 2);
169 // Draw classID background box onto image.
170 cv::rectangle(cvDetectionsFrame,
171 cv::Point(stTag.CornerTL.x, stTag.CornerTL.y - 20),
172 cv::Point(stTag.CornerTR.x, stTag.CornerTL.y),
173 cv::Scalar(255, 255, 255),
174 cv::FILLED);
175 // Draw class text onto image.
176 cv::putText(cvDetectionsFrame,
177 "Tag Conf: " + std::to_string(stTag.dConfidence),
178 cv::Point(stTag.CornerTL.x, stTag.CornerTL.y - 5),
180 0.5,
181 cv::Scalar(0, 0, 0));
182 }
183 }
184 else
185 {
186 // Submit logger message.
187 LOG_ERROR(logging::g_qSharedLogger,
188 "TensorflowDetect: Unable to draw markers on image because it is empty or because it has {} channels. (Should be 1 or 3)",
189 cvDetectionsFrame.channels());
190 }
191 }
192
193
205 inline void EstimatePoseFromPointCloud(const cv::Mat& cvPointCloud, TensorflowTag& stTag)
206 {
207 // Confirm correct coordinate system.
208 if (constants::ZED_COORD_SYSTEM != sl::COORDINATE_SYSTEM::LEFT_HANDED_Y_UP)
209 {
210 // Submit logger message.
211 LOG_CRITICAL(logging::g_qSharedLogger, "TensorflowDetection: Calculations won't work for anything other than ZED coordinate system == LEFT_HANDED_Y_UP");
212 }
213
214 // Find the center point of the given tag.
215 cv::Point2f cvCenter = FindTagCenter(stTag);
216
217 // Ensure the detected center is inside the domain of the point cloud.
218 if (cvCenter.y > cvPointCloud.rows || cvCenter.x > cvPointCloud.cols || cvCenter.y < 0 || cvCenter.x < 0)
219 {
220 LOG_ERROR(logging::g_qSharedLogger,
221 "Detected tag center ({}, {}) out of point cloud's domain ({},{})",
222 cvCenter.y,
223 cvCenter.x,
224 cvPointCloud.rows,
225 cvPointCloud.cols);
226 return;
227 }
228
229 // Get tag center point location relative to the camera. Point cloud location stores float x, y, z, BGRA.
230 cv::Vec4f cvCoordinate = cvPointCloud.at<cv::Vec4f>(cvCenter.y, cvCenter.x);
231 float fForward = cvCoordinate[2]; // Z
232 float fRight = cvCoordinate[0]; // X
233 float fUp = cvCoordinate[1]; // Y
234
235 // Calculate euclidean distance from ZED camera left eye to the point of interest
236 stTag.dStraightLineDistance = sqrt(pow(fForward, 2) + pow(fRight, 2) + pow(fUp, 2));
237
238 // Calculate the angle on plane horizontal to the viewpoint
239 stTag.dYawAngle = atan2(fRight, fForward);
240 }
241} // namespace tensorflowtag
242
243#endif
bool GetDeviceIsOpened() const
Accessor for the Device Is Opened private member.
Definition TensorflowTPU.hpp:347
int channels() const
_Tp & at(int i0=0)
bool empty() const
This class is designed to enable quick, easy, and robust inferencing of .tflite yolo model.
Definition YOLOModel.hpp:210
std::vector< std::vector< Detection > > Inference(const cv::Mat &cvInputFrame, const float fMinObjectConfidence=0.85, const float fNMSThreshold=0.6) override
Given an input image forward the image through the YOLO model to run inference on the EdgeTPU,...
Definition YOLOModel.hpp:270
void sqrt(InputArray src, OutputArray dst)
void pow(InputArray src, double power, OutputArray dst)
Point_< float > Point2f
__device__ __forceinline__ float1 atan2(const uchar1 &a, const uchar1 &b)
void rectangle(InputOutputArray img, Point pt1, Point pt2, const Scalar &color, int thickness=1, int lineType=LINE_8, int shift=0)
void putText(InputOutputArray img, const String &text, Point org, int fontFace, double fontScale, Scalar color, int thickness=1, int lineType=LINE_8, bool bottomLeftOrigin=false)
FONT_HERSHEY_SIMPLEX
Namespace containing functions related to tensorflow tag detections operations on images.
Definition TensorflowTagDetection.hpp:33
cv::Point2f FindTagCenter(const TensorflowTag &stTag)
Given an TensorflowTag struct find the center point of the corners.
Definition TensorflowTagDetection.hpp:64
void DrawDetections(cv::Mat &cvDetectionsFrame, const std::vector< TensorflowTag > &vDetectedTags)
Given a vector of TensorflowTag structs draw each tag corner and confidence onto the given image.
Definition TensorflowTagDetection.hpp:159
void EstimatePoseFromPointCloud(const cv::Mat &cvPointCloud, TensorflowTag &stTag)
Estimate the pose of a position with respect to the observer using a point cloud.
Definition TensorflowTagDetection.hpp:205
std::vector< TensorflowTag > Detect(const cv::Mat &cvFrame, yolomodel::tensorflow::TPUInterpreter &tfTensorflowDetector, const float fMinObjectConfidence=0.40f, const float fNMSThreshold=0.60f)
Detect ArUco tags in the provided image using a YOLO DNN model.
Definition TensorflowTagDetection.hpp:94
Represents a single ArUco tag. Stores all information about a specific tag detection.
Definition TensorflowTagDetection.hpp:43
This struct is used to.
Definition YOLOModel.hpp:42