20 #define _USE_MATH_DEFINES
22 #include <opencv2/calib3d/calib3d.hpp>
23 #include <opencv2/imgproc/imgproc.hpp>
39 Rvec.create(3, 1, CV_32FC1);
40 Tvec.create(3, 1, CV_32FC1);
41 for (
int i = 0; i < 3; i++)
42 Tvec.at<
float>(i, 0) =
Rvec.at<
float>(i, 0) = -999999;
51 Rvec.create(3, 1, CV_32FC1);
52 Tvec.create(3, 1, CV_32FC1);
53 for (
int i = 0; i < 3; i++)
54 Tvec.at<
float>(i, 0) =
Rvec.at<
float>(i, 0) = -999999;
68 :
std::vector<cv::Point2f>(corners)
72 Rvec.create(3, 1, CV_32FC1);
73 Tvec.create(3, 1, CV_32FC1);
74 for (
int i = 0; i < 3; i++)
75 Tvec.at<
float>(i, 0) =
Rvec.at<
float>(i, 0) = -999999;
87 for (
size_t i = 0; i < size(); i++)
105 bool invalid =
false;
106 for (
int i = 0; i < 3 && !invalid; i++)
108 if (
Tvec.at<
float>(i, 0) != -999999)
110 if (
Rvec.at<
float>(i, 0) != -999999)
114 throw cv::Exception(9003,
"extrinsic parameters are not set",
115 "Marker::getModelViewMatrix", __FILE__, __LINE__);
116 cv::Mat Rot(3, 3, CV_32FC1), Jacob;
117 cv::Rodrigues(
Rvec, Rot, Jacob);
120 for (
int i = 0; i < 3; i++)
121 for (
int j = 0; j < 3; j++)
122 para[i][j] = Rot.at<
float>(i, j);
124 para[0][3] =
Tvec.at<
float>(0, 0);
125 para[1][3] =
Tvec.at<
float>(1, 0);
126 para[2][3] =
Tvec.at<
float>(2, 0);
129 modelview_matrix[0 + 0 * 4] = para[0][0];
131 modelview_matrix[0 + 1 * 4] = para[0][1];
132 modelview_matrix[0 + 2 * 4] = para[0][2];
133 modelview_matrix[0 + 3 * 4] = para[0][3];
135 modelview_matrix[1 + 0 * 4] = para[1][0];
136 modelview_matrix[1 + 1 * 4] = para[1][1];
137 modelview_matrix[1 + 2 * 4] = para[1][2];
138 modelview_matrix[1 + 3 * 4] = para[1][3];
140 modelview_matrix[2 + 0 * 4] = -para[2][0];
141 modelview_matrix[2 + 1 * 4] = -para[2][1];
142 modelview_matrix[2 + 2 * 4] = -para[2][2];
143 modelview_matrix[2 + 3 * 4] = -para[2][3];
144 modelview_matrix[3 + 0 * 4] = 0.0;
145 modelview_matrix[3 + 1 * 4] = 0.0;
146 modelview_matrix[3 + 2 * 4] = 0.0;
147 modelview_matrix[3 + 3 * 4] = 1.0;
150 modelview_matrix[12] *= scale;
151 modelview_matrix[13] *= scale;
152 modelview_matrix[14] *= scale;
162 bool invalid =
false;
163 for (
int i = 0; i < 3 && !invalid; i++)
165 if (
Tvec.at<
float>(i, 0) != -999999)
167 if (
Rvec.at<
float>(i, 0) != -999999)
171 throw cv::Exception(9003,
"extrinsic parameters are not set",
172 "Marker::getModelViewMatrix", __FILE__, __LINE__);
175 position[0] = -
Tvec.ptr<
float>(0)[0];
176 position[1] = -
Tvec.ptr<
float>(0)[1];
177 position[2] = +
Tvec.ptr<
float>(0)[2];
180 cv::Mat Rot(3, 3, CV_32FC1);
181 cv::Rodrigues(
Rvec, Rot);
186 stAxes[0][0] = -Rot.at<
float>(0, 0);
187 stAxes[0][1] = -Rot.at<
float>(1, 0);
188 stAxes[0][2] = +Rot.at<
float>(2, 0);
190 stAxes[1][0] = -Rot.at<
float>(0, 1);
191 stAxes[1][1] = -Rot.at<
float>(1, 1);
192 stAxes[1][2] = +Rot.at<
float>(2, 1);
194 stAxes[2][0] = stAxes[0][1] * stAxes[1][2] - stAxes[0][2] * stAxes[1][1];
195 stAxes[2][1] = -stAxes[0][0] * stAxes[1][2] + stAxes[0][2] * stAxes[1][0];
196 stAxes[2][2] = stAxes[0][0] * stAxes[1][1] - stAxes[0][1] * stAxes[1][0];
200 axes[0][0] = stAxes[0][0];
201 axes[1][0] = stAxes[0][1];
202 axes[2][0] = stAxes[0][2];
204 axes[0][1] = stAxes[1][0];
205 axes[1][1] = stAxes[1][1];
206 axes[2][1] = stAxes[1][2];
208 axes[0][2] = stAxes[2][0];
209 axes[1][2] = stAxes[2][1];
210 axes[2][2] = stAxes[2][2];
214 double fTrace = axes[0][0] + axes[1][1] + axes[2][2];
220 fRoot = sqrt(fTrace + 1.0);
221 orientation[0] = 0.5 * fRoot;
223 orientation[1] = (axes[2][1] - axes[1][2]) * fRoot;
224 orientation[2] = (axes[0][2] - axes[2][0]) * fRoot;
225 orientation[3] = (axes[1][0] - axes[0][1]) * fRoot;
230 static unsigned int s_iNext[3] = { 1, 2, 0 };
232 if (axes[1][1] > axes[0][0])
234 if (axes[2][2] > axes[i][i])
236 unsigned int j = s_iNext[i];
237 unsigned int k = s_iNext[j];
239 fRoot = sqrt(axes[i][i] - axes[j][j] - axes[k][k] + 1.0);
240 double* apkQuat[3] = { &orientation[1], &orientation[2], &orientation[3] };
241 *apkQuat[i] = 0.5 * fRoot;
243 orientation[0] = (axes[k][j] - axes[j][k]) * fRoot;
244 *apkQuat[j] = (axes[j][i] + axes[i][j]) * fRoot;
245 *apkQuat[k] = (axes[k][i] + axes[i][k]) * fRoot;
249 void Marker::draw(cv::Mat& in, cv::Scalar color,
int lineWidth,
bool writeId,
bool writeInfo)
const
251 auto _to_string = [](
int i)
253 std::stringstream str;
260 float flineWidth = lineWidth;
262 flineWidth = std::max(1.
f, std::min(5.
f,
float(in.cols) / 500.f));
263 lineWidth = round(flineWidth);
264 cv::line(in, (*
this)[0], (*
this)[1], color, lineWidth);
265 cv::line(in, (*
this)[1], (*
this)[2], color, lineWidth);
266 cv::line(in, (*
this)[2], (*
this)[3], color, lineWidth);
267 cv::line(in, (*
this)[3], (*
this)[0], color, lineWidth);
270 cv::Point2f(2.
f *
static_cast<float>(lineWidth), 2.
f *
static_cast<float>(lineWidth));
271 cv::rectangle(in, (*
this)[0] - p2, (*
this)[0] + p2, cv::Scalar(0, 0, 255, 255), -1);
272 cv::rectangle(in, (*
this)[1] - p2, (*
this)[1] + p2, cv::Scalar(0, 255, 0, 255), lineWidth);
273 cv::rectangle(in, (*
this)[2] - p2, (*
this)[2] + p2, cv::Scalar(255, 0, 0, 255), lineWidth);
280 cv::Point cent(0, 0);
281 for (
int i = 0; i < 4; i++)
283 cent.x +=
static_cast<int>((*this)[i].x);
284 cent.y +=
static_cast<int>((*this)[i].y);
292 str += _to_string(
id);
293 float fsize = std::min(3.0
f, flineWidth * 0.75
f);
294 cv::putText(in, str, cent - cv::Point(10 * flineWidth, 0), cv::FONT_HERSHEY_SIMPLEX,
295 fsize, cv::Scalar(255, 255, 255) - color, lineWidth, cv::LINE_AA);
304 throw cv::Exception(9004,
"!CP.isValid(): invalid camera parameters. It is not possible to calculate extrinsics",
305 "calculateExtrinsics", __FILE__, __LINE__);
310 void print(cv::Point3f p, std::string cad)
312 std::cout << cad <<
" " << p.x <<
" " << p.y <<
" " << p.z << std::endl;
317 cv::Mat Extrinsics,
bool setYPerpendicular,
bool correctFisheye)
320 throw cv::Exception(9004,
"!isValid(): invalid marker. It is not possible to calculate extrinsics",
321 "calculateExtrinsics", __FILE__, __LINE__);
322 if (markerSizeMeters <= 0)
323 throw cv::Exception(9004,
"markerSize<=0: invalid markerSize",
"calculateExtrinsics",
325 if (camMatrix.rows == 0 || camMatrix.cols == 0)
326 throw cv::Exception(9004,
"CameraMatrix is empty",
"calculateExtrinsics", __FILE__, __LINE__);
328 std::vector<cv::Point3f> objpoints =
get3DPoints(markerSizeMeters);
333 std::vector<cv::Point2f> undistorted;
334 cv::fisheye::undistortPoints(*
this, undistorted, camMatrix, distCoeff);
335 cv::solvePnP(objpoints, undistorted, cv::Mat::eye(camMatrix.size(), camMatrix.type()),
336 cv::Mat::zeros(distCoeff.size(), distCoeff.type()), raux, taux);
340 cv::solvePnP(objpoints, *
this, camMatrix, distCoeff, raux, taux);
342 raux.convertTo(
Rvec, CV_32F);
343 taux.convertTo(
Tvec, CV_32F);
344 float tx = -1 * (Extrinsics.at<
double>(0, 0) / camMatrix.at<
float>(0, 0));
345 Tvec.at<
float>(0) += tx;
346 float ty = -1 * (Extrinsics.at<
double>(0, 1) / camMatrix.at<
float>(1, 1));
347 Tvec.at<
float>(1) += ty;
348 float tz = -1 * (Extrinsics.at<
double>(0, 2) / camMatrix.at<
float>(2, 2));
349 Tvec.at<
float>(2) += tz;
352 if (setYPerpendicular)
354 ssize = markerSizeMeters;
361 float halfSize = msize / 2.f;
368 return { cv::Point3f(-halfSize, halfSize, 0), cv::Point3f(halfSize, halfSize, 0),
369 cv::Point3f(halfSize, -halfSize, 0), cv::Point3f(-halfSize, -halfSize, 0) };
374 cv::Mat R(3, 3, CV_32F);
375 cv::Rodrigues(rotation, R);
377 cv::Mat RX = cv::Mat::eye(3, 3, CV_32F);
378 const float angleRad = 3.14159265359f / 2.f;
379 RX.at<
float>(1, 1) = cos(angleRad);
380 RX.at<
float>(1, 2) = -sin(angleRad);
381 RX.at<
float>(2, 1) = sin(angleRad);
382 RX.at<
float>(2, 2) = cos(angleRad);
386 Rodrigues(R, rotation);
393 cv::Point2f cent(0, 0);
394 for (
size_t i = 0; i < size(); i++)
396 cent.x += (*this)[i].x;
397 cent.y += (*this)[i].y;
399 cent.x /= float(size());
400 cent.y /= float(size());
410 cv::Point2f v01 = (*this)[1] - (*this)[0];
411 cv::Point2f v03 = (*this)[3] - (*this)[0];
412 float area1 = fabs(v01.x * v03.y - v01.y * v03.x);
413 cv::Point2f v21 = (*this)[1] - (*this)[2];
414 cv::Point2f v23 = (*this)[3] - (*this)[2];
415 float area2 = fabs(v21.x * v23.y - v21.y * v23.x);
416 return (area2 + area1) / 2.f;
424 for (
int i = 0; i < 4; i++)
425 sum +=
static_cast<float>(norm((*
this)[i] - (*
this)[(i + 1) % 4]));
433 assert(
Rvec.type() == CV_32F &&
Tvec.type() == CV_32F);
434 str.write((
char*)&
id,
sizeof(
id));
436 str.write((
char*)
Rvec.ptr<
float>(0), 3 *
sizeof(
float));
437 str.write((
char*)
Tvec.ptr<
float>(0), 3 *
sizeof(
float));
439 uint32_t np =
static_cast<uint32_t
>(size());
440 str.write((
char*)&np,
sizeof(np));
441 for (
size_t i = 0; i < size(); i++)
442 str.write((
char*)&at(i),
sizeof(cv::Point2f));
445 str.write((
char*)&s,
sizeof(s));
448 str.write((
char*)&s,
sizeof(s));
454 Rvec.create(1, 3, CV_32F);
455 Tvec.create(1, 3, CV_32F);
456 str.read((
char*)&
id,
sizeof(
id));
458 str.read((
char*)
Rvec.ptr<
float>(0), 3 *
sizeof(
float));
459 str.read((
char*)
Tvec.ptr<
float>(0), 3 *
sizeof(
float));
461 str.read((
char*)&np,
sizeof(np));
463 for (
size_t i = 0; i < size(); i++)
464 str.read((
char*)&(*this)[i],
sizeof(cv::Point2f));
467 str.read((
char*)&s,
sizeof(s));
470 str.read((
char*)&s,
sizeof(s));
477 cv::Mat T = cv::Mat::eye(4, 4, CV_32F);
478 cv::Mat rot = T.rowRange(0, 3).colRange(0, 3);
479 cv::Rodrigues(
Rvec, rot);
480 for (
int i = 0; i < 3; i++)
481 T.at<
float>(i, 3) =
Tvec.ptr<
float>(0)[i];
491 maxDist = std::max(maxDist,
float(cv::norm(p - center)));