114 int tagId,
const std::vector<cv::Point2f>& dstPoints,
bool antialiasing,
115 cv::Mat& destination) {
121 std::vector<cv::Point2f> tagImageCorners{
GetImageCorners(tagImage.size())};
122 std::vector<cv::Point2f> dstPointMat = dstPoints;
123 cv::Rect boundingRect = cv::boundingRect(dstPointMat);
124 cv::Mat perspecTrf = cv::getPerspectiveTransform(tagPoints, dstPointMat);
125 std::vector<cv::Point2f> extremeCorners{};
126 cv::perspectiveTransform(tagImageCorners, extremeCorners, perspecTrf);
127 boundingRect = cv::boundingRect(extremeCorners);
129 double warpedContourArea = cv::contourArea(extremeCorners);
130 double warpedTagUpscale =
131 std::sqrt(warpedContourArea) / std::sqrt(tagImage.size().area());
132 int warpStrat = cv::INTER_NEAREST;
134 int supersampling = 6;
135 supersampling =
static_cast<int>(std::ceil(supersampling / warpedTagUpscale));
136 supersampling = std::max(std::min(supersampling, 10), 1);
138 cv::Mat scaledTagImage{};
139 if (warpedTagUpscale > 2.0) {
140 warpStrat = cv::INTER_LINEAR;
141 int scaleFactor =
static_cast<int>(warpedTagUpscale / 3.0) + 2;
142 scaleFactor = std::max(std::min(scaleFactor, 40), 1);
143 scaleFactor *= supersampling;
144 cv::resize(tagImage, scaledTagImage, cv::Size{}, scaleFactor, scaleFactor,
148 scaledTagImage = tagImage;
153 boundingRect.width += 2;
154 boundingRect.height += 2;
155 if (boundingRect.x < 0) {
156 boundingRect.width += boundingRect.x;
159 if (boundingRect.y < 0) {
160 boundingRect.height += boundingRect.y;
164 std::min(destination.size().width - boundingRect.x, boundingRect.width);
165 boundingRect.height =
166 std::min(destination.size().height - boundingRect.y, boundingRect.height);
167 if (boundingRect.width <= 0 || boundingRect.height <= 0) {
171 std::vector<cv::Point2f> scaledDstPts{};
172 if (supersampling > 1) {
173 cv::multiply(dstPointMat,
174 cv::Scalar{
static_cast<double>(supersampling),
175 static_cast<double>(supersampling)},
177 boundingRect.x *= supersampling;
178 boundingRect.y *= supersampling;
179 boundingRect.width *= supersampling;
180 boundingRect.height *= supersampling;
182 scaledDstPts = dstPointMat;
185 cv::subtract(scaledDstPts,
186 cv::Scalar{
static_cast<double>(boundingRect.tl().x),
187 static_cast<double>(boundingRect.tl().y)},
189 perspecTrf = cv::getPerspectiveTransform(tagPoints, scaledDstPts);
192 cv::warpPerspective(scaledTagImage, tempRoi, perspecTrf, boundingRect.size(),
195 if (supersampling > 1) {
196 boundingRect.x /= supersampling;
197 boundingRect.y /= supersampling;
198 boundingRect.width /= supersampling;
199 boundingRect.height /= supersampling;
200 cv::resize(tempRoi, tempRoi, boundingRect.size(), 0, 0, cv::INTER_AREA);
203 cv::Mat tempMask{cv::Mat::zeros(tempRoi.size(), CV_8UC1)};
204 cv::subtract(extremeCorners,
205 cv::Scalar{
static_cast<float>(boundingRect.tl().x),
206 static_cast<float>(boundingRect.tl().y)},
208 cv::Point2f tempCenter{};
210 std::accumulate(extremeCorners.begin(), extremeCorners.end(), 0.0,
211 [extremeCorners](
float acc,
const cv::Point2f& p2) {
212 return acc + p2.x / extremeCorners.size();
215 std::accumulate(extremeCorners.begin(), extremeCorners.end(), 0.0,
216 [extremeCorners](
float acc,
const cv::Point2f& p2) {
217 return acc + p2.y / extremeCorners.size();
220 for (
auto& corner : extremeCorners) {
221 float xDiff = corner.x - tempCenter.x;
222 float yDiff = corner.y - tempCenter.y;
225 corner = cv::Point2f{tempCenter.x + xDiff, tempCenter.y + yDiff};
228 std::vector<cv::Point> extremeCornerInt{extremeCorners.begin(),
229 extremeCorners.end()};
230 cv::fillConvexPoly(tempMask, extremeCornerInt, cv::Scalar{255});
232 cv::copyTo(tempRoi, destination(boundingRect), tempMask);
265 int id,
const std::vector<cv::Point2f>& dstPoints, cv::Mat& destination) {
267 DrawPoly(dstPoints,
static_cast<int>(thickness), cv::Scalar{0, 0, 255},
true,
269 cv::Rect2d rect{cv::boundingRect(dstPoints)};
270 cv::Point2d textPt{rect.x + rect.width, rect.y};
271 textPt.x += thickness;
272 textPt.y += thickness;
273 cv::putText(destination, std::to_string(
id), textPt, cv::FONT_HERSHEY_PLAIN,
274 1.5 * thickness, cv::Scalar{0, 200, 0},
275 static_cast<int>(thickness), cv::LINE_AA);
279 std::vector<std::vector<frc::Translation3d>> list;
281 const units::meter_t sideHt = 19.5_in;
282 const units::meter_t driveHt = 35_in;
283 const units::meter_t topHt = 78_in;
286 list.emplace_back(std::vector<frc::Translation3d>{
287 frc::Translation3d{0_m, 0_m, 0_m},
291 frc::Translation3d{0_m, 0_m, 0_m}});
294 list.emplace_back(std::vector<frc::Translation3d>{
295 frc::Translation3d{0_m, 0_m, 0_m}, frc::Translation3d{0_m, 0_m, sideHt},
300 list.emplace_back(std::vector<frc::Translation3d>{
306 list.emplace_back(std::vector<frc::Translation3d>{
311 list.emplace_back(std::vector<frc::Translation3d>{
318 list.emplace_back(std::vector<frc::Translation3d>{
319 frc::Translation3d{0_m, 0_m, sideHt},
320 frc::Translation3d{0_m, 0_m, topHt},
324 list.emplace_back(std::vector<frc::Translation3d>{
325 frc::Translation3d{0_m, 0_m, driveHt},
326 frc::Translation3d{0_m,
fieldWidth, driveHt}});
333 std::vector<std::vector<frc::Translation3d>> list;
334 const units::meter_t subLength =
fieldLength / subdivisions;
335 const units::meter_t subWidth =
fieldWidth / subdivisions;
337 for (
int i = 0; i < subdivisions; i++) {
338 list.emplace_back(std::vector<frc::Translation3d>{
339 frc::Translation3d{0_m, subWidth * (i + 1), 0_m},
340 frc::Translation3d{
fieldLength, subWidth * (i + 1), 0_m}});
341 list.emplace_back(std::vector<frc::Translation3d>{
342 frc::Translation3d{subLength * (i + 1), 0_m, 0_m},
343 frc::Translation3d{subLength * (i + 1),
fieldWidth, 0_m}});
350 const std::vector<frc::Translation3d>& trls,
double resolution,
351 bool isClosed, cv::Mat& destination) {
352 resolution = std::hypot(destination.size().height, destination.size().width) *
354 std::vector<frc::Translation3d> pts{trls};
356 pts.emplace_back(pts[0]);
358 std::vector<std::vector<cv::Point2f>> polyPointList{};
360 for (
size_t i = 0; i < pts.size() - 1; i++) {
361 frc::Translation3d pta = pts[i];
362 frc::Translation3d ptb = pts[i + 1];
364 std::pair<std::optional<double>, std::optional<double>> inter =
370 double inter1 = inter.first.value();
371 double inter2 = inter.second.value();
372 frc::Translation3d baseDelta = ptb - pta;
373 frc::Translation3d old_pta = pta;
375 pta = old_pta + baseDelta * inter1;
378 ptb = old_pta + baseDelta * inter2;
380 baseDelta = ptb - pta;
384 cv::Point2d pxa = poly[0];
385 cv::Point2d pxb = poly[1];
387 double pxDist = std::hypot(pxb.x - pxa.x, pxb.y - pxa.y);
388 int subdivisions =
static_cast<int>(pxDist / resolution);
389 frc::Translation3d subDelta = baseDelta / (subdivisions + 1);
390 std::vector<frc::Translation3d> subPts{};
391 for (
int j = 0; j < subdivisions; j++) {
392 subPts.emplace_back(pta + (subDelta * (j + 1)));
394 if (subPts.size() > 0) {
397 poly.insert(poly.begin() + 1, toAdd.begin(), toAdd.end());
400 polyPointList.emplace_back(poly);
403 return polyPointList;