30 #include <opencv2/core/core.hpp> 31 #include <opencv2/features2d/features2d.hpp> 32 #include <opencv2/imgproc/imgproc.hpp> 33 #include <opencv2/calib3d/calib3d.hpp> 34 #include <opencv2/highgui/highgui.hpp> 50 MarkerDetector::MarkerDetector() {
51 _thresMethod = ADPT_THRES;
52 _thresParam1 = _thresParam2 = 7;
53 _cornerMethod = LINES;
54 _useLockedCorners =
false;
56 _thresParam1_range = 0;
63 _borderDistThres = 0.025;
72 MarkerDetector::~MarkerDetector() {}
80 void MarkerDetector::setDesiredSpeed(
int val) {
91 _cornerMethod = SUBPIX;
108 void MarkerDetector::detect(
const cv::Mat &input, std::vector< Marker > &detectedMarkers,
CameraParameters camParams,
float markerSizeMeters,
109 bool setYPerpendicular)
throw(cv::Exception) {
110 detect(input, detectedMarkers, camParams.CameraMatrix, camParams.Distorsion, markerSizeMeters, setYPerpendicular);
117 void MarkerDetector::enableLockedCornersMethod(
bool enable) {
118 _useLockedCorners = enable;
120 _cornerMethod = SUBPIX;
128 void MarkerDetector::detect(
const cv::Mat &input, vector< Marker > &detectedMarkers, Mat camMatrix, Mat distCoeff,
float markerSizeMeters,
129 bool setYPerpendicular)
throw(cv::Exception) {
132 if (input.type() == CV_8UC3)
133 cv::cvtColor(input, grey, CV_BGR2GRAY);
136 double t1 = cv::getTickCount();
140 detectedMarkers.clear();
143 cv::Mat imgToBeThresHolded = grey;
144 double ThresParam1 = _thresParam1, ThresParam2 = _thresParam2;
148 int n_param1 = 2 * _thresParam1_range + 1;
149 vector< cv::Mat > thres_images(n_param1);
150 #pragma omp parallel for 151 for (
int i = 0; i < n_param1; i++) {
152 double t1 = ThresParam1 - _thresParam1_range + _thresParam1_range * i;
153 thresHold(_thresMethod, imgToBeThresHolded, thres_images[i], t1, ThresParam2);
155 thres = thres_images[n_param1 / 2];
158 double t2 = cv::getTickCount();
160 vector< MarkerCandidate > MarkerCanditates;
161 detectRectangles(thres_images, MarkerCanditates);
163 double t3 = cv::getTickCount();
169 for (
int i = 0; i < MarkerCanditates.size(); i++) {
173 resW = warp(grey, canonicalMarker, Size(_markerWarpSize, _markerWarpSize), MarkerCanditates[i]);
176 int id = (*markerIdDetector_ptrfunc)(canonicalMarker, nRotations);
178 if (_cornerMethod == LINES)
179 refineCandidateLines(MarkerCanditates[i], camMatrix, distCoeff);
190 joinVectors(markers_omp, detectedMarkers,
true);
191 joinVectors(candidates_omp, _candidates,
true);
194 double t4 = cv::getTickCount();
197 if (detectedMarkers.size() > 0 && _cornerMethod != NONE && _cornerMethod != LINES) {
199 vector< Point2f > Corners;
200 for (
unsigned int i = 0; i < detectedMarkers.size(); i++)
201 for (
int c = 0; c < 4; c++)
202 Corners.push_back(detectedMarkers[i][c]);
206 if (_useLockedCorners)
207 findCornerMaxima(Corners, grey, _thresParam1);
209 if (_cornerMethod == HARRIS)
210 findBestCornerInRegion_harris(grey, Corners, 7);
211 else if (_cornerMethod == SUBPIX) {
212 cornerSubPix(grey, Corners, cvSize(_thresParam1, _thresParam1), cvSize(-1, -1), cvTermCriteria(CV_TERMCRIT_ITER | CV_TERMCRIT_EPS, 8, 0.005));
215 for (
unsigned int i = 0; i < detectedMarkers.size(); i++)
216 for (
int c = 0; c < 4; c++)
217 detectedMarkers[i][c] = Corners[i * 4 + c];
220 double t5 = cv::getTickCount();
223 std::sort(detectedMarkers.begin(), detectedMarkers.end());
226 vector< bool > toRemove(detectedMarkers.size(),
false);
227 for (
int i = 0; i < int(detectedMarkers.size()) - 1; i++) {
228 if (detectedMarkers[i].
id == detectedMarkers[i + 1].
id && !toRemove[i + 1]) {
230 if (perimeter(detectedMarkers[i]) > perimeter(detectedMarkers[i + 1]))
231 toRemove[i + 1] =
true;
238 removeElements(detectedMarkers, toRemove);
241 if (camMatrix.rows != 0 && markerSizeMeters > 0) {
242 for (
unsigned int i = 0; i < detectedMarkers.size(); i++)
243 detectedMarkers[i].calculateExtrinsics(markerSizeMeters, camMatrix, distCoeff, setYPerpendicular);
245 double t6 = cv::getTickCount();
261 void MarkerDetector::detectRectangles(
const cv::Mat &thres, vector< std::vector< cv::Point2f > > &MarkerCanditates) {
262 vector< MarkerCandidate > candidates;
263 vector< cv::Mat > thres_v;
264 thres_v.push_back(thres);
265 detectRectangles(thres_v, candidates);
267 MarkerCanditates.resize(candidates.size());
268 for (
size_t i = 0; i < MarkerCanditates.size(); i++)
269 MarkerCanditates[i] = candidates[i];
272 void MarkerDetector::detectRectangles(vector< cv::Mat > &thresImgv, vector< MarkerCandidate > &OutMarkerCanditates) {
276 int minSize = _minSize * std::max(thresImgv[0].cols, thresImgv[0].rows) * 4;
277 int maxSize = _maxSize * std::max(thresImgv[0].cols, thresImgv[0].rows) * 4;
282 #pragma omp parallel for 283 for (
size_t i = 0; i < thresImgv.size(); i++) {
284 std::vector< cv::Vec4i > hierarchy2;
285 std::vector< std::vector< cv::Point > > contours2;
287 thresImgv[i].copyTo(thres2);
288 cv::findContours(thres2, contours2, hierarchy2, CV_RETR_LIST, CV_CHAIN_APPROX_NONE);
291 vector< Point > approxCurve;
293 for (
unsigned int i = 0; i < contours2.size(); i++) {
296 if (minSize < contours2[i].size() && contours2[i].size() < maxSize) {
298 approxPolyDP(contours2[i], approxCurve,
double(contours2[i].size()) * 0.05,
true);
301 if (approxCurve.size() == 4) {
308 if (isContourConvex(Mat(approxCurve))) {
311 float minDist = 1e10;
312 for (
int j = 0; j < 4; j++) {
313 float d = std::sqrt((
float)(approxCurve[j].x - approxCurve[(j + 1) % 4].x) * (approxCurve[j].x - approxCurve[(j + 1) % 4].x) +
314 (approxCurve[j].y - approxCurve[(j + 1) % 4].y) * (approxCurve[j].y - approxCurve[(j + 1) % 4].y));
325 for (
int j = 0; j < 4; j++) {
326 MarkerCanditatesV[
omp_get_thread_num()].back().push_back(Point2f(approxCurve[j].x, approxCurve[j].y));
336 vector< MarkerCandidate > MarkerCanditates;
338 for (
size_t i = 0; i < MarkerCanditatesV.size(); i++)
339 for (
size_t j = 0; j < MarkerCanditatesV[i].size(); j++) {
340 MarkerCanditates.push_back(MarkerCanditatesV[i][j]);
345 valarray< bool > swapped(
false, MarkerCanditates.size());
346 for (
unsigned int i = 0; i < MarkerCanditates.size(); i++) {
350 double dx1 = MarkerCanditates[i][1].x - MarkerCanditates[i][0].x;
351 double dy1 = MarkerCanditates[i][1].y - MarkerCanditates[i][0].y;
352 double dx2 = MarkerCanditates[i][2].x - MarkerCanditates[i][0].x;
353 double dy2 = MarkerCanditates[i][2].y - MarkerCanditates[i][0].y;
354 double o = (dx1 * dy2) - (dy1 * dx2);
357 swap(MarkerCanditates[i][1], MarkerCanditates[i][3]);
368 #pragma omp parallel for 369 for (
unsigned int i = 0; i < MarkerCanditates.size(); i++) {
372 for (
unsigned int j = i + 1; j < MarkerCanditates.size(); j++) {
373 valarray< float > vdist(4);
374 for (
int c = 0; c < 4; c++)
375 vdist[c] = sqrt((MarkerCanditates[i][c].x - MarkerCanditates[j][c].x) * (MarkerCanditates[i][c].x - MarkerCanditates[j][c].x) +
376 (MarkerCanditates[i][c].y - MarkerCanditates[j][c].y) * (MarkerCanditates[i][c].y - MarkerCanditates[j][c].y));
379 if (vdist[0] < 6 && vdist[1] < 6 && vdist[2] < 6 && vdist[3] < 6) {
385 vector< pair< int, int > > TooNearCandidates;
386 joinVectors(TooNearCandidates_omp, TooNearCandidates);
388 valarray< bool > toRemove(
false, MarkerCanditates.size());
389 for (
unsigned int i = 0; i < TooNearCandidates.size(); i++) {
390 if (perimeter(MarkerCanditates[TooNearCandidates[i].first]) > perimeter(MarkerCanditates[TooNearCandidates[i].second]))
391 toRemove[TooNearCandidates[i].second] =
true;
393 toRemove[TooNearCandidates[i].first] =
true;
398 OutMarkerCanditates.reserve(MarkerCanditates.size());
399 for (
size_t i = 0; i < MarkerCanditates.size(); i++) {
401 OutMarkerCanditates.push_back(MarkerCanditates[i]);
404 reverse(OutMarkerCanditates.back().contour.begin(), OutMarkerCanditates.back().contour.end());
422 void MarkerDetector::thresHold(
int method,
const Mat &grey, Mat &out,
double param1,
double param2)
throw(cv::Exception) {
425 param1 = _thresParam1;
427 param2 = _thresParam2;
429 if (grey.type() != CV_8UC1)
430 throw cv::Exception(9001,
"grey.type()!=CV_8UC1",
"MarkerDetector::thresHold", __FILE__, __LINE__);
433 cv::threshold(grey, out, param1, 255, CV_THRESH_BINARY_INV);
439 else if (((
int)param1) % 2 != 1)
440 param1 = (int)(param1 + 1);
442 cv::adaptiveThreshold(grey, out, 255, ADAPTIVE_THRESH_MEAN_C, THRESH_BINARY_INV, param1, param2);
449 cv::Canny(grey, out, 10, 220);
464 bool MarkerDetector::warp(Mat &in, Mat &out, Size size, vector< Point2f > points)
throw(cv::Exception) {
466 if (points.size() != 4)
467 throw cv::Exception(9001,
"point.size()!=4",
"MarkerDetector::warp", __FILE__, __LINE__);
469 Point2f pointsRes[4], pointsIn[4];
470 for (
int i = 0; i < 4; i++)
471 pointsIn[i] = points[i];
472 pointsRes[0] = (Point2f(0, 0));
473 pointsRes[1] = Point2f(size.width - 1, 0);
474 pointsRes[2] = Point2f(size.width - 1, size.height - 1);
475 pointsRes[3] = Point2f(0, size.height - 1);
476 Mat M = getPerspectiveTransform(pointsIn, pointsRes);
477 cv::warpPerspective(in, out, M, size, cv::INTER_NEAREST);
482 assert(points.size() == 4);
483 int idxSegments[4] = {-1, -1, -1, -1};
485 cv::Point points2i[4];
486 for (
int i = 0; i < 4; i++) {
487 points2i[i].x = points[i].x;
488 points2i[i].y = points[i].y;
491 for (
size_t i = 0; i < contour.size(); i++) {
492 if (idxSegments[0] == -1)
493 if (contour[i] == points2i[0])
495 if (idxSegments[1] == -1)
496 if (contour[i] == points2i[1])
498 if (idxSegments[2] == -1)
499 if (contour[i] == points2i[2])
501 if (idxSegments[3] == -1)
502 if (contour[i] == points2i[3])
506 for (
int i = 0; i < 4; i++)
507 idxs[i] = idxSegments[i];
511 float distSum[4] = {0, 0, 0, 0};
512 cv::Scalar colors[4] = {cv::Scalar(0, 0, 255), cv::Scalar(255, 0, 0), cv::Scalar(0, 255, 0), cv::Scalar(111, 111, 0)};
514 for (
int i = 0; i < 3; i++) {
515 cv::Point p1 = contour[idxSegments[i]];
516 cv::Point p2 = contour[idxSegments[i + 1]];
517 float inv_den = 1. / sqrt(
float((p2.x - p1.x) * (p2.x - p1.x) + (p2.y - p1.y) * (p2.y - p1.y)));
520 for (
size_t j = idxSegments[i]; j < idxSegments[i + 1]; j++) {
521 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;
526 distSum[i] /= float(idxSegments[i + 1] - idxSegments[i]);
532 cv::Point p1 = contour[idxSegments[0]];
533 cv::Point p2 = contour[idxSegments[3]];
534 float inv_den = 1. / std::sqrt(
float((p2.x - p1.x) * (p2.x - p1.x) + (p2.y - p1.y) * (p2.y - p1.y)));
536 for (
size_t j = 0; j < idxSegments[0]; j++)
537 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;
538 for (
size_t j = idxSegments[3]; j < contour.size(); j++)
539 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;
541 distSum[3] /= float(idxSegments[0] + (contour.size() - idxSegments[3]));
546 if (distSum[0] + distSum[2] > distSum[1] + distSum[3])
555 else if (p.x >= s.width)
559 else if (p.y >= s.height)
566 else if (p.x >= s.width)
570 else if (p.y >= s.height)
579 bool MarkerDetector::warp_cylinder(Mat &in, Mat &out, Size size,
MarkerCandidate &mcand)
throw(cv::Exception) {
581 if (mcand.size() != 4)
582 throw cv::Exception(9001,
"point.size()!=4",
"MarkerDetector::warp", __FILE__, __LINE__);
592 vector< int > idxSegments;
596 for (
int i = 1; i < 4; i++)
597 if (idxSegments[i] < idxSegments[minIdx])
600 std::rotate(idxSegments.begin(), idxSegments.begin() + minIdx, idxSegments.end());
601 std::rotate(mcand.begin(), mcand.begin() + minIdx, mcand.end());
610 cv::Point2f center = mcand.getCenter();
611 Point2f enlargedRegion[4];
612 for (
int i = 0; i < 4; i++)
613 enlargedRegion[i] = mcand[i];
614 if (defrmdSide == 0) {
615 enlargedRegion[0] = mcand[0] + (mcand[3] - mcand[0]) * 1.2;
616 enlargedRegion[1] = mcand[1] + (mcand[2] - mcand[1]) * 1.2;
617 enlargedRegion[2] = mcand[2] + (mcand[1] - mcand[2]) * 1.2;
618 enlargedRegion[3] = mcand[3] + (mcand[0] - mcand[3]) * 1.2;
620 enlargedRegion[0] = mcand[0] + (mcand[1] - mcand[0]) * 1.2;
621 enlargedRegion[1] = mcand[1] + (mcand[0] - mcand[1]) * 1.2;
622 enlargedRegion[2] = mcand[2] + (mcand[3] - mcand[2]) * 1.2;
623 enlargedRegion[3] = mcand[3] + (mcand[2] - mcand[3]) * 1.2;
625 for (
size_t i = 0; i < 4; i++)
643 Point2f pointsRes[4], pointsIn[4];
644 for (
int i = 0; i < 4; i++)
645 pointsIn[i] = mcand[i];
647 cv::Size enlargedSize = size;
648 enlargedSize.width += 2 * enlargedSize.width * 0.2;
649 pointsRes[0] = (Point2f(0, 0));
650 pointsRes[1] = Point2f(enlargedSize.width - 1, 0);
651 pointsRes[2] = Point2f(enlargedSize.width - 1, enlargedSize.height - 1);
652 pointsRes[3] = Point2f(0, enlargedSize.height - 1);
655 rotate(pointsRes, pointsRes + 1, pointsRes + 4);
656 cv::Mat imAux, imAux2(enlargedSize, CV_8UC1);
657 Mat M = cv::getPerspectiveTransform(enlargedRegion, pointsRes);
658 cv::warpPerspective(in, imAux, M, enlargedSize, cv::INTER_NEAREST);
661 vector< cv::Point > pointsCO(mcand.contour.size());
662 assert(M.type() == CV_64F);
663 assert(M.cols == 3 && M.rows == 3);
665 double *mptr = M.ptr<
double >(0);
666 imAux2.setTo(cv::Scalar::all(0));
669 for (
size_t i = 0; i < mcand.contour.size(); i++) {
670 float inX = mcand.contour[i].x;
671 float inY = mcand.contour[i].y;
672 float w = inX * mptr[6] + inY * mptr[7] + mptr[8];
674 pointsCO[i].x = ((inX * mptr[0] + inY * mptr[1] + mptr[2]) / w) + 0.5;
675 pointsCO[i].y = ((inX * mptr[3] + inY * mptr[4] + mptr[5]) / w) + 0.5;
679 imAux2.at< uchar >(pointsCO[i].y, pointsCO[i].x) = 255;
680 if (pointsCO[i].y > 0)
681 imAux2.at< uchar >(pointsCO[i].y - 1, pointsCO[i].x) = 255;
682 if (pointsCO[i].y < imAux2.rows - 1)
683 imAux2.at< uchar >(pointsCO[i].y + 1, pointsCO[i].x) = 255;
686 cv::Mat outIm(enlargedSize, CV_8UC1);
687 outIm.setTo(cv::Scalar::all(0));
689 for (
int y = 0; y < imAux2.rows; y++) {
690 uchar *_offInfo = imAux2.ptr< uchar >(y);
691 int start = -1, end = -1;
693 for (
int x = 0; x < imAux.cols; x++) {
703 assert(start != -1 && end != -1 && (end - start) > size.width >> 1);
704 uchar *In_image = imAux.ptr< uchar >(y);
705 uchar *Out_image = outIm.ptr< uchar >(y);
706 memcpy(Out_image, In_image + start, imAux.cols - start);
712 cv::Mat centerReg = outIm(cv::Range::all(), cv::Range(0, size.width));
713 out = centerReg.clone();
727 bool MarkerDetector::isInto(Mat &contour, vector< Point2f > &b) {
729 for (
unsigned int i = 0; i < b.size(); i++)
730 if (pointPolygonTest(contour, b[i],
false) > 0)
740 int MarkerDetector::perimeter(vector< Point2f > &a) {
742 for (
unsigned int i = 0; i < a.size(); i++) {
743 int i2 = (i + 1) % a.size();
744 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));
754 void MarkerDetector::findBestCornerInRegion_harris(
const cv::Mat &grey, vector< cv::Point2f > &Corners,
int blockSize) {
766 vector< unsigned int > cornerIndex;
767 cornerIndex.resize(4);
768 for (
unsigned int j = 0; j < candidate.
contour.size(); j++) {
769 for (
unsigned int k = 0; k < 4; k++) {
770 if (candidate.
contour[j].x == candidate[k].x && candidate.
contour[j].y == candidate[k].y) {
778 if ((cornerIndex[1] > cornerIndex[0]) && (cornerIndex[2] > cornerIndex[1] || cornerIndex[2] < cornerIndex[0]))
780 else if (cornerIndex[2] > cornerIndex[1] && cornerIndex[2] < cornerIndex[0])
792 vector< Point2f > contour2f;
793 for (
unsigned int i = 0; i < candidate.
contour.size(); i++)
794 contour2f.push_back(cv::Point2f(candidate.
contour[i].x, candidate.
contour[i].y));
795 if (!camMatrix.empty() && !distCoeff.empty())
796 cv::undistortPoints(contour2f, contour2f, camMatrix, distCoeff, cv::Mat(), camMatrix);
799 vector< std::vector< cv::Point2f > > contourLines;
800 contourLines.resize(4);
801 for (
unsigned int l = 0; l < 4; l++) {
802 for (
int j = (
int)cornerIndex[l]; j != (int)cornerIndex[(l + 1) % 4]; j += inc) {
803 if (j == (
int)candidate.
contour.size() && !inverse)
805 else if (j == 0 && inverse)
806 j = candidate.
contour.size() - 1;
807 contourLines[l].push_back(contour2f[j]);
808 if (j == (
int)cornerIndex[(l + 1) % 4])
814 vector< Point3f > lines;
816 for (
unsigned int j = 0; j < lines.size(); j++)
817 interpolate2Dline(contourLines[j], lines[j]);
820 vector< Point2f > crossPoints;
821 crossPoints.resize(4);
822 for (
unsigned int i = 0; i < 4; i++)
823 crossPoints[i] = getCrossPoint(lines[(i - 1) % 4], lines[i]);
826 if (!camMatrix.empty() && !distCoeff.empty())
827 distortPoints(crossPoints, crossPoints, camMatrix, distCoeff);
830 for (
unsigned int j = 0; j < 4; j++)
831 candidate[j] = crossPoints[j];
837 void MarkerDetector::interpolate2Dline(
const std::vector< Point2f > &inPoints, Point3f &outLine) {
839 float minX, maxX, minY, maxY;
840 minX = maxX = inPoints[0].x;
841 minY = maxY = inPoints[0].y;
842 for (
unsigned int i = 1; i < inPoints.size(); i++) {
843 if (inPoints[i].x < minX)
844 minX = inPoints[i].x;
845 if (inPoints[i].x > maxX)
846 maxX = inPoints[i].x;
847 if (inPoints[i].y < minY)
848 minY = inPoints[i].y;
849 if (inPoints[i].y > maxY)
850 maxY = inPoints[i].y;
854 Mat A(inPoints.size(), 2, CV_32FC1, Scalar(0));
855 Mat B(inPoints.size(), 1, CV_32FC1, Scalar(0));
860 if (maxX - minX > maxY - minY) {
862 for (
int i = 0; i < inPoints.size(); i++) {
864 A.at<
float >(i, 0) = inPoints[i].x;
865 A.at<
float >(i, 1) = 1.;
866 B.at<
float >(i, 0) = inPoints[i].y;
870 solve(A, B, X, DECOMP_SVD);
872 outLine = Point3f(X.at<
float >(0, 0), -1., X.at<
float >(1, 0));
875 for (
int i = 0; i < inPoints.size(); i++) {
877 A.at<
float >(i, 0) = inPoints[i].y;
878 A.at<
float >(i, 1) = 1.;
879 B.at<
float >(i, 0) = inPoints[i].x;
883 solve(A, B, X, DECOMP_SVD);
885 outLine = Point3f(-1., X.at<
float >(0, 0), X.at<
float >(1, 0));
891 Point2f MarkerDetector::getCrossPoint(
const cv::Point3f &line1,
const cv::Point3f &line2) {
894 Mat A(2, 2, CV_32FC1, Scalar(0));
895 Mat B(2, 1, CV_32FC1, Scalar(0));
898 A.at<
float >(0, 0) = line1.x;
899 A.at<
float >(0, 1) = line1.y;
900 B.at<
float >(0, 0) = -line1.z;
902 A.at<
float >(1, 0) = line2.x;
903 A.at<
float >(1, 1) = line2.y;
904 B.at<
float >(1, 0) = -line2.z;
907 solve(A, B, X, DECOMP_SVD);
908 return Point2f(X.at<
float >(0, 0), X.at<
float >(1, 0));
914 void MarkerDetector::distortPoints(vector< cv::Point2f > in, vector< cv::Point2f > &out,
const Mat &camMatrix,
const Mat &distCoeff) {
916 cv::Mat Rvec = cv::Mat(3, 1, CV_32FC1, cv::Scalar::all(0));
917 cv::Mat Tvec = Rvec.clone();
919 vector< cv::Point3f > cornersPoints3d;
920 for (
unsigned int i = 0; i < in.size(); i++)
921 cornersPoints3d.push_back(cv::Point3f((in[i].x - camMatrix.at<
float >(0, 2)) / camMatrix.at<
float >(0, 0),
922 (in[i].y - camMatrix.at<
float >(1, 2)) / camMatrix.at<
float >(1, 1),
924 cv::projectPoints(cornersPoints3d, Rvec, Tvec, camMatrix, distCoeff, out);
935 void MarkerDetector::drawAllContours(Mat input, std::vector< std::vector< cv::Point > > &contours) { drawContours(input, contours, -1, Scalar(255, 0, 255)); }
943 void MarkerDetector::drawContour(Mat &in, vector< Point > &contour, Scalar color) {
944 for (
unsigned int i = 0; i < contour.size(); i++) {
945 cv::rectangle(in, contour[i], contour[i], color);
949 void MarkerDetector::drawApproxCurve(Mat &in, vector< Point > &contour, Scalar color) {
950 for (
unsigned int i = 0; i < contour.size(); i++) {
951 cv::line(in, contour[i], contour[(i + 1) % contour.size()], color);
961 void MarkerDetector::draw(Mat out,
const vector< Marker > &markers) {
962 for (
unsigned int i = 0; i < markers.size(); i++) {
963 cv::line(out, markers[i][0], markers[i][1], cvScalar(255, 0, 0), 2, CV_AA);
964 cv::line(out, markers[i][1], markers[i][2], cvScalar(255, 0, 0), 2, CV_AA);
965 cv::line(out, markers[i][2], markers[i][3], cvScalar(255, 0, 0), 2, CV_AA);
966 cv::line(out, markers[i][3], markers[i][0], cvScalar(255, 0, 0), 2, CV_AA);
1001 void MarkerDetector::glGetProjectionMatrix(
CameraParameters &CamMatrix, cv::Size orgImgSize, cv::Size size,
double proj_matrix[16],
double gnear,
double gfar,
1002 bool invert)
throw(cv::Exception) {
1003 cerr <<
"MarkerDetector::glGetProjectionMatrix . This a deprecated function. Use CameraParameters::glGetProjectionMatrix instead. " << __FILE__ <<
" " 1004 << __LINE__ << endl;
1005 CamMatrix.glGetProjectionMatrix(orgImgSize, size, proj_matrix, gnear, gfar, invert);
1015 void MarkerDetector::setMinMaxSize(
float min,
float max)
throw(cv::Exception) {
1016 if (min <= 0 || min > 1)
1017 throw cv::Exception(1,
" min parameter out of range",
"MarkerDetector::setMinMaxSize", __FILE__, __LINE__);
1018 if (max <= 0 || max > 1)
1019 throw cv::Exception(1,
" max parameter out of range",
"MarkerDetector::setMinMaxSize", __FILE__, __LINE__);
1021 throw cv::Exception(1,
" min>max",
"MarkerDetector::setMinMaxSize", __FILE__, __LINE__);
1033 void MarkerDetector::setWarpSize(
int val)
throw(cv::Exception) {
1035 throw cv::Exception(1,
" invalid canonical image size",
"MarkerDetector::setWarpSize", __FILE__, __LINE__);
1036 _markerWarpSize = val;
1040 void MarkerDetector::findCornerMaxima(vector< cv::Point2f > &Corners,
const cv::Mat &grey,
int wsize) {
1043 #pragma omp parallel for 1045 for (
size_t i = 0; i < Corners.size(); i++) {
1046 cv::Point2f minLimit(std::max(0,
int(Corners[i].x - wsize)), std::max(0,
int(Corners[i].y - wsize)));
1047 cv::Point2f maxLimit(std::min(grey.cols,
int(Corners[i].x + wsize)), std::min(grey.rows,
int(Corners[i].y + wsize)));
1049 cv::Mat reg = grey(cv::Range(minLimit.y, maxLimit.y), cv::Range(minLimit.x, maxLimit.x));
1050 cv::Mat harr, harrint;
1051 cv::cornerHarris(reg, harr, 3, 3, 0.04);
1054 cv::integral(harr, harrint);
1056 for (
int y = bls_a; y < harr.rows - bls_a; y++) {
1057 float *h = harr.ptr<
float >(y);
1058 for (
int x = bls_a; x < harr.cols - bls_a; x++)
1059 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) +
1060 harrint.at<
double >(y, x);
1065 cv::Point2f best(-1, -1);
1066 cv::Point2f center(reg.cols / 2, reg.rows / 2);
1069 for (
size_t i = 0; i < harr.rows; i++) {
1071 float *har = harr.ptr<
float >(i);
1072 for (
size_t x = 0; x < harr.cols; x++) {
1073 float d = float(fabs(center.x - x) + fabs(center.y - i)) / float(reg.cols / 2 + reg.rows / 2);
1075 if (w * har[x] > maxv) {
1077 best = cv::Point2f(x, i);
1081 Corners[i] = best + minLimit;
void findCornerPointsInContour(const vector< cv::Point2f > &points, const vector< cv::Point > &contour, vector< int > &idxs)
void RefineCorner(cv::Mat image, std::vector< cv::Point2f > &corners)
method to refine the corners
int findDeformedSidesIdx(const vector< cv::Point > &contour, const vector< int > &idxSegments)
void setPointIntoImage(cv::Point &p, cv::Size s)
int omp_get_max_threads()
static int detect(const cv::Mat &in, int &nRotations)
Parameters of the camera.
vector< cv::Point > contour