29 #define _USE_MATH_DEFINES 32 #include <opencv2/calib3d/calib3d.hpp> 33 #include <opencv2/highgui/highgui.hpp> 34 #include <opencv2/imgproc/imgproc.hpp> 43 Rvec.create(3, 1, CV_32FC1);
44 Tvec.create(3, 1, CV_32FC1);
45 for (
int i = 0; i < 3; i++)
46 Tvec.at<
float >(i, 0) = Rvec.at<
float >(i, 0) = -999999;
51 Marker::Marker(
const Marker &M) :
std::vector<
cv::Point2f >(M) {
61 Marker::Marker(
const std::vector< cv::Point2f > &corners,
int _id) :
std::vector<
cv::Point2f >(corners) {
64 Rvec.create(3, 1, CV_32FC1);
65 Tvec.create(3, 1, CV_32FC1);
66 for (
int i = 0; i < 3; i++)
67 Tvec.at<
float >(i, 0) =
Rvec.at<
float >(i, 0) = -999999;
76 for (
int i = 0; i < 3 && !invalid; i++) {
77 if (
Tvec.at<
float >(i, 0) != -999999)
79 if (
Rvec.at<
float >(i, 0) != -999999)
83 throw cv::Exception(9003,
"extrinsic parameters are not set",
"Marker::getModelViewMatrix", __FILE__, __LINE__);
84 Mat Rot(3, 3, CV_32FC1), Jacob;
85 Rodrigues(
Rvec, Rot, Jacob);
88 for (
int i = 0; i < 3; i++)
89 for (
int j = 0; j < 3; j++)
90 para[i][j] = Rot.at<
float >(i, j);
92 para[0][3] =
Tvec.at<
float >(0, 0);
93 para[1][3] =
Tvec.at<
float >(1, 0);
94 para[2][3] =
Tvec.at<
float >(2, 0);
97 modelview_matrix[0 + 0 * 4] = para[0][0];
99 modelview_matrix[0 + 1 * 4] = para[0][1];
100 modelview_matrix[0 + 2 * 4] = para[0][2];
101 modelview_matrix[0 + 3 * 4] = para[0][3];
103 modelview_matrix[1 + 0 * 4] = para[1][0];
104 modelview_matrix[1 + 1 * 4] = para[1][1];
105 modelview_matrix[1 + 2 * 4] = para[1][2];
106 modelview_matrix[1 + 3 * 4] = para[1][3];
108 modelview_matrix[2 + 0 * 4] = -para[2][0];
109 modelview_matrix[2 + 1 * 4] = -para[2][1];
110 modelview_matrix[2 + 2 * 4] = -para[2][2];
111 modelview_matrix[2 + 3 * 4] = -para[2][3];
112 modelview_matrix[3 + 0 * 4] = 0.0;
113 modelview_matrix[3 + 1 * 4] = 0.0;
114 modelview_matrix[3 + 2 * 4] = 0.0;
115 modelview_matrix[3 + 3 * 4] = 1.0;
117 modelview_matrix[12] *= scale;
118 modelview_matrix[13] *= scale;
119 modelview_matrix[14] *= scale;
131 bool invalid =
false;
132 for (
int i = 0; i < 3 && !invalid; i++) {
133 if (
Tvec.at<
float >(i, 0) != -999999)
135 if (
Rvec.at<
float >(i, 0) != -999999)
139 throw cv::Exception(9003,
"extrinsic parameters are not set",
"Marker::getModelViewMatrix", __FILE__, __LINE__);
142 position[0] = -
Tvec.ptr<
float >(0)[0];
143 position[1] = -
Tvec.ptr<
float >(0)[1];
144 position[2] = +
Tvec.ptr<
float >(0)[2];
147 cv::Mat Rot(3, 3, CV_32FC1);
148 cv::Rodrigues(
Rvec, Rot);
153 stAxes[0][0] = -Rot.at<
float >(0, 0);
154 stAxes[0][1] = -Rot.at<
float >(1, 0);
155 stAxes[0][2] = +Rot.at<
float >(2, 0);
157 stAxes[1][0] = -Rot.at<
float >(0, 1);
158 stAxes[1][1] = -Rot.at<
float >(1, 1);
159 stAxes[1][2] = +Rot.at<
float >(2, 1);
161 stAxes[2][0] = stAxes[0][1] * stAxes[1][2] - stAxes[0][2] * stAxes[1][1];
162 stAxes[2][1] = -stAxes[0][0] * stAxes[1][2] + stAxes[0][2] * stAxes[1][0];
163 stAxes[2][2] = stAxes[0][0] * stAxes[1][1] - stAxes[0][1] * stAxes[1][0];
167 axes[0][0] = stAxes[0][0];
168 axes[1][0] = stAxes[0][1];
169 axes[2][0] = stAxes[0][2];
171 axes[0][1] = stAxes[1][0];
172 axes[1][1] = stAxes[1][1];
173 axes[2][1] = stAxes[1][2];
175 axes[0][2] = stAxes[2][0];
176 axes[1][2] = stAxes[2][1];
177 axes[2][2] = stAxes[2][2];
181 double fTrace = axes[0][0] + axes[1][1] + axes[2][2];
186 fRoot = sqrt(fTrace + 1.0);
187 orientation[0] = 0.5 * fRoot;
189 orientation[1] = (axes[2][1] - axes[1][2]) * fRoot;
190 orientation[2] = (axes[0][2] - axes[2][0]) * fRoot;
191 orientation[3] = (axes[1][0] - axes[0][1]) * fRoot;
194 static unsigned int s_iNext[3] = {1, 2, 0};
196 if (axes[1][1] > axes[0][0])
198 if (axes[2][2] > axes[i][i])
200 unsigned int j = s_iNext[i];
201 unsigned int k = s_iNext[j];
203 fRoot = sqrt(axes[i][i] - axes[j][j] - axes[k][k] + 1.0);
204 double *apkQuat[3] = {&orientation[1], &orientation[2], &orientation[3]};
205 *apkQuat[i] = 0.5 * fRoot;
207 orientation[0] = (axes[k][j] - axes[j][k]) * fRoot;
208 *apkQuat[j] = (axes[j][i] + axes[i][j]) * fRoot;
209 *apkQuat[k] = (axes[k][i] + axes[i][k]) * fRoot;
215 void Marker::draw(Mat &in, Scalar color,
int lineWidth,
bool writeId)
const {
218 cv::line(in, (*
this)[0], (*
this)[1], color, lineWidth, CV_AA);
219 cv::line(in, (*
this)[1], (*
this)[2], color, lineWidth, CV_AA);
220 cv::line(in, (*
this)[2], (*
this)[3], color, lineWidth, CV_AA);
221 cv::line(in, (*
this)[3], (*
this)[0], color, lineWidth, CV_AA);
222 cv::rectangle(in, (*
this)[0] - Point2f(2, 2), (*
this)[0] + Point2f(2, 2), Scalar(0, 0, 255, 255), lineWidth, CV_AA);
223 cv::rectangle(in, (*
this)[1] - Point2f(2, 2), (*
this)[1] + Point2f(2, 2), Scalar(0, 255, 0, 255), lineWidth, CV_AA);
224 cv::rectangle(in, (*
this)[2] - Point2f(2, 2), (*
this)[2] + Point2f(2, 2), Scalar(255, 0, 0, 255), lineWidth, CV_AA);
227 sprintf(cad,
"id=%d",
id);
230 for (
int i = 0; i < 4; i++) {
231 cent.x += (*this)[i].x;
232 cent.y += (*this)[i].y;
236 putText(in, cad, cent, FONT_HERSHEY_SIMPLEX, 0.5, Scalar(255 - color[0], 255 - color[1], 255 - color[2], 255), 2);
244 throw cv::Exception(9004,
"!CP.isValid(): invalid camera parameters. It is not possible to calculate extrinsics",
"calculateExtrinsics", __FILE__,
249 void print(cv::Point3f p,
string cad) { cout << cad <<
" " << p.x <<
" " << p.y <<
" " << p.z << endl; }
254 throw cv::Exception(9004,
"!isValid(): invalid marker. It is not possible to calculate extrinsics",
"calculateExtrinsics", __FILE__, __LINE__);
255 if (markerSizeMeters <= 0)
256 throw cv::Exception(9004,
"markerSize<=0: invalid markerSize",
"calculateExtrinsics", __FILE__, __LINE__);
257 if (camMatrix.rows == 0 || camMatrix.cols == 0)
258 throw cv::Exception(9004,
"CameraMatrix is empty",
"calculateExtrinsics", __FILE__, __LINE__);
260 double halfSize = markerSizeMeters / 2.;
261 cv::Mat ObjPoints(4, 3, CV_32FC1);
262 ObjPoints.at<
float >(1, 0) = -halfSize;
263 ObjPoints.at<
float >(1, 1) = halfSize;
264 ObjPoints.at<
float >(1, 2) = 0;
265 ObjPoints.at<
float >(2, 0) = halfSize;
266 ObjPoints.at<
float >(2, 1) = halfSize;
267 ObjPoints.at<
float >(2, 2) = 0;
268 ObjPoints.at<
float >(3, 0) = halfSize;
269 ObjPoints.at<
float >(3, 1) = -halfSize;
270 ObjPoints.at<
float >(3, 2) = 0;
271 ObjPoints.at<
float >(0, 0) = -halfSize;
272 ObjPoints.at<
float >(0, 1) = -halfSize;
273 ObjPoints.at<
float >(0, 2) = 0;
275 cv::Mat ImagePoints(4, 2, CV_32FC1);
278 for (
int c = 0; c < 4; c++) {
279 ImagePoints.at<
float >(c, 0) = ((*
this)[c].x);
280 ImagePoints.at<
float >(c, 1) = ((*
this)[c].y);
284 cv::solvePnP(ObjPoints, ImagePoints, camMatrix, distCoeff, raux, taux);
285 raux.convertTo(
Rvec, CV_32F);
286 taux.convertTo(
Tvec, CV_32F);
288 if (setYPerpendicular)
290 ssize = markerSizeMeters;
299 cv::Mat R(3, 3, CV_32F);
300 Rodrigues(rotation, R);
302 cv::Mat RX = cv::Mat::eye(3, 3, CV_32F);
303 float angleRad = M_PI / 2;
304 RX.at<
float >(1, 1) = cos(angleRad);
305 RX.at<
float >(1, 2) = -sin(angleRad);
306 RX.at<
float >(2, 1) = sin(angleRad);
307 RX.at<
float >(2, 2) = cos(angleRad);
311 Rodrigues(R, rotation);
319 cv::Point2f cent(0, 0);
320 for (
size_t i = 0; i < size(); i++) {
321 cent.x += (*this)[i].x;
322 cent.y += (*this)[i].y;
324 cent.x /= float(size());
325 cent.y /= float(size());
334 cv::Point2f v01 = (*this)[1] - (*this)[0];
335 cv::Point2f v03 = (*this)[3] - (*this)[0];
336 float area1 = fabs(v01.x * v03.y - v01.y * v03.x);
337 cv::Point2f v21 = (*this)[1] - (*this)[2];
338 cv::Point2f v23 = (*this)[3] - (*this)[2];
339 float area2 = fabs(v21.x * v23.y - v21.y * v23.x);
340 return (area2 + area1) / 2.;
347 for (
int i = 0; i < 4; i++)
348 sum += norm((*
this)[i] - (*
this)[(i + 1) % 4]);
void rotateXAxis(cv::Mat &rotation)
void calculateExtrinsics(float markerSize, const CameraParameters &CP, bool setYPerpendicular=true)
This class represents a marker. It is a vector of the fours corners ot the marker.
Parameters of the camera.
void glGetModelViewMatrix(double modelview_matrix[16])
cv::Point2f getCenter() const
void draw(cv::Mat &in, cv::Scalar color, int lineWidth=1, bool writeId=true) const
void print(cv::Point3f p, string cad)
float getPerimeter() const
void OgreGetPoseParameters(double position[3], double orientation[4])