Go to the documentation of this file.00001 #include <aruco/subpixelcorner.h>
00002 #include <opencv2/imgproc/imgproc.hpp>
00003 using namespace cv;
00004
00005 namespace aruco{
00006
00007 SubPixelCorner::SubPixelCorner()
00008 {
00009 _winSize=15;
00010 _apertureSize=3;
00011 _term.maxCount=10;
00012 _term.epsilon=0.1;
00013 _term.type=CV_TERMCRIT_ITER | CV_TERMCRIT_EPS;
00014 enable=true;
00015 }
00016
00017 void SubPixelCorner::checkTerm()
00018 {
00019 switch( _term.type)
00020 {
00021 case CV_TERMCRIT_ITER:
00022 _term.epsilon = 0.f;
00023 _term.maxCount;
00024 break;
00025 case CV_TERMCRIT_EPS:
00026 _term.maxCount=_term.COUNT;
00027 break;
00028 case CV_TERMCRIT_ITER | CV_TERMCRIT_EPS:
00029 break;
00030 default:
00031 _term.maxCount=_term.COUNT;
00032 _term.epsilon=0.1;
00033 _term.type=CV_TERMCRIT_ITER | CV_TERMCRIT_EPS;
00034 break;
00035 }
00036
00037 eps = std::max( _term.epsilon ,0.0);
00038 eps=eps*eps;
00039
00040 _max_iters= std::max( _term.maxCount, 1 );
00041 int max1=TermCriteria::MAX_ITER;
00042 _max_iters= std::min(_max_iters,max1);
00043
00044 }
00045
00046 double SubPixelCorner::pointDist(cv::Point2f estimate_corner,cv::Point2f curr_corner)
00047 {
00048 double dist=((curr_corner.x-estimate_corner.x)*(curr_corner.x-estimate_corner.x))+
00049 ((curr_corner.y-estimate_corner.y)*(curr_corner.y-estimate_corner.y));
00050 return dist;
00051 }
00052
00053
00054 void SubPixelCorner::generateMask()
00055 {
00056
00057 double coeff = 1. / (_winSize*_winSize);
00058 float * maskX=(float *)calloc(1,(_winSize*sizeof(float)));
00059 float * maskY=(float *)calloc(1,(_winSize*sizeof(float)));
00060 mask.create (_winSize,_winSize,CV_32FC(1));
00061
00062 int k=0;
00063 for( int i = -_winSize/2, k = 0; i <= _winSize/2; i++, k++ )
00064 {
00065 maskX[k] = (float)exp( -i * i * coeff );
00066
00067 }
00068
00069 maskY = maskX;
00070
00071 for( int i = 0; i < _winSize; i++ )
00072 {
00073 float * mask_ptr=mask.ptr <float>(i);
00074 for( int j = 0; j < _winSize; j++ )
00075 {
00076 mask_ptr[j] = maskX[j] * maskY[i];
00077 }
00078 }
00079
00080 }
00081
00082 void SubPixelCorner::RefineCorner(cv::Mat image,std::vector <cv::Point2f> &corners)
00083 {
00084
00085 if(enable==false)
00086 return;
00087 checkTerm();
00088
00089 generateMask ();
00090
00091 for(int k=0;k<corners.size ();k++)
00092 {
00093 cv::Point2f curr_corner;
00094
00095 cv::Point2f estimate_corner=corners[k];
00096
00097
00098
00099 if(estimate_corner.x<0 || estimate_corner.y<0 || estimate_corner.y >image.rows || estimate_corner.y > image.cols)
00100 continue;
00101 int iter=0;
00102 double dist=TermCriteria::EPS;
00103
00104 do
00105 {
00106 iter=iter+1;
00107 curr_corner=estimate_corner;
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134 Mat local;
00135 cv::getRectSubPix (image,Size(_winSize+2*(_apertureSize/2),_winSize+2*(_apertureSize/2)),curr_corner,local);
00136
00137
00138
00139 cv::Mat Dx,Dy;
00140
00141
00142
00143 cv::Sobel (local,Dx,CV_32FC(1),1,0,_apertureSize,1,0);
00144 cv::Sobel (local,Dy,CV_32FC(1),0,1,_apertureSize,1,0);
00145
00146
00147 double A=0,B=0,C=0,D=0,E=0,F=0;
00148 int lx=0,ly=0;
00149 for(int i=_apertureSize/2;i<=_winSize;i++)
00150 {
00151
00152 float *dx_ptr=Dx.ptr <float>(i);
00153 float *dy_ptr=Dy.ptr <float>(i);
00154 ly=i-_winSize/2-_apertureSize/2;
00155
00156 float * mask_ptr=mask.ptr <float>(ly+_winSize/2);
00157
00158 for(int j=_apertureSize/2;j<=_winSize;j++)
00159 {
00160
00161 lx=j-_winSize/2-_apertureSize/2;
00162
00163 double val=mask_ptr[lx+_winSize/2];
00164 double dxx=dx_ptr[j]*dx_ptr[j]*val;
00165 double dyy=dy_ptr[j]*dy_ptr[j]*val;
00166 double dxy=dx_ptr[j]*dy_ptr[j]*val;
00167
00168 A=A+dxx;
00169 B=B+dxy;
00170 E=E+dyy;
00171 C=C+dxx*lx+dxy*ly;
00172 F=F+dxy*lx+dyy*ly;
00173
00174 }
00175 }
00176
00177
00178 double det=(A*E-B*B);
00179 if(fabs( det ) > DBL_EPSILON*DBL_EPSILON)
00180 {
00181 det=1.0/det;
00182
00183 estimate_corner.x=curr_corner.x+((C*E)-(B*F))*det;
00184 estimate_corner.y=curr_corner.y+((A*F)-(C*D))*det;
00185 }
00186 else
00187 {
00188 estimate_corner.x=curr_corner.x;
00189 estimate_corner.y=curr_corner.y;
00190 }
00191
00192 dist=pointDist(estimate_corner,curr_corner);
00193
00194
00195 }while(iter<_max_iters && dist>eps);
00196
00197
00198 if(fabs(corners[k].x-estimate_corner.x) > _winSize || fabs(corners[k].y-estimate_corner.y)>_winSize)
00199 {
00200 estimate_corner.x=corners[k].x;
00201 estimate_corner.y=corners[k].y;
00202 }
00203 corners[k].x=estimate_corner.x;
00204 corners[k].y=estimate_corner.y;
00205
00206
00207 }
00208
00209 }
00210
00211 }