29 #include <opencv2/core/core.hpp>    30 #include <opencv2/features2d/features2d.hpp>    31 #include <opencv2/imgproc/imgproc.hpp>    32 #include <opencv2/calib3d/calib3d.hpp>    33 #include <opencv2/highgui/highgui.hpp>    50 MarkerDetector::MarkerDetector() {
    54     if (markerIdDetector->getBestInputSize()!=-1)setWarpSize(markerIdDetector->getBestInputSize());
    66 MarkerDetector::~MarkerDetector() {}
    77 std::vector<aruco::Marker> MarkerDetector::detect(
const cv::Mat &input ) 
throw(cv::Exception) {
    78     std::vector< Marker >  detectedMarkers;
    79     detect(input,detectedMarkers);
    80     return detectedMarkers;
    83 std::vector<aruco::Marker> MarkerDetector::detect(
const cv::Mat &input,
const CameraParameters &camParams, 
float markerSizeMeters , 
bool setYPerperdicular ) 
throw(cv::Exception){
    84     std::vector< Marker >  detectedMarkers;
    85     detect(input,detectedMarkers,camParams,markerSizeMeters,setYPerperdicular);
    86     return detectedMarkers;
    96 void MarkerDetector::detect(
const cv::Mat &input, std::vector< Marker > &detectedMarkers, 
CameraParameters camParams, 
float markerSizeMeters,
    97                             bool setYPerpendicular) 
throw(cv::Exception) {
    98     if ( camParams.CamSize!=input.size() && camParams.isValid() && markerSizeMeters>0){
   101         cp_aux.
resize(input.size());
   102         detect(input, detectedMarkers, cp_aux.
CameraMatrix, cp_aux.
Distorsion, markerSizeMeters, setYPerpendicular);
   105         detect(input, detectedMarkers, camParams.CameraMatrix, camParams.Distorsion, markerSizeMeters, setYPerpendicular);
   117 void MarkerDetector::detect(
const cv::Mat &input, vector< Marker > &detectedMarkers, Mat camMatrix, Mat distCoeff, 
float markerSizeMeters,
   118                             bool setYPerpendicular) 
throw(cv::Exception) {
   121     if (input.type() == CV_8UC3)
   122         cv::cvtColor(input, grey, CV_BGR2GRAY);
   126     imagePyramid.clear();
   127     imagePyramid.push_back(grey);
   128     while(imagePyramid.back().cols>120){
   130       cv::pyrDown(imagePyramid.back(),pyrd);
   131       imagePyramid.push_back(pyrd);
   137     detectedMarkers.clear();
   140     cv::Mat imgToBeThresHolded = grey;
   144     int n_param1 = 2 * _params._thresParam1_range + 1;
   145     vector< cv::Mat > thres_images;
   150     vector<int> p1_values;
   151     for(
int i=std::max(3.,_params._thresParam1-2*_params._thresParam1_range);i<=_params._thresParam1+2*_params._thresParam1_range;i+=2)p1_values.push_back(i);
   152     thres_images.resize(p1_values.size());
   153 #pragma omp parallel for   154     for (
int i = 0; i < int(p1_values.size()); i++)
   155         thresHold(_params._thresMethod, imgToBeThresHolded, thres_images[i], p1_values[i], _params._thresParam2);
   156     thres = thres_images[n_param1 / 2];
   161     vector< MarkerCandidate > MarkerCanditates;
   162     detectRectangles(thres_images, MarkerCanditates);
   165     float desiredarea=_params._markerWarpSize*_params._markerWarpSize;
   173 #pragma omp parallel for   174     for (
int i = 0; i < int(MarkerCanditates.size()); i++) {
   182         for(
size_t p=1;p<imagePyramid.size();p++){
   183             if (MarkerCanditates[i].getArea() / 
pow(4,p) >= desiredarea ) imgPyrIdx=p;
   187         vector<cv::Point2f> points2d_pyr=MarkerCanditates[i];
   188         for(
auto &p:points2d_pyr) p*=1./
pow(2,imgPyrIdx);
   189         resW = warp(imagePyramid[imgPyrIdx], canonicalMarker, Size(_params._markerWarpSize, _params._markerWarpSize), points2d_pyr);
   194             if (markerIdDetector->detect(canonicalMarker, 
id,nRotations)) {
   195                  if (_params._cornerMethod == LINES) 
   196                     refineCandidateLines(MarkerCanditates[i], camMatrix, distCoeff);
   206     joinVectors(markers_omp, detectedMarkers, 
true);
   207     joinVectors(candidates_omp, _candidates, 
true);
   215     if (detectedMarkers.size() > 0 && _params._cornerMethod != 
NONE && _params._cornerMethod != LINES) {
   217         vector< Point2f > Corners;
   218         for (
unsigned int i = 0; i < detectedMarkers.size(); i++)
   219             for (
int c = 0; c < 4; c++)
   220                 Corners.push_back(detectedMarkers[i][c]);
   223           if (_params._cornerMethod == SUBPIX) {
   224             cornerSubPix(grey, Corners, cvSize(_params._subpix_wsize, _params._subpix_wsize), cvSize(-1, -1), cvTermCriteria(CV_TERMCRIT_ITER | CV_TERMCRIT_EPS, 12, 0.005));
   227         for (
unsigned int i = 0; i < detectedMarkers.size(); i++)
   228             for (
int c = 0; c < 4; c++)
   229                 detectedMarkers[i][c] = Corners[i * 4 + c];
   234     std::sort(detectedMarkers.begin(), detectedMarkers.end());
   237     vector< bool > toRemove(detectedMarkers.size(), 
false);
   239     for (
int i = 0; i < int(detectedMarkers.size()) - 1; i++) {
   240         for (
int j = i+1; j < int(detectedMarkers.size()) && !toRemove[i] ; j++) {
   241             if (detectedMarkers[i].
id == detectedMarkers[j].
id) {
   243                 if (perimeter(detectedMarkers[i]) < perimeter(detectedMarkers[j]))
   254     int borderDistThresX = _params._borderDistThres * float(input.cols);
   255     int borderDistThresY = _params._borderDistThres * float(input.rows);
   256     for (
size_t i = 0; i < detectedMarkers.size(); i++) {
   258         for (
size_t c = 0; c < detectedMarkers[i].size(); c++) {
   259             if (detectedMarkers[i][c].
x < borderDistThresX || detectedMarkers[i][c].y < borderDistThresY ||
   260                 detectedMarkers[i][c].
x > input.cols - borderDistThresX || detectedMarkers[i][c].y > input.rows - borderDistThresY) {
   268     removeElements(detectedMarkers, toRemove);
   271     if (camMatrix.rows != 0 && markerSizeMeters > 0) {
   272         for (
unsigned int i = 0; i < detectedMarkers.size(); i++)
   273             detectedMarkers[i].calculateExtrinsics(markerSizeMeters, camMatrix, distCoeff, setYPerpendicular);
   290         const float d0=p1[0]-at(idx_p2).x;
   291         const float d1=p1[1]-at(idx_p2).y;
   300          return  dim==0? at(idx).x:at(idx).y;
   306     template <
class BBOX>
   317 void MarkerDetector::detectRectangles(
const cv::Mat &thres, vector< std::vector< cv::Point2f > > &MarkerCanditates) {
   318     vector< MarkerCandidate > candidates;
   319     vector< cv::Mat > thres_v;
   320     thres_v.push_back(thres);
   321     detectRectangles(thres_v, candidates);
   323     MarkerCanditates.resize(candidates.size());
   324     for (
size_t i = 0; i < MarkerCanditates.size(); i++)
   325         MarkerCanditates[i] = candidates[i];
   328 void MarkerDetector::detectRectangles(vector< cv::Mat > &thresImgv, vector< MarkerCandidate > &OutMarkerCanditates) {
   333     int maxSize = _params._maxSize * std::max(thresImgv[0].cols, thresImgv[0].rows) * 4;
   334     int minSize=  std::min ( 
float(_params._minSize_pix) , _params._minSize* std::max(thresImgv[0].cols, thresImgv[0].rows) * 4 );
   337 #pragma omp parallel for   338     for (
int img_idx = 0; img_idx < int(thresImgv.size()); img_idx++) {
   339         std::vector< cv::Vec4i > hierarchy2;
   340         std::vector< std::vector< cv::Point > > contours2;
   342         thresImgv[img_idx].copyTo(thres2);
   343         cv::findContours(thres2, contours2, hierarchy2, CV_RETR_LIST, CV_CHAIN_APPROX_NONE);
   345         vector< Point > approxCurve;
   347         for (
unsigned int i = 0; i < contours2.size(); i++) {
   350             if (minSize < 
int(contours2[i].size()) && int(contours2[i].size()) < maxSize) {
   352                 approxPolyDP(contours2[i], approxCurve, 
double(contours2[i].size()) * 0.05, 
true);
   355                 if (approxCurve.size() == 4) {
   362                     if (isContourConvex(Mat(approxCurve))) {
   365                         float minDist = 1e10;
   366                         for (
int j = 0; j < 4; j++) {
   367                             float d = 
std::sqrt((
float)(approxCurve[j].
x - approxCurve[(j + 1) % 4].
x) * (approxCurve[j].
x - approxCurve[(j + 1) % 4].
x) +
   368                                                 (approxCurve[j].y - approxCurve[(j + 1) % 4].y) * (approxCurve[j].y - approxCurve[(j + 1) % 4].y));
   370                             if (d < minDist) minDist = d;
   378                             if (_params._cornerMethod==LINES)
   380                             for (
int j = 0; j < 4; j++)
   381                                 MarkerCanditatesV[
omp_get_thread_num()].back().push_back(Point2f(approxCurve[j].
x, approxCurve[j].y));
   390     vector< MarkerCandidate > MarkerCanditates;
   392     for (
size_t i = 0; i < MarkerCanditatesV.size(); i++)
   393         for (
size_t j = 0; j < MarkerCanditatesV[i].size(); j++) {
   394             MarkerCanditates.push_back(MarkerCanditatesV[i][j]);
   398     valarray< bool > swapped(
false, MarkerCanditates.size()); 
   399     for (
unsigned int i = 0; i < MarkerCanditates.size(); i++) {
   403         double dx1 = MarkerCanditates[i][1].x - MarkerCanditates[i][0].x;
   404         double dy1 = MarkerCanditates[i][1].y - MarkerCanditates[i][0].y;
   405         double dx2 = MarkerCanditates[i][2].x - MarkerCanditates[i][0].x;
   406         double dy2 = MarkerCanditates[i][2].y - MarkerCanditates[i][0].y;
   407         double o = (dx1 * dy2) - (dy1 * dx2);
   410             swap(MarkerCanditates[i][1], MarkerCanditates[i][3]);
   419 #pragma omp parallel for   420     for (
unsigned int i = 0; i < MarkerCanditates.size(); i++) {
   422         for (
unsigned int j = i + 1; j < MarkerCanditates.size(); j++) {
   423             valarray< float > vdist(4);
   424             for (
int c = 0; c < 4; c++)
   425                 vdist[c] = 
sqrt((MarkerCanditates[i][c].
x - MarkerCanditates[j][c].
x) * (MarkerCanditates[i][c].x - MarkerCanditates[j][c].x) +
   426                                 (MarkerCanditates[i][c].y - MarkerCanditates[j][c].y) * (MarkerCanditates[i][c].y - MarkerCanditates[j][c].y));
   429             if (vdist[0] < 6 && vdist[1] < 6 && vdist[2] < 6 && vdist[3] < 6) {
   437     vector< pair< int, int > > TooNearCandidates;
   438     joinVectors(TooNearCandidates_omp, TooNearCandidates);
   440     valarray< bool > toRemove(
false, MarkerCanditates.size());
   441     for (
unsigned int i = 0; i < TooNearCandidates.size(); i++) {
   442         if (perimeter(MarkerCanditates[TooNearCandidates[i].first]) > perimeter(MarkerCanditates[TooNearCandidates[i].second]))
   443             toRemove[TooNearCandidates[i].second] = 
true;
   445             toRemove[TooNearCandidates[i].first] = 
true;
   450     OutMarkerCanditates.reserve(MarkerCanditates.size());
   451     for (
size_t i = 0; i < MarkerCanditates.size(); i++) {
   453             OutMarkerCanditates.push_back(MarkerCanditates[i]);
   455             if (swapped[i] && OutMarkerCanditates.back().contour.size()>1) 
   456                 reverse(OutMarkerCanditates.back().contour.begin(), OutMarkerCanditates.back().contour.end()); 
   477 void  MarkerDetector::adpt_threshold_multi( 
const Mat &grey, std::vector<Mat> &outThresImages,
double param1  ,
double param1_range , 
double param2,
double param2_range ){
   480     int start_p1 = std::max(3.,param1-2*param1_range);
   481     int end_p1 = param1+2*param1_range;
   482     int start_p2 = std::max(3.,param2-2*param2_range);
   483     int end_p2 = param2+2*param2_range;
   484     vector<std::pair<int,int> > p1_2_values;
   485     for(
int i=start_p1;i<=end_p1;i+=2)
   486         for(
int j=start_p2;j<=end_p2;j+=2)
   487             p1_2_values.push_back(std::pair<int,int>(i,j));
   488     outThresImages.resize(p1_2_values.size());
   491     cv::integral(grey,intimg);
   493 #pragma omp parallel for   494     for(
int i=0;i<int(p1_2_values.size());i++){
   497         float inv_area=1./(p1_2_values[i].first*p1_2_values[i].first);
   498         int wsize_2=p1_2_values[i].first/2;
   499         outThresImages[i].create(grey.size(),grey.type() );
   501         for(
int y=wsize_2;y<grey.rows-wsize_2;y++){
   502             int *_y1=intimg.ptr<
int>(y-wsize_2);
   503             int *_y2=intimg.ptr<
int>(y+wsize_2+1);
   504             uchar *out=      outThresImages[i].ptr<uchar>(y);
   505             for(
int x=wsize_2;
x<grey.cols-wsize_2;
x++){
   509                 float mean=float( _y2[x2]-_y2[x1]-_y1[x2]+_y1[x1])* inv_area ;
   510                 if ( mean- grey.at<uchar>(y,
x)>p1_2_values[i].second)
   526 void MarkerDetector::thresHold(
int method, 
const Mat &grey, Mat &out, 
double param1, 
double param2) 
throw(cv::Exception) {
   529         param1 = _params._thresParam1;
   531         param2 = _params._thresParam2;
   533     if (grey.type() != CV_8UC1)
   534         throw cv::Exception(9001, 
"grey.type()!=CV_8UC1", 
"MarkerDetector::thresHold", __FILE__, __LINE__);
   537         cv::threshold(grey, out, param1, 255, CV_THRESH_BINARY_INV);
   543         else if (((
int)param1) % 2 != 1)
   544             param1 = (int)(param1 + 1);
   546         cv::adaptiveThreshold(grey, out, 255, ADAPTIVE_THRESH_MEAN_C, THRESH_BINARY_INV, param1, param2);
   553         cv::Canny(grey, out, 10, 220);
   568 bool MarkerDetector::warp(Mat &in, Mat &out, Size size, vector< Point2f > points) 
throw(cv::Exception) {
   570     if (points.size() != 4)
   571         throw cv::Exception(9001, 
"point.size()!=4", 
"MarkerDetector::warp", __FILE__, __LINE__);
   573     Point2f pointsRes[4], pointsIn[4];
   574     for (
int i = 0; i < 4; i++)
   575         pointsIn[i] = points[i];
   576     pointsRes[0] = (Point2f(0, 0));
   577     pointsRes[1] = Point2f(size.width - 1, 0);
   578     pointsRes[2] = Point2f(size.width - 1, size.height - 1);
   579     pointsRes[3] = Point2f(0, size.height - 1);
   580     Mat M = getPerspectiveTransform(pointsIn, pointsRes);
   581     cv::warpPerspective(in, out, M, size, cv::INTER_NEAREST);
   586     assert(points.size() == 4);
   587     int idxSegments[4] = {-1, -1, -1, -1};
   589     cv::Point points2i[4];
   590     for (
int i = 0; i < 4; i++) {
   591         points2i[i].x = points[i].x;
   592         points2i[i].y = points[i].y;
   595     for (
size_t i = 0; i < contour.size(); i++) {
   596         if (idxSegments[0] == -1)
   597             if (contour[i] == points2i[0])
   599         if (idxSegments[1] == -1)
   600             if (contour[i] == points2i[1])
   602         if (idxSegments[2] == -1)
   603             if (contour[i] == points2i[2])
   605         if (idxSegments[3] == -1)
   606             if (contour[i] == points2i[3])
   610     for (
int i = 0; i < 4; i++)
   611         idxs[i] = idxSegments[i];
   615     float distSum[4] = {0, 0, 0, 0};
   618     for (
int i = 0; i < 3; i++) {
   619         cv::Point p1 = contour[idxSegments[i]];
   620         cv::Point p2 = contour[idxSegments[i + 1]];
   621         float inv_den = 1. / 
sqrt(
float((p2.x - p1.x) * (p2.x - p1.x) + (p2.y - p1.y) * (p2.y - p1.y)));
   624         for (
int j = idxSegments[i]; j < idxSegments[i + 1]; j++) {
   625             float dist = std::fabs(
float((p2.x - p1.x) * (p1.y - contour[j].y) - (p1.x - contour[j].x) * (p2.y - p1.y))) * inv_den;
   630         distSum[i] /= float(idxSegments[i + 1] - idxSegments[i]);
   636     cv::Point p1 = contour[idxSegments[0]];
   637     cv::Point p2 = contour[idxSegments[3]];
   638     float inv_den = 1. / 
std::sqrt(
float((p2.x - p1.x) * (p2.x - p1.x) + (p2.y - p1.y) * (p2.y - p1.y)));
   640     for (
int j = 0; j < idxSegments[0]; j++)
   641         distSum[3] += std::fabs(
float((p2.x - p1.x) * (p1.y - contour[j].y) - (p1.x - contour[j].x) * (p2.y - p1.y))) * inv_den;
   642     for (
size_t j = 
size_t(idxSegments[3]); j < contour.size(); j++)
   643         distSum[3] += std::fabs(
float((p2.x - p1.x) * (p1.y - contour[j].y) - (p1.x - contour[j].x) * (p2.y - p1.y))) * inv_den;
   645     distSum[3] /= float(idxSegments[0] + (contour.size() - idxSegments[3]));
   650     if (distSum[0] + distSum[2] > distSum[1] + distSum[3])
   659     else if (p.x >= s.width)
   663     else if (p.y >= s.height)
   670     else if (p.x >= s.width)
   674     else if (p.y >= s.height)
   683 bool MarkerDetector::warp_cylinder(Mat &in, Mat &out, Size size, 
MarkerCandidate &mcand) 
throw(cv::Exception) {
   685     if (mcand.size() != 4)
   686         throw cv::Exception(9001, 
"point.size()!=4", 
"MarkerDetector::warp", __FILE__, __LINE__);
   696     vector< int > idxSegments;
   700     for (
int i = 1; i < 4; i++)
   701         if (idxSegments[i] < idxSegments[minIdx])
   704     std::rotate(idxSegments.begin(), idxSegments.begin() + minIdx, idxSegments.end());
   705     std::rotate(mcand.begin(), mcand.begin() + minIdx, mcand.end());
   715     Point2f enlargedRegion[4];
   716     for (
int i = 0; i < 4; i++)
   717         enlargedRegion[i] = mcand[i];
   718     if (defrmdSide == 0) {
   719         enlargedRegion[0] = mcand[0] + (mcand[3] - mcand[0]) * 1.2;
   720         enlargedRegion[1] = mcand[1] + (mcand[2] - mcand[1]) * 1.2;
   721         enlargedRegion[2] = mcand[2] + (mcand[1] - mcand[2]) * 1.2;
   722         enlargedRegion[3] = mcand[3] + (mcand[0] - mcand[3]) * 1.2;
   724         enlargedRegion[0] = mcand[0] + (mcand[1] - mcand[0]) * 1.2;
   725         enlargedRegion[1] = mcand[1] + (mcand[0] - mcand[1]) * 1.2;
   726         enlargedRegion[2] = mcand[2] + (mcand[3] - mcand[2]) * 1.2;
   727         enlargedRegion[3] = mcand[3] + (mcand[2] - mcand[3]) * 1.2;
   729     for (
size_t i = 0; i < 4; i++)
   747     Point2f pointsRes[4], pointsIn[4];
   748     for (
int i = 0; i < 4; i++)
   749         pointsIn[i] = mcand[i];
   751     cv::Size enlargedSize = size;
   752     enlargedSize.width += 2 * enlargedSize.width * 0.2;
   753     pointsRes[0] = (Point2f(0, 0));
   754     pointsRes[1] = Point2f(enlargedSize.width - 1, 0);
   755     pointsRes[2] = Point2f(enlargedSize.width - 1, enlargedSize.height - 1);
   756     pointsRes[3] = Point2f(0, enlargedSize.height - 1);
   759         rotate(pointsRes, pointsRes + 1, pointsRes + 4);
   760     cv::Mat imAux, imAux2(enlargedSize, CV_8UC1);
   761     Mat M = cv::getPerspectiveTransform(enlargedRegion, pointsRes);
   762     cv::warpPerspective(in, imAux, M, enlargedSize, cv::INTER_NEAREST);
   765     vector< cv::Point > pointsCO(mcand.contour.size());
   766     assert(M.type() == CV_64F);
   767     assert(M.cols == 3 && M.rows == 3);
   769     double *mptr = M.ptr< 
double >(0);
   770     imAux2.setTo(cv::Scalar::all(0));
   773     for (
size_t i = 0; i < mcand.contour.size(); i++) {
   774         float inX = mcand.contour[i].x;
   775         float inY = mcand.contour[i].y;
   776         float w = inX * mptr[6] + inY * mptr[7] + mptr[8];
   778         pointsCO[i].x = ((inX * mptr[0] + inY * mptr[1] + mptr[2]) / w) + 0.5;
   779         pointsCO[i].y = ((inX * mptr[3] + inY * mptr[4] + mptr[5]) / w) + 0.5;
   783         imAux2.at< uchar >(pointsCO[i].y, pointsCO[i].x) = 255;
   784         if (pointsCO[i].y > 0)
   785             imAux2.at< uchar >(pointsCO[i].y - 1, pointsCO[i].x) = 255;
   786         if (pointsCO[i].y < imAux2.rows - 1)
   787             imAux2.at< uchar >(pointsCO[i].y + 1, pointsCO[i].x) = 255;
   790     cv::Mat outIm(enlargedSize, CV_8UC1);
   791     outIm.setTo(cv::Scalar::all(0));
   793     for (
int y = 0; y < imAux2.rows; y++) {
   794         uchar *_offInfo = imAux2.ptr< uchar >(y);
   795         int start = -1, end = -1;
   797         for (
int x = 0; 
x < imAux.cols; 
x++) {
   807         assert(start != -1 && end != -1 && (end - start) > size.width >> 1);
   808         uchar *In_image = imAux.ptr< uchar >(y);
   809         uchar *Out_image = outIm.ptr< uchar >(y);
   810         memcpy(Out_image, In_image + start, imAux.cols - start);
   816     cv::Mat centerReg = outIm(cv::Range::all(), cv::Range(0, size.width));
   817     out = centerReg.clone();
   831 bool MarkerDetector::isInto(Mat &contour, vector< Point2f > &b) {
   833     for (
unsigned int i = 0; i < b.size(); i++)
   834         if (pointPolygonTest(contour, b[i], 
false) > 0)
   844 int MarkerDetector::perimeter(vector< Point2f > &a) {
   846     for (
unsigned int i = 0; i < a.size(); i++) {
   847         int i2 = (i + 1) % a.size();
   848         sum += 
sqrt((a[i].
x - a[i2].
x) * (a[i].x - a[i2].x) + (a[i].y - a[i2].y) * (a[i].y - a[i2].y));
   863     vector< int > cornerIndex(4,-1);
   864     for (
unsigned int j = 0; j < candidate.
contour.size(); j++) {
   865         for (
unsigned int k = 0; k < 4; k++) {
   866             if (candidate.
contour[j].x == candidate[k].x && candidate.
contour[j].y == candidate[k].y) {
   874     if ((cornerIndex[1] > cornerIndex[0]) && (cornerIndex[2] > cornerIndex[1] || cornerIndex[2] < cornerIndex[0]))
   876     else if (cornerIndex[2] > cornerIndex[1] && cornerIndex[2] < cornerIndex[0])
   888     vector< Point2f > contour2f;
   889     if(!camMatrix.empty() && !distCoeff.empty()){
   890     for (
unsigned int i = 0; i < candidate.
contour.size(); i++)
   891         contour2f.push_back(cv::Point2f(candidate.
contour[i].x, candidate.
contour[i].y));
   892     if (!camMatrix.empty() && !distCoeff.empty())
   893         cv::undistortPoints(contour2f, contour2f, camMatrix, distCoeff, cv::Mat(), camMatrix);
   897         contour2f.reserve(candidate.
contour.size());
   899             contour2f.push_back(cv::Point2f(p.x,p.y));
   902     vector< std::vector< cv::Point2f > > contourLines;
   903     contourLines.resize(4);
   904     for (
unsigned int l = 0; l < 4; l++) {
   905         for (
int j = (
int)cornerIndex[l]; j != (int)cornerIndex[(l + 1) % 4]; j += inc) {
   908             else if (j == 0 && inverse)
   909                 j = candidate.
contour.size() - 1;
   910             contourLines[l].push_back(contour2f[j]);
   911             if (j == (
int)cornerIndex[(l + 1) % 4])
   917     vector< Point3f > lines;
   919     for (
unsigned int j = 0; j < lines.size(); j++)
   920         interpolate2Dline(contourLines[j], lines[j]);
   923     vector< Point2f > crossPoints;
   924     crossPoints.resize(4);
   925     for (
unsigned int i = 0; i < 4; i++)
   926         crossPoints[i] = getCrossPoint(lines[(i - 1) % 4], lines[i]);
   929     if (!camMatrix.empty() && !distCoeff.empty())
   930         distortPoints(crossPoints, crossPoints, camMatrix, distCoeff);
   933     for (
unsigned int j = 0; j < 4; j++)
   934         candidate[j] = crossPoints[j];
   940 void MarkerDetector::interpolate2Dline(
const std::vector< Point2f > &inPoints, Point3f &outLine) {
   942     float minX, maxX, minY, maxY;
   943     minX = maxX = inPoints[0].x;
   944     minY = maxY = inPoints[0].y;
   945     for (
unsigned int i = 1; i < inPoints.size(); i++) {
   946         if (inPoints[i].
x < minX)
   947             minX = inPoints[i].x;
   948         if (inPoints[i].
x > maxX)
   949             maxX = inPoints[i].x;
   950         if (inPoints[i].y < minY)
   951             minY = inPoints[i].y;
   952         if (inPoints[i].y > maxY)
   953             maxY = inPoints[i].y;
   957     Mat A(inPoints.size(), 2, CV_32FC1, Scalar(0));
   958     Mat B(inPoints.size(), 1, CV_32FC1, Scalar(0));
   963     if (maxX - minX > maxY - minY) {
   965         for (
size_t i = 0; i < inPoints.size(); i++) {
   967             A.at< 
float >(i, 0) = inPoints[i].
x;
   968             A.at< 
float >(i, 1) = 1.;
   969             B.at< 
float >(i, 0) = inPoints[i].y;
   973         solve(A, B, X, DECOMP_SVD);
   975         outLine = Point3f(X.at< 
float >(0, 0), -1., X.at< 
float >(1, 0));
   978         for (
size_t i = 0; i < inPoints.size(); i++) {
   980             A.at< 
float >(i, 0) = inPoints[i].y;
   981             A.at< 
float >(i, 1) = 1.;
   982             B.at< 
float >(i, 0) = inPoints[i].
x;
   986         solve(A, B, X, DECOMP_SVD);
   988         outLine = Point3f(-1., X.at< 
float >(0, 0), X.at< 
float >(1, 0));
   994 Point2f MarkerDetector::getCrossPoint(
const cv::Point3f &line1, 
const cv::Point3f &line2) {
   997     Mat A(2, 2, CV_32FC1, Scalar(0));
   998     Mat B(2, 1, CV_32FC1, Scalar(0));
  1001     A.at< 
float >(0, 0) = line1.x;
  1002     A.at< 
float >(0, 1) = line1.y;
  1003     B.at< 
float >(0, 0) = -line1.z;
  1005     A.at< 
float >(1, 0) = line2.x;
  1006     A.at< 
float >(1, 1) = line2.y;
  1007     B.at< 
float >(1, 0) = -line2.z;
  1010     solve(A, B, X, DECOMP_SVD);
  1011     return Point2f(X.at< 
float >(0, 0), X.at< 
float >(1, 0));
  1017 void MarkerDetector::distortPoints(vector< cv::Point2f > in, vector< cv::Point2f > &out, 
const Mat &camMatrix, 
const Mat &distCoeff) {
  1019     cv::Mat Rvec = cv::Mat(3, 1, CV_32FC1, cv::Scalar::all(0));
  1020     cv::Mat Tvec = Rvec.clone();
  1022     vector< cv::Point3f > cornersPoints3d;
  1023     for (
unsigned int i = 0; i < in.size(); i++)
  1024         cornersPoints3d.push_back(cv::Point3f((in[i].x - camMatrix.at< 
float >(0, 2)) / camMatrix.at< 
float >(0, 0), 
  1025                                               (in[i].y - camMatrix.at< 
float >(1, 2)) / camMatrix.at< 
float >(1, 1), 
  1027     cv::projectPoints(cornersPoints3d, Rvec, Tvec, camMatrix, distCoeff, out);
  1038 void MarkerDetector::drawAllContours(Mat input, std::vector< std::vector< cv::Point > > &contours) { drawContours(input, contours, -1, Scalar(255, 0, 255)); }
  1046 void MarkerDetector::drawContour(Mat &in, vector< Point > &contour, Scalar color) {
  1047     for (
unsigned int i = 0; i < contour.size(); i++) {
  1048         cv::rectangle(in, contour[i], contour[i], color);
  1052 void MarkerDetector::drawApproxCurve(Mat &in, vector< Point > &contour, Scalar color) {
  1053     for (
unsigned int i = 0; i < contour.size(); i++) {
  1054         cv::line(in, contour[i], contour[(i + 1) % contour.size()], color);
  1064 void MarkerDetector::draw(Mat out, 
const vector< Marker > &markers) {
  1065     for (
unsigned int i = 0; i < markers.size(); i++) {
  1066         cv::line(out, markers[i][0], markers[i][1], cvScalar(255, 0, 0), 2, CV_AA);
  1067         cv::line(out, markers[i][1], markers[i][2], cvScalar(255, 0, 0), 2, CV_AA);
  1068         cv::line(out, markers[i][2], markers[i][3], cvScalar(255, 0, 0), 2, CV_AA);
  1069         cv::line(out, markers[i][3], markers[i][0], cvScalar(255, 0, 0), 2, CV_AA);
  1099 void MarkerDetector::findCornerMaxima(vector< cv::Point2f > &Corners, 
const cv::Mat &grey, 
int wsize) {
  1102 #pragma omp parallel for  1104     for (
size_t i = 0; i < Corners.size(); i++) {
  1105         cv::Point2f minLimit(std::max(0, 
int(Corners[i].
x - wsize)), std::max(0, 
int(Corners[i].y - wsize)));
  1106         cv::Point2f maxLimit(std::min(grey.cols, 
int(Corners[i].x + wsize)), std::min(grey.rows, 
int(Corners[i].y + wsize)));
  1108         cv::Mat reg = grey(cv::Range(minLimit.y, maxLimit.y), cv::Range(minLimit.x, maxLimit.x));
  1109         cv::Mat harr, harrint;
  1110         cv::cornerHarris(reg, harr, 3, 3, 0.04);
  1113         cv::integral(harr, harrint);
  1115         for (
int y = bls_a; y < harr.rows - bls_a; y++) {
  1116             float *h = harr.ptr< 
float >(y);
  1117             for (
int x = bls_a; 
x < harr.cols - bls_a; 
x++)
  1118                 h[
x] = harrint.at< 
double >(y + bls_a, 
x + bls_a) - harrint.at< 
double >(y + bls_a, 
x) - harrint.at< 
double >(y, 
x + bls_a) +
  1119                        harrint.at< 
double >(y, 
x);
  1124         cv::Point2f best(-1, -1);
  1125         cv::Point2f center(reg.cols / 2, reg.rows / 2);
  1128         for (
int i = 0; i < harr.rows; i++) {
  1130             float *har = harr.ptr< 
float >(i);
  1131             for (
int x = 0; 
x < harr.cols; 
x++) {
  1132                 float d = float(fabs(center.x - 
x) + fabs(center.y - i)) / float(reg.cols / 2 + reg.rows / 2);
  1134                 if (w * har[
x] > maxv) {
  1136                     best = cv::Point2f(
x, i);
  1140         Corners[i] = best + minLimit;
  1145 void MarkerDetector::setMarkerLabeler(cv::Ptr<MarkerLabeler> detector)
throw(cv::Exception){
  1146     markerIdDetector=detector;
  1147     if (markerIdDetector->getBestInputSize()!=-1)setWarpSize(markerIdDetector->getBestInputSize());
  1152     markerIdDetector= MarkerLabeler::create(dict_type,error_correction_rate);
  1153     if (markerIdDetector->getBestInputSize()!=-1)setWarpSize(markerIdDetector->getBestInputSize());
  1155 void MarkerDetector::setDictionary(
string dict_type,
float error_correction_rate)
throw(cv::Exception){
  1156     markerIdDetector= MarkerLabeler::create(Dictionary::getTypeFromString( dict_type),error_correction_rate);
  1157     if (markerIdDetector->getBestInputSize()!=-1)setWarpSize(markerIdDetector->getBestInputSize());
 
void findCornerPointsInContour(const vector< cv::Point2f > &points, const vector< cv::Point > &contour, vector< int > &idxs)
bool kdtree_get_bbox(BBOX &bb) const 
void resize(cv::Size size)
int findDeformedSidesIdx(const vector< cv::Point > &contour, const vector< int > &idxSegments)
const CwiseUnaryOp< internal::scalar_pow_op< Scalar >, const Derived > pow(const Scalar &exponent) const 
void setPointIntoImage(cv::Point &p, cv::Size s)
int omp_get_max_threads()
size_t kdtree_get_point_count() const 
float kdtree_distance(const float *p1, const size_t idx_p2, size_t size) const 
const CwiseUnaryOp< internal::scalar_inverse_op< Scalar >, const Derived > inverse() const 
TFSIMD_FORCE_INLINE const tfScalar & x() const 
Parameters of the camera. 
TFSIMD_FORCE_INLINE const tfScalar & w() const 
float kdtree_get_pt(const size_t idx, int dim) const 
static cv::Ptr< MarkerLabeler > create(Dictionary::DICT_TYPES dict_type, float error_correction_rate=0)
TFSIMD_FORCE_INLINE Vector3 rotate(const Vector3 &wAxis, const tfScalar angle) const 
vector< cv::Point > contour
const CwiseUnaryOp< internal::scalar_sqrt_op< Scalar >, const Derived > sqrt() const