Commit b2f08277 authored by Pavel Rojtberg's avatar Pavel Rojtberg

aruco: simplify code by using lambdas

parent 250bcd9f
......@@ -279,49 +279,6 @@ static void _filterTooCloseCandidates(const vector< vector< Point2f > > &candida
}
}
/**
* ParallelLoopBody class for the parallelization of the basic candidate detections using
* different threhold window sizes. Called from function _detectInitialCandidates()
*/
class DetectInitialCandidatesParallel : public ParallelLoopBody {
public:
DetectInitialCandidatesParallel(const Mat *_grey,
vector< vector< vector< Point2f > > > *_candidatesArrays,
vector< vector< vector< Point > > > *_contoursArrays,
const Ptr<DetectorParameters> &_params)
: grey(_grey), candidatesArrays(_candidatesArrays), contoursArrays(_contoursArrays),
params(_params) {}
void operator()(const Range &range) const CV_OVERRIDE {
const int begin = range.start;
const int end = range.end;
for(int i = begin; i < end; i++) {
int currScale =
params->adaptiveThreshWinSizeMin + i * params->adaptiveThreshWinSizeStep;
// threshold
Mat thresh;
_threshold(*grey, thresh, currScale, params->adaptiveThreshConstant);
// detect rectangles
_findMarkerContours(thresh, (*candidatesArrays)[i], (*contoursArrays)[i],
params->minMarkerPerimeterRate, params->maxMarkerPerimeterRate,
params->polygonalApproxAccuracyRate, params->minCornerDistanceRate,
params->minDistanceToBorder);
}
}
private:
DetectInitialCandidatesParallel &operator=(const DetectInitialCandidatesParallel &);
const Mat *grey;
vector< vector< vector< Point2f > > > *candidatesArrays;
vector< vector< vector< Point > > > *contoursArrays;
const Ptr<DetectorParameters> &params;
};
/**
* @brief Initial steps on finding square candidates
*/
......@@ -341,21 +298,23 @@ static void _detectInitialCandidates(const Mat &grey, vector< vector< Point2f >
vector< vector< vector< Point > > > contoursArrays((size_t) nScales);
////for each value in the interval of thresholding window sizes
// for(int i = 0; i < nScales; i++) {
// int currScale = params.adaptiveThreshWinSizeMin + i*params.adaptiveThreshWinSizeStep;
// // treshold
// Mat thresh;
// _threshold(grey, thresh, currScale, params.adaptiveThreshConstant);
// // detect rectangles
// _findMarkerContours(thresh, candidatesArrays[i], contoursArrays[i],
// params.minMarkerPerimeterRate,
// params.maxMarkerPerimeterRate, params.polygonalApproxAccuracyRate,
// params.minCornerDistance, params.minDistanceToBorder);
//}
// this is the parallel call for the previous commented loop (result is equivalent)
parallel_for_(Range(0, nScales), DetectInitialCandidatesParallel(&grey, &candidatesArrays,
&contoursArrays, params));
parallel_for_(Range(0, nScales), [&](const Range& range) {
const int begin = range.start;
const int end = range.end;
for (int i = begin; i < end; i++) {
int currScale = params->adaptiveThreshWinSizeMin + i * params->adaptiveThreshWinSizeStep;
// threshold
Mat thresh;
_threshold(grey, thresh, currScale, params->adaptiveThreshConstant);
// detect rectangles
_findMarkerContours(thresh, candidatesArrays[i], contoursArrays[i],
params->minMarkerPerimeterRate, params->maxMarkerPerimeterRate,
params->polygonalApproxAccuracyRate, params->minCornerDistanceRate,
params->minDistanceToBorder);
}
});
// join candidates
for(int i = 0; i < nScales; i++) {
......@@ -545,46 +504,6 @@ static bool _identifyOneCandidate(const Ptr<Dictionary>& dictionary, InputArray
return true;
}
/**
* ParallelLoopBody class for the parallelization of the marker identification step
* Called from function _identifyCandidates()
*/
class IdentifyCandidatesParallel : public ParallelLoopBody {
public:
IdentifyCandidatesParallel(const Mat& _grey, vector< vector< Point2f > >& _candidates,
const Ptr<Dictionary> &_dictionary,
vector< int >& _idsTmp, vector< char >& _validCandidates,
const Ptr<DetectorParameters> &_params)
: grey(_grey), candidates(_candidates), dictionary(_dictionary),
idsTmp(_idsTmp), validCandidates(_validCandidates), params(_params) {}
void operator()(const Range &range) const CV_OVERRIDE {
const int begin = range.start;
const int end = range.end;
for(int i = begin; i < end; i++) {
int currId;
if(_identifyOneCandidate(dictionary, grey, candidates[i], currId, params)) {
validCandidates[i] = 1;
idsTmp[i] = currId;
}
}
}
private:
IdentifyCandidatesParallel &operator=(const IdentifyCandidatesParallel &); // to quiet MSVC
const Mat &grey;
vector< vector< Point2f > >& candidates;
const Ptr<Dictionary> &dictionary;
vector< int > &idsTmp;
vector< char > &validCandidates;
const Ptr<DetectorParameters> &params;
};
/**
* @brief Copy the contents of a corners vector to an OutputArray, settings its size.
*/
......@@ -645,19 +564,18 @@ static void _identifyCandidates(InputArray _image, vector< vector< Point2f > >&
vector< char > validCandidates(ncandidates, 0);
//// Analyze each of the candidates
// for (int i = 0; i < ncandidates; i++) {
// int currId = i;
// Mat currentCandidate = _candidates.getMat(i);
// if (_identifyOneCandidate(dictionary, grey, currentCandidate, currId, params)) {
// validCandidates[i] = 1;
// idsTmp[i] = currId;
// }
//}
// this is the parallel call for the previous commented loop (result is equivalent)
parallel_for_(Range(0, ncandidates),
IdentifyCandidatesParallel(grey, _candidates, _dictionary, idsTmp,
validCandidates, params));
parallel_for_(Range(0, ncandidates), [&](const Range &range) {
const int begin = range.start;
const int end = range.end;
for(int i = begin; i < end; i++) {
int currId;
if(_identifyOneCandidate(_dictionary, grey, _candidates[i], currId, params)) {
validCandidates[i] = 1;
idsTmp[i] = currId;
}
}
});
for(int i = 0; i < ncandidates; i++) {
if(validCandidates[i] == 1) {
......@@ -772,40 +690,6 @@ static void _getSingleMarkerObjectPoints(float markerLength, OutputArray _objPoi
objPoints.ptr< Vec3f >(0)[3] = Vec3f(-markerLength / 2.f, -markerLength / 2.f, 0);
}
/**
* ParallelLoopBody class for the parallelization of the marker corner subpixel refinement
* Called from function detectMarkers()
*/
class MarkerSubpixelParallel : public ParallelLoopBody {
public:
MarkerSubpixelParallel(const Mat *_grey, OutputArrayOfArrays _corners,
const Ptr<DetectorParameters> &_params)
: grey(_grey), corners(_corners), params(_params) {}
void operator()(const Range &range) const CV_OVERRIDE {
const int begin = range.start;
const int end = range.end;
for(int i = begin; i < end; i++) {
cornerSubPix(*grey, corners.getMat(i),
Size(params->cornerRefinementWinSize, params->cornerRefinementWinSize),
Size(-1, -1), TermCriteria(TermCriteria::MAX_ITER | TermCriteria::EPS,
params->cornerRefinementMaxIterations,
params->cornerRefinementMinAccuracy));
}
}
private:
MarkerSubpixelParallel &operator=(const MarkerSubpixelParallel &); // to quiet MSVC
const Mat *grey;
OutputArrayOfArrays corners;
const Ptr<DetectorParameters> &params;
};
/**
* Line fitting A * B = C :: Called from function refineCandidateLines
* @param nContours, contour-container
......@@ -948,34 +832,6 @@ static void _refineCandidateLines(std::vector<Point>& nContours, std::vector<Poi
}
}
/**
* ParallelLoopBody class for the parallelization of the marker corner contour refinement
* Called from function detectMarkers()
*/
class MarkerContourParallel : public ParallelLoopBody {
public:
MarkerContourParallel( vector< vector< Point > >& _contours, vector< vector< Point2f > >& _candidates, const Mat& _camMatrix, const Mat& _distCoeff)
: contours(_contours), candidates(_candidates), camMatrix(_camMatrix), distCoeff(_distCoeff){}
void operator()(const Range &range) const CV_OVERRIDE {
for(int i = range.start; i < range.end; i++) {
_refineCandidateLines(contours[i], candidates[i], camMatrix, distCoeff);
}
}
private:
MarkerContourParallel &operator=(const MarkerContourParallel &){
return *this;
}
vector< vector< Point > >& contours;
vector< vector< Point2f > >& candidates;
const Mat& camMatrix;
const Mat& distCoeff;
};
#ifdef APRIL_DEBUG
static void _darken(const Mat &im){
for (int y = 0; y < im.rows; y++) {
......@@ -1152,17 +1008,19 @@ void detectMarkers(InputArray _image, const Ptr<Dictionary> &_dictionary, Output
_params->cornerRefinementMinAccuracy > 0);
//// do corner refinement for each of the detected markers
// for (unsigned int i = 0; i < _corners.cols(); i++) {
// cornerSubPix(grey, _corners.getMat(i),
// Size(params.cornerRefinementWinSize, params.cornerRefinementWinSize),
// Size(-1, -1), TermCriteria(TermCriteria::MAX_ITER | TermCriteria::EPS,
// params.cornerRefinementMaxIterations,
// params.cornerRefinementMinAccuracy));
//}
// this is the parallel call for the previous commented loop (result is equivalent)
parallel_for_(Range(0, _corners.cols()),
MarkerSubpixelParallel(&grey, _corners, _params));
parallel_for_(Range(0, _corners.cols()), [&](const Range& range) {
const int begin = range.start;
const int end = range.end;
for (int i = begin; i < end; i++) {
cornerSubPix(grey, _corners.getMat(i),
Size(_params->cornerRefinementWinSize, _params->cornerRefinementWinSize),
Size(-1, -1),
TermCriteria(TermCriteria::MAX_ITER | TermCriteria::EPS,
_params->cornerRefinementMaxIterations,
_params->cornerRefinementMinAccuracy));
}
});
}
/// STEP 4, Optional : Corner refinement :: use contour container
......@@ -1171,7 +1029,12 @@ void detectMarkers(InputArray _image, const Ptr<Dictionary> &_dictionary, Output
if(! _ids.empty()){
// do corner refinement using the contours for each detected markers
parallel_for_(Range(0, _corners.cols()), MarkerContourParallel(contours, candidates, camMatrix.getMat(), distCoeff.getMat()));
parallel_for_(Range(0, _corners.cols()), [&](const Range& range) {
for (int i = range.start; i < range.end; i++) {
_refineCandidateLines(contours[i], candidates[i], camMatrix.getMat(),
distCoeff.getMat());
}
});
// copy the corners to the output array
_copyVector2Output(candidates, _corners);
......@@ -1179,42 +1042,6 @@ void detectMarkers(InputArray _image, const Ptr<Dictionary> &_dictionary, Output
}
}
/**
* ParallelLoopBody class for the parallelization of the single markers pose estimation
* Called from function estimatePoseSingleMarkers()
*/
class SinglePoseEstimationParallel : public ParallelLoopBody {
public:
SinglePoseEstimationParallel(Mat& _markerObjPoints, InputArrayOfArrays _corners,
InputArray _cameraMatrix, InputArray _distCoeffs,
Mat& _rvecs, Mat& _tvecs)
: markerObjPoints(_markerObjPoints), corners(_corners), cameraMatrix(_cameraMatrix),
distCoeffs(_distCoeffs), rvecs(_rvecs), tvecs(_tvecs) {}
void operator()(const Range &range) const CV_OVERRIDE {
const int begin = range.start;
const int end = range.end;
for(int i = begin; i < end; i++) {
solvePnP(markerObjPoints, corners.getMat(i), cameraMatrix, distCoeffs,
rvecs.at<Vec3d>(i), tvecs.at<Vec3d>(i));
}
}
private:
SinglePoseEstimationParallel &operator=(const SinglePoseEstimationParallel &); // to quiet MSVC
Mat& markerObjPoints;
InputArrayOfArrays corners;
InputArray cameraMatrix, distCoeffs;
Mat& rvecs, tvecs;
};
/**
*/
void estimatePoseSingleMarkers(InputArrayOfArrays _corners, float markerLength,
......@@ -1232,15 +1059,16 @@ void estimatePoseSingleMarkers(InputArrayOfArrays _corners, float markerLength,
Mat rvecs = _rvecs.getMat(), tvecs = _tvecs.getMat();
//// for each marker, calculate its pose
// for (int i = 0; i < nMarkers; i++) {
// solvePnP(markerObjPoints, _corners.getMat(i), _cameraMatrix, _distCoeffs,
// _rvecs.getMat(i), _tvecs.getMat(i));
//}
// this is the parallel call for the previous commented loop (result is equivalent)
parallel_for_(Range(0, nMarkers),
SinglePoseEstimationParallel(markerObjPoints, _corners, _cameraMatrix,
_distCoeffs, rvecs, tvecs));
parallel_for_(Range(0, nMarkers), [&](const Range& range) {
const int begin = range.start;
const int end = range.end;
for (int i = begin; i < end; i++) {
solvePnP(markerObjPoints, _corners.getMat(i), _cameraMatrix, _distCoeffs, rvecs.at<Vec3d>(i),
tvecs.at<Vec3d>(i));
}
});
if(_objPoints.needed()){
markerObjPoints.convertTo(_objPoints, -1);
}
......
......@@ -270,50 +270,6 @@ static int _filterCornersWithoutMinMarkers(const Ptr<CharucoBoard> &_board,
return (int)_filteredCharucoIds.total();
}
/**
* ParallelLoopBody class for the parallelization of the charuco corners subpixel refinement
* Called from function _selectAndRefineChessboardCorners()
*/
class CharucoSubpixelParallel : public ParallelLoopBody {
public:
CharucoSubpixelParallel(const Mat *_grey, vector< Point2f > *_filteredChessboardImgPoints,
vector< Size > *_filteredWinSizes, const Ptr<DetectorParameters> &_params)
: grey(_grey), filteredChessboardImgPoints(_filteredChessboardImgPoints),
filteredWinSizes(_filteredWinSizes), params(_params) {}
void operator()(const Range &range) const CV_OVERRIDE {
const int begin = range.start;
const int end = range.end;
for(int i = begin; i < end; i++) {
vector< Point2f > in;
in.push_back((*filteredChessboardImgPoints)[i]);
Size winSize = (*filteredWinSizes)[i];
if(winSize.height == -1 || winSize.width == -1)
winSize = Size(params->cornerRefinementWinSize, params->cornerRefinementWinSize);
cornerSubPix(*grey, in, winSize, Size(),
TermCriteria(TermCriteria::MAX_ITER | TermCriteria::EPS,
params->cornerRefinementMaxIterations,
params->cornerRefinementMinAccuracy));
(*filteredChessboardImgPoints)[i] = in[0];
}
}
private:
CharucoSubpixelParallel &operator=(const CharucoSubpixelParallel &); // to quiet MSVC
const Mat *grey;
vector< Point2f > *filteredChessboardImgPoints;
vector< Size > *filteredWinSizes;
const Ptr<DetectorParameters> &params;
};
/**
* @brief From all projected chessboard corners, select those inside the image and apply subpixel
* refinement. Returns number of valid corners.
......@@ -353,23 +309,25 @@ static int _selectAndRefineChessboardCorners(InputArray _allCorners, InputArray
const Ptr<DetectorParameters> params = DetectorParameters::create(); // use default params for corner refinement
//// For each of the charuco corners, apply subpixel refinement using its correspondind winSize
// for(unsigned int i=0; i<filteredChessboardImgPoints.size(); i++) {
// vector<Point2f> in;
// in.push_back(filteredChessboardImgPoints[i]);
// Size winSize = filteredWinSizes[i];
// if(winSize.height == -1 || winSize.width == -1)
// winSize = Size(params.cornerRefinementWinSize, params.cornerRefinementWinSize);
// cornerSubPix(grey, in, winSize, Size(),
// TermCriteria(TermCriteria::MAX_ITER | TermCriteria::EPS,
// params->cornerRefinementMaxIterations,
// params->cornerRefinementMinAccuracy));
// filteredChessboardImgPoints[i] = in[0];
//}
// this is the parallel call for the previous commented loop (result is equivalent)
parallel_for_(
Range(0, (int)filteredChessboardImgPoints.size()),
CharucoSubpixelParallel(&grey, &filteredChessboardImgPoints, &filteredWinSizes, params));
parallel_for_(Range(0, (int)filteredChessboardImgPoints.size()), [&](const Range& range) {
const int begin = range.start;
const int end = range.end;
for (int i = begin; i < end; i++) {
vector<Point2f> in;
in.push_back(filteredChessboardImgPoints[i]);
Size winSize = filteredWinSizes[i];
if (winSize.height == -1 || winSize.width == -1)
winSize = Size(params->cornerRefinementWinSize, params->cornerRefinementWinSize);
cornerSubPix(grey, in, winSize, Size(),
TermCriteria(TermCriteria::MAX_ITER | TermCriteria::EPS,
params->cornerRefinementMaxIterations,
params->cornerRefinementMinAccuracy));
filteredChessboardImgPoints[i] = in[0];
}
});
// parse output
Mat(filteredChessboardImgPoints).copyTo(_selectedCorners);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment