1 #include <opencv2/calib3d/calib3d.hpp> 2 #include <opencv2/imgproc/imgproc.hpp> 13 assert ( M.cols==M.rows && M.cols==4 );
14 assert ( M.type() ==CV_32F || M.type() ==CV_64F );
16 cv::Mat r33=cv::Mat ( M,cv::Rect ( 0,0,3,3 ) );
18 cv::Mat Rpure=svd.u*svd.vt;
19 cv::Rodrigues ( Rpure,R );
20 T.create ( 1,3,M.type() );
21 if ( M.type() ==CV_32F )
22 for (
int i=0; i<3; i++ )
23 T.ptr<
float> ( 0 ) [i]=M.at<
float> ( i,3 );
25 for (
int i=0; i<3; i++ )
26 T.ptr<
double> ( 0 ) [i]=M.at<
double> ( i,3 );
43 cv::Mat R ( 3,3,CV_32F );
44 R.at<
float> ( 0,0 ) =q[0]*q[0] +q[1]*q[1] -q[2]*q[2] -q[3]*q[3];
45 R.at<
float> ( 0,1 ) =2.* ( q[1]*q[2] - q[0]*q[3] );
46 R.at<
float> ( 0,2 ) =2.* ( q[1]*q[3] + q[0]*q[2] );
48 R.at<
float> ( 1,0 ) =2.* ( q[1]*q[2] + q[0]*q[3] );
49 R.at<
float> ( 1,1 ) =q[0]*q[0] +q[2]*q[2] -q[1]*q[1] -q[3]*q[3];
50 R.at<
float> ( 1,2 ) =2.* ( q[2]*q[3] - q[0]*q[1] );
52 R.at<
float> ( 2,0 ) =2.* ( q[1]*q[3] - q[0]*q[2] );
53 R.at<
float> ( 2,1 ) =2.* ( q[2]*q[3] + q[0]*q[1] );
54 R.at<
float> ( 2,2 ) =q[0]*q[0] +q[3]*q[3] -q[1]*q[1] -q[2]*q[2];
66 assert ( S.total() ==M.total() );
67 assert ( S.type() ==M.type() );
68 assert ( S.rows>S.cols && M.rows>M.cols );
71 S.convertTo ( _s,CV_32F );
72 M.convertTo ( _m,CV_32F );
75 cv::Mat Mu_s=cv::Mat::zeros ( 1,3,CV_32F );
76 cv::Mat Mu_m=cv::Mat::zeros ( 1,3,CV_32F );
79 for (
int i=0; i<_s.rows; i++ ) {
80 Mu_s+=_s ( cv::Range ( i,i+1 ),cv::Range ( 0,3 ) );
81 Mu_m+=_m ( cv::Range ( i,i+1 ),cv::Range ( 0,3 ) );
84 for (
int i=0; i<3; i++ ) {
85 Mu_s.ptr<
float> ( 0 ) [i]/=
float ( _s.rows );
86 Mu_m.ptr<
float> ( 0 ) [i]/=
float ( _m.rows );
92 cv::Mat Mu_st=Mu_s.t() *Mu_m;
94 cv::Mat Var_sm=cv::Mat::zeros ( 3,3,CV_32F );
95 for (
int i=0; i<_s.rows; i++ )
96 Var_sm+= ( _s ( cv::Range ( i,i+1 ),cv::Range ( 0,3 ) ).t() *_m ( cv::Range ( i,i+1 ),cv::Range ( 0,3 ) ) ) - Mu_st;
98 for (
int i=0; i<3; i++ )
99 for (
int j=0; j<3; j++ )
100 Var_sm.at<
float> ( i,j ) /=float ( _s.rows );
103 cv::Mat AA=Var_sm-Var_sm.t();
105 cv::Mat A ( 3,1,CV_32F );
106 A.at<
float> ( 0,0 ) =AA.at<
float> ( 1,2 );
107 A.at<
float> ( 1,0 ) =AA.at<
float> ( 2,0 );
108 A.at<
float> ( 2,0 ) =AA.at<
float> ( 0,1 );
110 cv::Mat Q_Var_sm ( 4,4,CV_32F );
111 Q_Var_sm.at<
float> ( 0,0 ) =trace ( Var_sm ) [0];
112 for (
int i=1; i<4; i++ ) {
113 Q_Var_sm.at<
float> ( 0,i ) =A.ptr<
float> ( 0 ) [i-1];
114 Q_Var_sm.at<
float> ( i,0 ) =A.ptr<
float> ( 0 ) [i-1];
116 cv::Mat q33=Var_sm+Var_sm.t()- ( trace ( Var_sm ) [0]*cv::Mat::eye ( 3,3,CV_32F ) );
118 cv::Mat Q33=Q_Var_sm ( cv::Range ( 1,4 ),cv::Range ( 1,4 ) );
121 cv::Mat eigenvalues,eigenvectors;
122 eigen ( Q_Var_sm,eigenvalues,eigenvectors );
126 Quaternion rot ( eigenvectors.at<
float> ( 0,0 ),eigenvectors.at<
float> ( 0,1 ),eigenvectors.at<
float> ( 0,2 ),eigenvectors.at<
float> ( 0,3 ) );
129 cv::Mat T= Mu_m.t()- RR*Mu_s.t();
132 RT_4x4=cv::Mat::eye ( 4,4,CV_32F );
133 cv::Mat r33=RT_4x4 ( cv::Range ( 0,3 ),cv::Range ( 0,3 ) );
135 for (
int i=0; i<3; i++ ) RT_4x4.at<
float> ( i,3 ) =T.ptr<
float> ( 0 ) [i];
141 float *matrix=RT_4x4.ptr<
float> ( 0 );
142 for (
int i=0; i<S.rows; i++ ) {
143 cv::Point3f org= S.ptr<cv::Point3f> ( 0 ) [i];
144 cv::Point3f dest_est;
145 dest_est.x= matrix[0]*org.x+ matrix[1]*org.y +matrix[2]*org.z+matrix[3];
146 dest_est.y= matrix[4]*org.x+ matrix[5]*org.y +matrix[6]*org.z+matrix[7];
147 dest_est.z= matrix[8]*org.x+ matrix[9]*org.y +matrix[10]*org.z+matrix[11];
148 cv::Point3f dest_real=M.ptr<cv::Point3f> ( 0 ) [ i ];
149 err+=cv::norm ( dest_est-dest_real );
151 return err/float ( S.rows );;
167 Morg.create ( orgPoints_32FC3.size(),1,CV_32FC3 );
168 Mdest.create ( dstPoints_32FC3.size(),1,CV_32FC3 );
169 for (
size_t i=0; i<dstPoints_32FC3.size(); i++ ) {
170 Morg.ptr< cv::Point3f> ( 0 ) [i]=orgPoints_32FC3[i];
171 Mdest.ptr< cv::Point3f> ( 0 ) [i]=dstPoints_32FC3[i];
177 cv::Mat
getRTMatrix (
const cv::Mat &R_,
const cv::Mat &T_ ,
int forceType=-1 ) {
182 if ( R.type() ==CV_64F ) {
183 assert ( T.type() ==CV_64F );
184 cv::Mat Matrix=cv::Mat::eye ( 4,4,CV_64FC1 );
186 cv::Mat R33=cv::Mat ( Matrix,cv::Rect ( 0,0,3,3 ) );
187 if ( R.total() ==3 ) {
188 cv::Rodrigues ( R,R33 );
189 }
else if ( R.total() ==9 ) {
191 R.convertTo ( R64,CV_64F );
194 for (
int i=0; i<3; i++ )
195 Matrix.at<
double> ( i,3 ) =T.ptr<
double> ( 0 ) [i];
197 }
else if ( R.depth() ==CV_32F ) {
198 cv::Mat Matrix=cv::Mat::eye ( 4,4,CV_32FC1 );
199 cv::Mat R33=cv::Mat ( Matrix,cv::Rect ( 0,0,3,3 ) );
200 if ( R.total() ==3 ) {
201 cv::Rodrigues ( R,R33 );
202 }
else if ( R.total() ==9 ) {
204 R.convertTo ( R32,CV_32F );
208 for (
int i=0; i<3; i++ )
209 Matrix.at<
float> ( i,3 ) =T.ptr<
float> ( 0 ) [i];
213 if ( forceType==-1 )
return M;
216 M.convertTo ( MTyped,forceType );
230 cv::Point3f
mult (
const cv::Mat &m, cv::Point3f p ) {
231 assert ( m.isContinuous() );
232 if ( m.type() ==CV_32F ) {
233 const float *ptr=m.ptr<
float> ( 0 );
235 res.x= ptr[0]*p.x +ptr[1]*p.y +ptr[2]*p.z+ptr[3];
236 res.y= ptr[4]*p.x +ptr[5]*p.y +ptr[6]*p.z+ptr[7];
237 res.z= ptr[8]*p.x +ptr[9]*p.y +ptr[10]*p.z+ptr[11];
239 }
else if ( m.type() ==CV_64F ) {
240 const double *ptr=m.ptr<
double> ( 0 );
242 res.x= ptr[0]*p.x +ptr[1]*p.y +ptr[2]*p.z+ptr[3];
243 res.y= ptr[4]*p.x +ptr[5]*p.y +ptr[6]*p.z+ptr[7];
244 res.z= ptr[8]*p.x +ptr[9]*p.y +ptr[10]*p.z+ptr[11];
250 std::vector<cv::Vec4f>
getPcdPoints(
const vector<cv::Point3f> &mpoints,cv::Scalar color,
int npoints=100){
251 vector<cv::Vec4f> points;
252 double msize=cv::norm(mpoints[0]-mpoints[1]);
253 float fcolor;uchar *c=(uchar*)&fcolor;
254 for(
int i=0;i<3;i++)c[i]=color[i];
257 for(
size_t i=0;i<mpoints.size();i++){
258 cv::Point3f v=mpoints[(i+1)%mpoints.size()]-mpoints[i];
259 float ax=1./float(npoints);
260 for(
float x=0;
x<=1;
x+=ax){
261 cv::Point3f p3=mpoints[i]+v*
x;
262 points.push_back(cv::Vec4f(p3.x,p3.y,p3.z, fcolor));
268 cv::Point3f v1=mpoints[1]-mpoints[0];
269 cv::Point3f v2=mpoints[3]-mpoints[0];
272 cv::Point3f vz=v2.cross(v1);
276 cv::Point3f center=(mpoints[0]+mpoints[1]+mpoints[2]+mpoints[3])*0.25;
277 float ax=(msize/3)/100;
278 for(
float x=0;
x<=msize/3;
x+=ax){
279 cv::Point3f p3=center+vz*
x;
280 points.push_back(cv::Vec4f(p3.x,p3.y,p3.z, fcolor));
297 string text = std::to_string(
id);
298 int fontFace = cv::FONT_HERSHEY_SCRIPT_SIMPLEX;
299 double fontScale = 2;
302 float markerSize_2=markerSize/2;
303 cv::Size textSize = cv::getTextSize(text, fontFace,
304 fontScale, thickness, &baseline);
305 cv::Mat img(textSize +cv::Size(0,baseline/2), CV_8UC1,cv::Scalar::all(0));
308 cv::putText(img, text, cv::Point(0,textSize.height+baseline/4), fontFace, fontScale,cv::Scalar::all(255), thickness, 8);
310 vector<cv::Point3f> points_id;
311 for(
int y=0;y<img.rows;y++)
312 for(
int x=0;
x<img.cols;
x++)
313 if (img.at<uchar>(y,
x)!=0) points_id.push_back( cv::Point3f((
float(
x)/
float(img.cols))-0.5,(
float(img.rows-y)/
float(img.rows))-0.5,0));
317 for(
auto &p:points_id)p*=markerSize_2;
319 for(
auto &p:points_id)p=
mult( rt_g2m,p);
322 float fcolor;uchar *c=(uchar*)&fcolor;
323 for(
int i=0;i<3;i++)c[i]=color[i];
325 vector<cv::Vec4f> res;
326 for(
auto &p:points_id)
327 res.push_back(cv::Vec4f(p.x,p.y,p.z, fcolor));
337 std::vector<cv::Vec4f> points2write;
341 color=cv::Scalar(255,0,0);
343 points2write.insert(points2write.end(),points4.begin(),points4.end());
345 points2write.insert(points2write.end(),points_id.begin(),points_id.end());
349 if (!frame_pose.second.empty()){
350 cv::Mat g2c=frame_pose.second.inv();
352 for(
auto &p:mpoints) p=
mult(g2c,p);
353 auto pcam=
getPcdPoints( mpoints,cv::Scalar(0,255,0),25);
354 points2write.insert(points2write.end(),pcam.begin(),pcam.end());
362 std::ofstream filePCD ( fpath, std::ios::binary );
364 filePCD<<
"# .PCD v.7 - Point Cloud Data file format\nVERSION .7\nFIELDS x y z rgb\nSIZE 4 4 4 4\nTYPE F F F F\nCOUNT 1 1 1 1\nVIEWPOINT 0 0 0 1 0 0 0\nWIDTH "<<points2write.size()<<
"\nHEIGHT 1\nPOINTS "<<points2write.size()<<
"\nDATA binary\n";
367 filePCD.write((
char*)&points2write[0],points2write.size()*
sizeof(points2write[0]));
std::map< int, cv::Mat > frame_pose_map
void savePCDFile(string fpath, const aruco::MarkerMap &ms, const std::map< int, cv::Mat > frame_pose_map)
static vector< cv::Point3f > get3DPoints(float msize)
void getRTfromMatrix44(const cv::Mat &M, cv::Mat &R, cv::Mat &T)
vector< cv::Vec4f > getMarkerIdPcd(aruco::Marker3DInfo &minfo, cv::Scalar color)
Quaternion(float q0, float q1, float q2, float q3)
cv::Mat getRotation() const
cv::Point3f mult(const cv::Mat &m, cv::Point3f p)
float rigidBodyTransformation_Horn1987(cv::Mat &S, cv::Mat &M, cv::Mat &RT_4x4)
cv::Mat getRTMatrix(const cv::Mat &R_, const cv::Mat &T_, int forceType=-1)
TFSIMD_FORCE_INLINE const tfScalar & x() const
float getMarkerSize() const
std::vector< cv::Vec4f > getPcdPoints(const vector< cv::Point3f > &mpoints, cv::Scalar color, int npoints=100)
This class defines a set of markers whose locations are attached to a common reference system...