115 int tagId,
const std::vector<cv::Point2f>& dstPoints,
bool antialiasing,
116 cv::Mat& destination) {
122 std::vector<cv::Point2f> tagImageCorners{
GetImageCorners(tagImage.size())};
123 std::vector<cv::Point2f> dstPointMat = dstPoints;
124 cv::Rect boundingRect = cv::boundingRect(dstPointMat);
125 cv::Mat perspecTrf = cv::getPerspectiveTransform(tagPoints, dstPointMat);
126 std::vector<cv::Point2f> extremeCorners{};
127 cv::perspectiveTransform(tagImageCorners, extremeCorners, perspecTrf);
128 boundingRect = cv::boundingRect(extremeCorners);
130 double warpedContourArea = cv::contourArea(extremeCorners);
131 double warpedTagUpscale =
132 std::sqrt(warpedContourArea) / std::sqrt(tagImage.size().area());
133 int warpStrat = cv::INTER_NEAREST;
135 int supersampling = 6;
136 supersampling =
static_cast<int>(std::ceil(supersampling / warpedTagUpscale));
137 supersampling = std::max(std::min(supersampling, 10), 1);
139 cv::Mat scaledTagImage{};
140 if (warpedTagUpscale > 2.0) {
141 warpStrat = cv::INTER_LINEAR;
142 int scaleFactor =
static_cast<int>(warpedTagUpscale / 3.0) + 2;
143 scaleFactor = std::max(std::min(scaleFactor, 40), 1);
144 scaleFactor *= supersampling;
145 cv::resize(tagImage, scaledTagImage, cv::Size{}, scaleFactor, scaleFactor,
149 scaledTagImage = tagImage;
154 boundingRect.width += 2;
155 boundingRect.height += 2;
156 if (boundingRect.x < 0) {
157 boundingRect.width += boundingRect.x;
160 if (boundingRect.y < 0) {
161 boundingRect.height += boundingRect.y;
165 std::min(destination.size().width - boundingRect.x, boundingRect.width);
166 boundingRect.height =
167 std::min(destination.size().height - boundingRect.y, boundingRect.height);
168 if (boundingRect.width <= 0 || boundingRect.height <= 0) {
172 std::vector<cv::Point2f> scaledDstPts{};
173 if (supersampling > 1) {
174 cv::multiply(dstPointMat,
175 cv::Scalar{
static_cast<double>(supersampling),
176 static_cast<double>(supersampling)},
178 boundingRect.x *= supersampling;
179 boundingRect.y *= supersampling;
180 boundingRect.width *= supersampling;
181 boundingRect.height *= supersampling;
183 scaledDstPts = dstPointMat;
186 cv::subtract(scaledDstPts,
187 cv::Scalar{
static_cast<double>(boundingRect.tl().x),
188 static_cast<double>(boundingRect.tl().y)},
190 perspecTrf = cv::getPerspectiveTransform(tagPoints, scaledDstPts);
193 cv::warpPerspective(scaledTagImage, tempRoi, perspecTrf, boundingRect.size(),
196 if (supersampling > 1) {
197 boundingRect.x /= supersampling;
198 boundingRect.y /= supersampling;
199 boundingRect.width /= supersampling;
200 boundingRect.height /= supersampling;
201 cv::resize(tempRoi, tempRoi, boundingRect.size(), 0, 0, cv::INTER_AREA);
204 cv::Mat tempMask{cv::Mat::zeros(tempRoi.size(), CV_8UC1)};
205 cv::subtract(extremeCorners,
206 cv::Scalar{
static_cast<float>(boundingRect.tl().x),
207 static_cast<float>(boundingRect.tl().y)},
209 cv::Point2f tempCenter{};
211 std::accumulate(extremeCorners.begin(), extremeCorners.end(), 0.0,
212 [extremeCorners](
float acc,
const cv::Point2f& p2) {
213 return acc + p2.x / extremeCorners.size();
216 std::accumulate(extremeCorners.begin(), extremeCorners.end(), 0.0,
217 [extremeCorners](
float acc,
const cv::Point2f& p2) {
218 return acc + p2.y / extremeCorners.size();
221 for (
auto& corner : extremeCorners) {
222 float xDiff = corner.x - tempCenter.x;
223 float yDiff = corner.y - tempCenter.y;
226 corner = cv::Point2f{tempCenter.x + xDiff, tempCenter.y + yDiff};
229 std::vector<cv::Point> extremeCornerInt{extremeCorners.begin(),
230 extremeCorners.end()};
231 cv::fillConvexPoly(tempMask, extremeCornerInt, cv::Scalar{255});
233 cv::copyTo(tempRoi, destination(boundingRect), tempMask);
266 int id,
const std::vector<cv::Point2f>& dstPoints, cv::Mat& destination) {
268 DrawPoly(dstPoints,
static_cast<int>(thickness), cv::Scalar{0, 0, 255},
true,
270 cv::Rect2d rect{cv::boundingRect(dstPoints)};
271 cv::Point2d textPt{rect.x + rect.width, rect.y};
272 textPt.x += thickness;
273 textPt.y += thickness;
274 cv::putText(destination, std::to_string(
id), textPt, cv::FONT_HERSHEY_PLAIN,
275 1.5 * thickness, cv::Scalar{0, 200, 0},
276 static_cast<int>(thickness), cv::LINE_AA);
280 std::vector<std::vector<frc::Translation3d>> list;
282 const units::meter_t sideHt = 19.5_in;
283 const units::meter_t driveHt = 35_in;
284 const units::meter_t topHt = 78_in;
287 list.emplace_back(std::vector<frc::Translation3d>{
288 frc::Translation3d{0_m, 0_m, 0_m},
292 frc::Translation3d{0_m, 0_m, 0_m}});
295 list.emplace_back(std::vector<frc::Translation3d>{
296 frc::Translation3d{0_m, 0_m, 0_m}, frc::Translation3d{0_m, 0_m, sideHt},
301 list.emplace_back(std::vector<frc::Translation3d>{
307 list.emplace_back(std::vector<frc::Translation3d>{
312 list.emplace_back(std::vector<frc::Translation3d>{
319 list.emplace_back(std::vector<frc::Translation3d>{
320 frc::Translation3d{0_m, 0_m, sideHt},
321 frc::Translation3d{0_m, 0_m, topHt},
325 list.emplace_back(std::vector<frc::Translation3d>{
326 frc::Translation3d{0_m, 0_m, driveHt},
327 frc::Translation3d{0_m,
fieldWidth, driveHt}});
334 std::vector<std::vector<frc::Translation3d>> list;
335 const units::meter_t subLength =
fieldLength / subdivisions;
336 const units::meter_t subWidth =
fieldWidth / subdivisions;
338 for (
int i = 0; i < subdivisions; i++) {
339 list.emplace_back(std::vector<frc::Translation3d>{
340 frc::Translation3d{0_m, subWidth * (i + 1), 0_m},
341 frc::Translation3d{
fieldLength, subWidth * (i + 1), 0_m}});
342 list.emplace_back(std::vector<frc::Translation3d>{
343 frc::Translation3d{subLength * (i + 1), 0_m, 0_m},
344 frc::Translation3d{subLength * (i + 1),
fieldWidth, 0_m}});
351 const std::vector<frc::Translation3d>& trls,
double resolution,
352 bool isClosed, cv::Mat& destination) {
353 resolution = std::hypot(destination.size().height, destination.size().width) *
355 std::vector<frc::Translation3d> pts{trls};
357 pts.emplace_back(pts[0]);
359 std::vector<std::vector<cv::Point2f>> polyPointList{};
361 for (
size_t i = 0; i < pts.size() - 1; i++) {
362 frc::Translation3d pta = pts[i];
363 frc::Translation3d ptb = pts[i + 1];
365 std::pair<std::optional<double>, std::optional<double>> inter =
371 double inter1 = inter.first.value();
372 double inter2 = inter.second.value();
373 frc::Translation3d baseDelta = ptb - pta;
374 frc::Translation3d old_pta = pta;
376 pta = old_pta + baseDelta * inter1;
379 ptb = old_pta + baseDelta * inter2;
381 baseDelta = ptb - pta;
385 cv::Point2d pxa = poly[0];
386 cv::Point2d pxb = poly[1];
388 double pxDist = std::hypot(pxb.x - pxa.x, pxb.y - pxa.y);
389 int subdivisions =
static_cast<int>(pxDist / resolution);
390 frc::Translation3d subDelta = baseDelta / (subdivisions + 1);
391 std::vector<frc::Translation3d> subPts{};
392 for (
int j = 0; j < subdivisions; j++) {
393 subPts.emplace_back(pta + (subDelta * (j + 1)));
395 if (subPts.size() > 0) {
398 poly.insert(poly.begin() + 1, toAdd.begin(), toAdd.end());
401 polyPointList.emplace_back(poly);
404 return polyPointList;