24#include <opencv2/calib3d.hpp>
25#include <opencv2/core.hpp>
26#include <opencv2/imgproc.hpp>
30#define OPENCV_DISABLE_EIGEN_TENSOR_SUPPORT
31#include <opencv2/core/eigen.hpp>
40 (Eigen::Matrix3d() << 0, -1, 0, 0, 0, -1, 1, 0, 0).finished()};
42 (Eigen::Matrix3d() << 0, 0, 1, -1, 0, 0, 0, -1, 0).finished()};
45 const std::vector<cv::Point2f>& points) {
46 std::vector<int> outputHull{};
47 cv::convexHull(points, outputHull);
48 std::vector<cv::Point2f> convexPoints;
49 for (
size_t i = 0; i < outputHull.size(); i++) {
50 convexPoints.push_back(points[outputHull[i]]);
56 const std::vector<cv::Point2f>& points) {
57 return cv::minAreaRect(points);
61 const wpi::math::Translation3d& trl) {
66 const wpi::math::Rotation3d& rot) {
71 const std::vector<wpi::math::Translation3d>& translations) {
72 std::vector<cv::Point3f> retVal;
73 retVal.reserve(translations.size());
74 for (
size_t i = 0; i < translations.size(); i++) {
76 retVal.emplace_back(cv::Point3f{trl.X().to<
float>(), trl.Y().to<
float>(),
77 trl.Z().to<
float>()});
83 const wpi::math::Rotation3d& rotation) {
84 std::vector<cv::Point3f> retVal{};
86 retVal.emplace_back(cv::Point3d{
87 rot.GetQuaternion().ToRotationVector()(0),
88 rot.GetQuaternion().ToRotationVector()(1),
89 rot.GetQuaternion().ToRotationVector()(2),
94[[maybe_unused]]
static cv::Point2f
AvgPoint(std::vector<cv::Point2f> points) {
95 if (points.size() == 0) {
98 cv::reduce(points, points, 0, cv::REDUCE_AVG);
103 const std::vector<cv::Point2f>& points) {
104 std::vector<photon::TargetCorner> retVal;
105 retVal.reserve(points.size());
106 for (
size_t i = 0; i < points.size(); i++) {
113 const std::vector<cv::Point2f>& points) {
114 std::vector<std::pair<float, float>> retVal;
115 retVal.reserve(points.size());
116 for (
size_t i = 0; i < points.size(); i++) {
117 retVal.emplace_back(std::make_pair(points[i].x, points[i].y));
123 const std::vector<std::pair<float, float>>& corners) {
124 std::vector<cv::Point2f> retVal;
125 retVal.reserve(corners.size());
126 for (
size_t i = 0; i < corners.size(); i++) {
127 retVal.emplace_back(cv::Point2f{corners[i].first, corners[i].second});
133 const std::vector<photon::TargetCorner>& corners) {
134 std::vector<cv::Point2f> retVal;
135 retVal.reserve(corners.size());
136 for (
size_t i = 0; i < corners.size(); i++) {
137 retVal.emplace_back(cv::Point2f{
static_cast<float>(corners[i].x),
138 static_cast<float>(corners[i].y)});
144 const std::vector<cv::Point2f>& points) {
145 return cv::boundingRect(points);
149 const Eigen::Matrix<double, 3, 3>& cameraMatrix,
150 const Eigen::Matrix<double, 8, 1>& distCoeffs,
152 const std::vector<wpi::math::Translation3d>& objectTranslations) {
156 cv::Mat cameraMat(cameraMatrix.rows(), cameraMatrix.cols(), CV_64F);
157 cv::eigen2cv(cameraMatrix, cameraMat);
158 cv::Mat distCoeffsMat(distCoeffs.rows(), distCoeffs.cols(), CV_64F);
159 cv::eigen2cv(distCoeffs, distCoeffsMat);
160 std::vector<cv::Point2f> imagePoints{};
161 cv::projectPoints(objectPoints, rvec, tvec, cameraMat, distCoeffsMat,
168 bool backwards,
int shiftStart) {
169 size_t size = elements.size();
170 int dir = backwards ? -1 : 1;
171 std::vector<T> reordered{elements};
172 for (
size_t i = 0; i < size; i++) {
173 int index = (i * dir + shiftStart * dir) % size;
175 index = size + index;
177 reordered[i] = elements[index];
183 const wpi::math::Translation3d& trl) {
188 const wpi::math::Rotation3d& rot) {
194 cv::Mat wrapped{tvecInput.rows, tvecInput.cols, CV_32F};
195 tvecInput.convertTo(wrapped, CV_32F);
196 data = wrapped.at<cv::Vec3f>(cv::Point{0, 0});
198 wpi::units::meter_t{data[0]}, wpi::units::meter_t{data[1]},
199 wpi::units::meter_t{data[2]}});
204 cv::Mat wrapped{rvecInput.rows, rvecInput.cols, CV_32F};
205 rvecInput.convertTo(wrapped, CV_32F);
206 data = wrapped.at<cv::Vec3f>(cv::Point{0, 0});
208 wpi::math::Rotation3d{Eigen::Vector3d{data[0], data[1], data[2]}});
212 const Eigen::Matrix<double, 3, 3>& cameraMatrix,
213 const Eigen::Matrix<double, 8, 1>& distCoeffs,
214 std::vector<wpi::math::Translation3d> modelTrls,
215 std::vector<cv::Point2f> imagePoints) {
219 std::vector<cv::Mat> rvecs;
220 std::vector<cv::Mat> tvecs;
221 cv::Mat rvec = cv::Mat::zeros(3, 1, CV_32F);
222 cv::Mat tvec = cv::Mat::zeros(3, 1, CV_32F);
223 cv::Mat reprojectionError = cv::Mat::zeros(2, 1, CV_32F);
225 cv::Mat cameraMat(cameraMatrix.rows(), cameraMatrix.cols(), CV_32F);
226 cv::eigen2cv(cameraMatrix, cameraMat);
227 cv::Mat distCoeffsMat(distCoeffs.rows(), distCoeffs.cols(), CV_32F);
228 cv::eigen2cv(distCoeffs, distCoeffsMat);
231 wpi::math::Transform3d best{};
232 std::optional<wpi::math::Transform3d> alt{std::nullopt};
234 for (
int tries = 0; tries < 2; tries++) {
235 cv::solvePnPGeneric(objectMat, imagePoints, cameraMat, distCoeffsMat, rvecs,
236 tvecs,
false, cv::SOLVEPNP_IPPE_SQUARE, rvec, tvec,
239 errors = reprojectionError.at<cv::Vec2f>(cv::Point{0, 0});
243 if (tvecs.size() > 1) {
248 if (!std::isnan(errors[0])) {
251 cv::Point2f pt = imagePoints[0];
258 if (std::isnan(errors[0])) {
259 fmt::print(
"SolvePNP_Square failed!\n");
265 result.
alt = alt.value();
266 result.
ambiguity = errors[0] / errors[1];
279 const Eigen::Matrix<double, 3, 3>& cameraMatrix,
280 const Eigen::Matrix<double, 8, 1>& distCoeffs,
281 std::vector<wpi::math::Translation3d> modelTrls,
282 std::vector<cv::Point2f> imagePoints) {
284 std::vector<cv::Mat> rvecs{};
285 std::vector<cv::Mat> tvecs{};
286 cv::Mat rvec = cv::Mat::zeros(3, 1, CV_32F);
287 cv::Mat tvec = cv::Mat::zeros(3, 1, CV_32F);
288 cv::Mat reprojectionError = cv::Mat::zeros(2, 1, CV_32F);
290 cv::Mat cameraMat(cameraMatrix.rows(), cameraMatrix.cols(), CV_64F);
291 cv::eigen2cv(cameraMatrix, cameraMat);
292 cv::Mat distCoeffsMat(distCoeffs.rows(), distCoeffs.cols(), CV_64F);
293 cv::eigen2cv(distCoeffs, distCoeffsMat);
296 wpi::math::Transform3d best{};
298 cv::solvePnPGeneric(objectMat, imagePoints, cameraMat, distCoeffsMat, rvecs,
299 tvecs,
false, cv::SOLVEPNP_SQPNP, rvec, tvec,
302 error = reprojectionError.at<
float>(cv::Point{0, 0});
306 if (std::isnan(error)) {
307 fmt::print(
"SolvePNP_Square failed!\n");
Definition TargetCorner.h:25
static cv::RotatedRect GetMinAreaRect(const std::vector< cv::Point2f > &points)
Definition OpenCVHelp.h:55
static std::vector< cv::Point3f > TranslationToTVec(const std::vector< wpi::math::Translation3d > &translations)
Definition OpenCVHelp.h:70
static wpi::math::Translation3d TVecToTranslation(const cv::Mat &tvecInput)
Definition OpenCVHelp.h:192
static std::vector< photon::TargetCorner > PointsToTargetCorners(const std::vector< cv::Point2f > &points)
Definition OpenCVHelp.h:102
static wpi::math::Rotation3d RotationNWUtoEDN(const wpi::math::Rotation3d &rot)
Definition OpenCVHelp.h:65
static cv::Point2f AvgPoint(std::vector< cv::Point2f > points)
Definition OpenCVHelp.h:94
static std::optional< photon::PnpResult > SolvePNP_SQPNP(const Eigen::Matrix< double, 3, 3 > &cameraMatrix, const Eigen::Matrix< double, 8, 1 > &distCoeffs, std::vector< wpi::math::Translation3d > modelTrls, std::vector< cv::Point2f > imagePoints)
Definition OpenCVHelp.h:278
static std::vector< cv::Point3f > RotationToRVec(const wpi::math::Rotation3d &rotation)
Definition OpenCVHelp.h:82
static wpi::math::Translation3d TranslationEDNToNWU(const wpi::math::Translation3d &trl)
Definition OpenCVHelp.h:182
static cv::Rect GetBoundingRect(const std::vector< cv::Point2f > &points)
Definition OpenCVHelp.h:143
static std::optional< photon::PnpResult > SolvePNP_Square(const Eigen::Matrix< double, 3, 3 > &cameraMatrix, const Eigen::Matrix< double, 8, 1 > &distCoeffs, std::vector< wpi::math::Translation3d > modelTrls, std::vector< cv::Point2f > imagePoints)
Definition OpenCVHelp.h:211
static std::vector< cv::Point2f > ProjectPoints(const Eigen::Matrix< double, 3, 3 > &cameraMatrix, const Eigen::Matrix< double, 8, 1 > &distCoeffs, const RotTrlTransform3d &camRt, const std::vector< wpi::math::Translation3d > &objectTranslations)
Definition OpenCVHelp.h:148
static wpi::math::Translation3d TranslationNWUtoEDN(const wpi::math::Translation3d &trl)
Definition OpenCVHelp.h:60
static wpi::math::Rotation3d EDN_TO_NWU
Definition OpenCVHelp.h:41
static std::vector< std::pair< float, float > > PointsToCorners(const std::vector< cv::Point2f > &points)
Definition OpenCVHelp.h:112
static std::vector< T > ReorderCircular(const std::vector< T > elements, bool backwards, int shiftStart)
Definition OpenCVHelp.h:167
static wpi::math::Rotation3d RVecToRotation(const cv::Mat &rvecInput)
Definition OpenCVHelp.h:202
static wpi::math::Rotation3d NWU_TO_EDN
Definition OpenCVHelp.h:39
static std::vector< cv::Point2f > GetConvexHull(const std::vector< cv::Point2f > &points)
Definition OpenCVHelp.h:44
static wpi::math::Rotation3d RotationEDNToNWU(const wpi::math::Rotation3d &rot)
Definition OpenCVHelp.h:187
static std::vector< cv::Point2f > CornersToPoints(const std::vector< std::pair< float, float > > &corners)
Definition OpenCVHelp.h:122
Definition VisionEstimation.h:30
double altReprojErr
Definition PnpResultStruct.h:40
double bestReprojErr
Definition PnpResultStruct.h:39
double ambiguity
Definition PnpResultStruct.h:41
wpi::math::Transform3d alt
Definition PnpResultStruct.h:38
wpi::math::Transform3d best
Definition PnpResultStruct.h:37
Definition PnpResult.h:26