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
ArucoDetection.hpp
1
12#ifndef ARUCO_DETECTION_HPP
13#define ARUCO_DETECTION_HPP
14
15#include "../../AutonomyLogging.h"
16#include "../../util/vision/ImageOperations.hpp"
17#include "../../util/vision/TagDetectionUtilty.hpp"
18
20#include <chrono>
21#include <opencv2/imgproc.hpp>
23#include <opencv2/opencv.hpp>
24#include <vector>
25
27
28
35namespace arucotag
36{
37
49 inline void PreprocessFrame(const cv::Mat& cvInputFrame, cv::Mat& cvOutputFrame)
50 {
51 // Check if the input frame is in BGR format.
52 if (cvInputFrame.channels() != 3)
53 {
54 // Submit logger message.
55 LOG_ERROR(logging::g_qSharedLogger, "PreprocessFrame() requires a BGR image.");
56 return;
57 }
58
59 // Grayscale.
60 cv::cvtColor(cvInputFrame, cvOutputFrame, cv::COLOR_BGR2GRAY);
61 // cv::filter2D(cvOutputFrame, cvOutputFrame, -1, constants::ARUCO_EDGE_KERNEL);
62 // Reduce number of colors/gradients in the image.
63 // imgops::ColorReduce(cvOutputFrame);
64 // Denoise (Looks like bilateral filter is req. for ArUco, check speed since docs say it's slow)
65 // cv::bilateralFilter(cvInputFrame, cvInputFrame, /*diameter =*/5, /*sigmaColor =*/0.2, /*sigmaSpace =*/3);
66 // imgops::CustomBilateralFilter(cvInputFrame, 3, 0.1, 3);
67 // Deblur? (Would require determining point spread function that caused the blur)
68
69 // Threshold mask (could use OTSU or TRIANGLE, just a const threshold for now)
70 // cv::threshold(cvInputFrame, cvInputFrame, constants::ARUCO_PIXEL_THRESHOLD, constants::ARUCO_PIXEL_THRESHOLD_MAX_VALUE, cv::THRESH_BINARY);
71
72 // Super-Resolution
73 // std::string szModelPath = "ESPCN_x3.pb";
74 // std::string szModelName = "espcn";
75 // dnn_superres::DnnSuperResImpl dnSuperResModel;
76 // dnSuperResModel.readModel(/*path*/);
77 // dnSuperResModel.setModel(/*path, scale*/);
78 // dnSuperResModel.upsample(cvInputFrame, cvOutputFrame);
79 }
80
81
93 inline std::vector<tagdetectutils::ArucoTag> Detect(const cv::Mat& cvFrame, const cv::aruco::ArucoDetector& cvArucoDetector)
94 {
96 std::vector<int> vIDs;
97 std::vector<std::vector<cv::Point2f>> cvMarkerCorners, cvRejectedCandidates;
98
99 // Run Aruco detection algorithm.
100 cvArucoDetector.detectMarkers(cvFrame, cvMarkerCorners, vIDs, cvRejectedCandidates);
101
102 // Store all of the detected tags as tagdetectutils::ArucoTag.
103 std::vector<tagdetectutils::ArucoTag> vDetectedTags;
104 vDetectedTags.reserve(vIDs.size());
105
106 // Loop through each detection and build tag for it.
107 for (long unsigned int unIter = 0; unIter < vIDs.size(); unIter++)
108 {
109 // Create and initialize new tag.
110 tagdetectutils::ArucoTag stDetectedTag;
111 stDetectedTag.nID = vIDs[unIter];
112 // Copy corners.
113 stDetectedTag.pBoundingBox = std::make_shared<cv::Rect2d>(cv::boundingRect(cvMarkerCorners[unIter]));
114 stDetectedTag.eDetectionMethod = tagdetectutils::TagDetectionMethod::eOpenCV;
115 stDetectedTag.szClassName = "OpenCVTag";
116 stDetectedTag.cvImageResolution = cvFrame.size();
117
118 // Add new tag to detected tags vector.
119 vDetectedTags.push_back(stDetectedTag);
120 }
121
122 // Return the detected tags.
123 return vDetectedTags;
124 }
125
126
138 inline void DrawDetections(cv::Mat& cvDetectionsFrame, const std::vector<tagdetectutils::ArucoTag>& vDetectedTags)
139 {
140 // Check if the given frame is a 1 or 3 channel image. (not BGRA)
141 if (!cvDetectionsFrame.empty() && (cvDetectionsFrame.channels() == 1 || cvDetectionsFrame.channels() == 3))
142 {
143 // Loop through each of the given AR tags and repackage them so that the draw function can read them.
144 for (long unsigned int nIter = 0; nIter < vDetectedTags.size(); ++nIter)
145 {
146 // Check if the tag detection type is OpenCV.
147 if (vDetectedTags[nIter].eDetectionMethod == tagdetectutils::TagDetectionMethod::eOpenCV)
148 {
149 // Draw bounding box onto image.
150 cv::rectangle(cvDetectionsFrame, *vDetectedTags[nIter].pBoundingBox, cv::Scalar(0, 0, 0), 2);
151 // Draw tag ID onto image.
152 std::string szText = "TAG " + std::to_string(vDetectedTags[nIter].nID);
153 cv::Size cvTextSize = cv::getTextSize(szText, cv::FONT_HERSHEY_SIMPLEX, 0.75, 1, nullptr);
154 cv::rectangle(cvDetectionsFrame,
155 vDetectedTags[nIter].pBoundingBox->tl() - cv::Point2d(0, cvTextSize.height),
156 vDetectedTags[nIter].pBoundingBox->tl() + cv::Point2d(cvTextSize.width, 0),
157 cv::Scalar(0, 0, 0),
158 cv::FILLED);
159 cv::putText(cvDetectionsFrame, szText, vDetectedTags[nIter].pBoundingBox->tl(), cv::FONT_HERSHEY_SIMPLEX, 0.75, cv::Scalar(255, 255, 255));
160 }
161 }
162 }
163 else
164 {
165 // Submit logger message.
166 LOG_ERROR(logging::g_qSharedLogger,
167 "ArucoDetect: Unable to draw markers on image because it is empty or because it has {} channels. (Should be 1 or 3)",
168 cvDetectionsFrame.channels());
169 }
170 }
171} // namespace arucotag
172
173#endif
MatSize size
int channels() const
bool empty() const
void detectMarkers(InputArray image, OutputArrayOfArrays corners, OutputArray ids, OutputArrayOfArrays rejectedImgPoints=noArray()) const
void cvtColor(InputArray src, OutputArray dst, int code, int dstCn=0)
COLOR_BGR2GRAY
void rectangle(InputOutputArray img, Point pt1, Point pt2, const Scalar &color, int thickness=1, int lineType=LINE_8, int shift=0)
Size getTextSize(const String &text, int fontFace, double fontScale, int thickness, int *baseLine)
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
Rect boundingRect(InputArray array)
Namespace containing functions related to ArUco operations on images.
Definition ArucoDetection.hpp:36
std::vector< tagdetectutils::ArucoTag > Detect(const cv::Mat &cvFrame, const cv::aruco::ArucoDetector &cvArucoDetector)
Detect ArUco tags in the provided image.
Definition ArucoDetection.hpp:93
void DrawDetections(cv::Mat &cvDetectionsFrame, const std::vector< tagdetectutils::ArucoTag > &vDetectedTags)
Given a vector of tagdetectutils::ArucoTag structs draw each tag corner and ID onto the given image.
Definition ArucoDetection.hpp:138
void PreprocessFrame(const cv::Mat &cvInputFrame, cv::Mat &cvOutputFrame)
Preprocess images for specifically for the Aruco Detect() method. This method creates a copy of the c...
Definition ArucoDetection.hpp:49
Represents a single ArUco tag. Combines attributes from TorchTag, TensorflowTag, and the original Aru...
Definition TagDetectionUtilty.hpp:59