Commit 1df640a6 authored by Maksim Shabunin's avatar Maksim Shabunin

Merge pull request #786 from paroj:aruco_nocopy

parents 9ed1d7e6 b05edca6
...@@ -356,8 +356,8 @@ static void _detectInitialCandidates(const Mat &grey, vector< vector< Point2f > ...@@ -356,8 +356,8 @@ static void _detectInitialCandidates(const Mat &grey, vector< vector< Point2f >
/** /**
* @brief Detect square candidates in the input image * @brief Detect square candidates in the input image
*/ */
static void _detectCandidates(InputArray _image, OutputArrayOfArrays _candidates, static void _detectCandidates(InputArray _image, vector< vector< Point2f > >& candidatesOut,
OutputArrayOfArrays _contours, const Ptr<DetectorParameters> &_params) { vector< vector< Point > >& contoursOut, const Ptr<DetectorParameters> &_params) {
Mat image = _image.getMat(); Mat image = _image.getMat();
CV_Assert(image.total() != 0); CV_Assert(image.total() != 0);
...@@ -375,25 +375,8 @@ static void _detectCandidates(InputArray _image, OutputArrayOfArrays _candidates ...@@ -375,25 +375,8 @@ static void _detectCandidates(InputArray _image, OutputArrayOfArrays _candidates
_reorderCandidatesCorners(candidates); _reorderCandidatesCorners(candidates);
/// 4. FILTER OUT NEAR CANDIDATE PAIRS /// 4. FILTER OUT NEAR CANDIDATE PAIRS
vector< vector< Point2f > > candidatesOut;
vector< vector< Point > > contoursOut;
_filterTooCloseCandidates(candidates, candidatesOut, contours, contoursOut, _filterTooCloseCandidates(candidates, candidatesOut, contours, contoursOut,
_params->minMarkerDistanceRate); _params->minMarkerDistanceRate);
// parse output
_candidates.create((int)candidatesOut.size(), 1, CV_32FC2);
_contours.create((int)contoursOut.size(), 1, CV_32SC2);
for(int i = 0; i < (int)candidatesOut.size(); i++) {
_candidates.create(4, 1, CV_32FC2, i, true);
Mat m = _candidates.getMat(i);
for(int j = 0; j < 4; j++)
m.ptr< Vec2f >(0)[j] = candidatesOut[i][j];
_contours.create((int)contoursOut[i].size(), 1, CV_32SC2, i, true);
Mat c = _contours.getMat(i);
for(unsigned int j = 0; j < contoursOut[i].size(); j++)
c.ptr< Point2i >()[j] = contoursOut[i][j];
}
} }
...@@ -546,9 +529,9 @@ static bool _identifyOneCandidate(Ptr<Dictionary> &dictionary, InputArray _image ...@@ -546,9 +529,9 @@ static bool _identifyOneCandidate(Ptr<Dictionary> &dictionary, InputArray _image
*/ */
class IdentifyCandidatesParallel : public ParallelLoopBody { class IdentifyCandidatesParallel : public ParallelLoopBody {
public: public:
IdentifyCandidatesParallel(const Mat *_grey, InputArrayOfArrays _candidates, IdentifyCandidatesParallel(const Mat& _grey, InputArrayOfArrays _candidates,
InputArrayOfArrays _contours, Ptr<Dictionary> &_dictionary, InputArrayOfArrays _contours, Ptr<Dictionary> &_dictionary,
vector< int > *_idsTmp, vector< char > *_validCandidates, vector< int >& _idsTmp, vector< char >& _validCandidates,
const Ptr<DetectorParameters> &_params) const Ptr<DetectorParameters> &_params)
: grey(_grey), candidates(_candidates), contours(_contours), dictionary(_dictionary), : grey(_grey), candidates(_candidates), contours(_contours), dictionary(_dictionary),
idsTmp(_idsTmp), validCandidates(_validCandidates), params(_params) {} idsTmp(_idsTmp), validCandidates(_validCandidates), params(_params) {}
...@@ -560,9 +543,9 @@ class IdentifyCandidatesParallel : public ParallelLoopBody { ...@@ -560,9 +543,9 @@ class IdentifyCandidatesParallel : public ParallelLoopBody {
for(int i = begin; i < end; i++) { for(int i = begin; i < end; i++) {
int currId; int currId;
Mat currentCandidate = candidates.getMat(i); Mat currentCandidate = candidates.getMat(i);
if(_identifyOneCandidate(dictionary, *grey, currentCandidate, currId, params)) { if(_identifyOneCandidate(dictionary, grey, currentCandidate, currId, params)) {
(*validCandidates)[i] = 1; validCandidates[i] = 1;
(*idsTmp)[i] = currId; idsTmp[i] = currId;
} }
} }
} }
...@@ -570,50 +553,41 @@ class IdentifyCandidatesParallel : public ParallelLoopBody { ...@@ -570,50 +553,41 @@ class IdentifyCandidatesParallel : public ParallelLoopBody {
private: private:
IdentifyCandidatesParallel &operator=(const IdentifyCandidatesParallel &); // to quiet MSVC IdentifyCandidatesParallel &operator=(const IdentifyCandidatesParallel &); // to quiet MSVC
const Mat *grey; const Mat &grey;
InputArrayOfArrays candidates, contours; InputArrayOfArrays candidates, contours;
Ptr<Dictionary> &dictionary; Ptr<Dictionary> &dictionary;
vector< int > *idsTmp; vector< int > &idsTmp;
vector< char > *validCandidates; vector< char > &validCandidates;
const Ptr<DetectorParameters> &params; const Ptr<DetectorParameters> &params;
}; };
/** /**
* @brief Copy the contents of a Mat vector to an OutputArray, settings its size. * @brief Copy the contents of a corners vector to an OutputArray, settings its size.
*/
void _copyVector2Output(vector< Mat > &vec, OutputArrayOfArrays out);
/**
*
*/ */
void _copyVector2Output(vector< Mat > &vec, OutputArrayOfArrays out) { static void _copyVector2Output(vector< vector< Point2f > > &vec, OutputArrayOfArrays out) {
out.release();
out.create((int)vec.size(), 1, CV_32FC2); out.create((int)vec.size(), 1, CV_32FC2);
if(out.isMatVector()) { if(out.isMatVector()) {
for (unsigned int i = 0; i < vec.size(); i++) { for (unsigned int i = 0; i < vec.size(); i++) {
out.create(4, 1, CV_32FC2, i, true); out.create(4, 1, CV_32FC2, i);
Mat &m = out.getMatRef(i); Mat &m = out.getMatRef(i);
vec[i].copyTo(m); Mat(Mat(vec[i]).t()).copyTo(m);
} }
} }
else if(out.isUMatVector()) { else if(out.isUMatVector()) {
for (unsigned int i = 0; i < vec.size(); i++) { for (unsigned int i = 0; i < vec.size(); i++) {
out.create(4, 1, CV_32FC2, i, true); out.create(4, 1, CV_32FC2, i);
UMat &m = out.getUMatRef(i); UMat &m = out.getUMatRef(i);
vec[i].copyTo(m); Mat(Mat(vec[i]).t()).copyTo(m);
} }
} }
else if(out.kind() == _OutputArray::STD_VECTOR_VECTOR){ else if(out.kind() == _OutputArray::STD_VECTOR_VECTOR){
for (unsigned int i = 0; i < vec.size(); i++) { for (unsigned int i = 0; i < vec.size(); i++) {
out.create(4, 1, CV_32FC2, i, true); out.create(4, 1, CV_32FC2, i);
Mat m = out.getMat(i); Mat m = out.getMat(i);
vec[i].copyTo(m); Mat(Mat(vec[i]).t()).copyTo(m);
} }
} }
else { else {
...@@ -627,17 +601,16 @@ void _copyVector2Output(vector< Mat > &vec, OutputArrayOfArrays out) { ...@@ -627,17 +601,16 @@ void _copyVector2Output(vector< Mat > &vec, OutputArrayOfArrays out) {
/** /**
* @brief Identify square candidates according to a marker dictionary * @brief Identify square candidates according to a marker dictionary
*/ */
static void _identifyCandidates(InputArray _image, InputArrayOfArrays _candidates, static void _identifyCandidates(InputArray _image, vector< vector< Point2f > >& _candidates,
InputArrayOfArrays _contours, Ptr<Dictionary> &_dictionary, InputArrayOfArrays _contours, Ptr<Dictionary> &_dictionary,
OutputArrayOfArrays _accepted, OutputArray _ids, vector< vector< Point2f > >& _accepted, vector< int >& ids,
const Ptr<DetectorParameters> &params, const Ptr<DetectorParameters> &params,
OutputArrayOfArrays _rejected = noArray()) { OutputArrayOfArrays _rejected = noArray()) {
int ncandidates = (int)_candidates.total(); int ncandidates = (int)_candidates.size();
vector< Mat > accepted; vector< vector< Point2f > > accepted;
vector< Mat > rejected; vector< vector< Point2f > > rejected;
vector< int > ids;
CV_Assert(_image.getMat().total() != 0); CV_Assert(_image.getMat().total() != 0);
...@@ -659,24 +632,20 @@ static void _identifyCandidates(InputArray _image, InputArrayOfArrays _candidate ...@@ -659,24 +632,20 @@ static void _identifyCandidates(InputArray _image, InputArrayOfArrays _candidate
// this is the parallel call for the previous commented loop (result is equivalent) // this is the parallel call for the previous commented loop (result is equivalent)
parallel_for_(Range(0, ncandidates), parallel_for_(Range(0, ncandidates),
IdentifyCandidatesParallel(&grey, _candidates, _contours, _dictionary, &idsTmp, IdentifyCandidatesParallel(grey, _candidates, _contours, _dictionary, idsTmp,
&validCandidates, params)); validCandidates, params));
for(int i = 0; i < ncandidates; i++) { for(int i = 0; i < ncandidates; i++) {
if(validCandidates[i] == 1) { if(validCandidates[i] == 1) {
accepted.push_back(_candidates.getMat(i)); accepted.push_back(_candidates[i]);
ids.push_back(idsTmp[i]); ids.push_back(idsTmp[i]);
} else { } else {
rejected.push_back(_candidates.getMat(i)); rejected.push_back(_candidates[i]);
} }
} }
// parse output // parse output
_copyVector2Output(accepted, _accepted); _accepted = accepted;
_ids.create((int)ids.size(), 1, CV_32SC1);
for(unsigned int i = 0; i < ids.size(); i++)
_ids.getMat().ptr< int >(0)[i] = ids[i];
if(_rejected.needed()) { if(_rejected.needed()) {
_copyVector2Output(rejected, _rejected); _copyVector2Output(rejected, _rejected);
...@@ -687,26 +656,25 @@ static void _identifyCandidates(InputArray _image, InputArrayOfArrays _candidate ...@@ -687,26 +656,25 @@ static void _identifyCandidates(InputArray _image, InputArrayOfArrays _candidate
/** /**
* @brief Final filter of markers after its identification * @brief Final filter of markers after its identification
*/ */
static void _filterDetectedMarkers(InputArrayOfArrays _inCorners, InputArray _inIds, static void _filterDetectedMarkers(vector< vector< Point2f > >& _corners, vector< int >& _ids) {
OutputArrayOfArrays _outCorners, OutputArray _outIds) {
CV_Assert(_inCorners.total() == _inIds.total()); CV_Assert(_corners.size() == _ids.size());
if(_inCorners.total() == 0) return; if(_corners.empty()) return;
// mark markers that will be removed // mark markers that will be removed
vector< bool > toRemove(_inCorners.total(), false); vector< bool > toRemove(_corners.size(), false);
bool atLeastOneRemove = false; bool atLeastOneRemove = false;
// remove repeated markers with same id, if one contains the other (doble border bug) // remove repeated markers with same id, if one contains the other (doble border bug)
for(unsigned int i = 0; i < _inCorners.total() - 1; i++) { for(unsigned int i = 0; i < _corners.size() - 1; i++) {
for(unsigned int j = i + 1; j < _inCorners.total(); j++) { for(unsigned int j = i + 1; j < _corners.size(); j++) {
if(_inIds.getMat().ptr< int >(0)[i] != _inIds.getMat().ptr< int >(0)[j]) continue; if(_ids[i] != _ids[j]) continue;
// check if first marker is inside second // check if first marker is inside second
bool inside = true; bool inside = true;
for(unsigned int p = 0; p < 4; p++) { for(unsigned int p = 0; p < 4; p++) {
Point2f point = _inCorners.getMat(j).ptr< Point2f >(0)[p]; Point2f point = _corners[j][p];
if(pointPolygonTest(_inCorners.getMat(i), point, false) < 0) { if(pointPolygonTest(_corners[i], point, false) < 0) {
inside = false; inside = false;
break; break;
} }
...@@ -720,8 +688,8 @@ static void _filterDetectedMarkers(InputArrayOfArrays _inCorners, InputArray _in ...@@ -720,8 +688,8 @@ static void _filterDetectedMarkers(InputArrayOfArrays _inCorners, InputArray _in
// check the second marker // check the second marker
inside = true; inside = true;
for(unsigned int p = 0; p < 4; p++) { for(unsigned int p = 0; p < 4; p++) {
Point2f point = _inCorners.getMat(i).ptr< Point2f >(0)[p]; Point2f point = _corners[i][p];
if(pointPolygonTest(_inCorners.getMat(j), point, false) < 0) { if(pointPolygonTest(_corners[j], point, false) < 0) {
inside = false; inside = false;
break; break;
} }
...@@ -736,25 +704,18 @@ static void _filterDetectedMarkers(InputArrayOfArrays _inCorners, InputArray _in ...@@ -736,25 +704,18 @@ static void _filterDetectedMarkers(InputArrayOfArrays _inCorners, InputArray _in
// parse output // parse output
if(atLeastOneRemove) { if(atLeastOneRemove) {
vector< Mat > filteredCorners; vector< vector< Point2f > >::iterator filteredCorners = _corners.begin();
vector< int > filteredIds; vector< int >::iterator filteredIds = _ids.begin();
for(unsigned int i = 0; i < toRemove.size(); i++) { for(unsigned int i = 0; i < toRemove.size(); i++) {
if(!toRemove[i]) { if(!toRemove[i]) {
filteredCorners.push_back(_inCorners.getMat(i).clone()); *filteredCorners++ = _corners[i];
filteredIds.push_back(_inIds.getMat().ptr< int >(0)[i]); *filteredIds++ = _ids[i];
} }
} }
_outIds.create((int)filteredIds.size(), 1, CV_32SC1); _ids.erase(filteredIds, _ids.end());
for(unsigned int i = 0; i < filteredIds.size(); i++) _corners.erase(filteredCorners, _corners.end());
_outIds.getMat().ptr< int >(0)[i] = filteredIds[i];
_outCorners.create((int)filteredCorners.size(), 1, CV_32FC2);
for(unsigned int i = 0; i < filteredCorners.size(); i++) {
_outCorners.create(4, 1, CV_32FC2, i, true);
filteredCorners[i].copyTo(_outCorners.getMat(i));
}
} }
} }
...@@ -818,7 +779,7 @@ void detectMarkers(InputArray _image, Ptr<Dictionary> &_dictionary, OutputArrayO ...@@ -818,7 +779,7 @@ void detectMarkers(InputArray _image, Ptr<Dictionary> &_dictionary, OutputArrayO
OutputArray _ids, const Ptr<DetectorParameters> &_params, OutputArray _ids, const Ptr<DetectorParameters> &_params,
OutputArrayOfArrays _rejectedImgPoints) { OutputArrayOfArrays _rejectedImgPoints) {
CV_Assert(_image.getMat().total() != 0); CV_Assert(!_image.empty());
Mat grey; Mat grey;
_convertToGrey(_image.getMat(), grey); _convertToGrey(_image.getMat(), grey);
...@@ -826,14 +787,19 @@ void detectMarkers(InputArray _image, Ptr<Dictionary> &_dictionary, OutputArrayO ...@@ -826,14 +787,19 @@ void detectMarkers(InputArray _image, Ptr<Dictionary> &_dictionary, OutputArrayO
/// STEP 1: Detect marker candidates /// STEP 1: Detect marker candidates
vector< vector< Point2f > > candidates; vector< vector< Point2f > > candidates;
vector< vector< Point > > contours; vector< vector< Point > > contours;
vector< int > ids;
_detectCandidates(grey, candidates, contours, _params); _detectCandidates(grey, candidates, contours, _params);
/// STEP 2: Check candidate codification (identify markers) /// STEP 2: Check candidate codification (identify markers)
_identifyCandidates(grey, candidates, contours, _dictionary, _corners, _ids, _params, _identifyCandidates(grey, candidates, contours, _dictionary, candidates, ids, _params,
_rejectedImgPoints); _rejectedImgPoints);
/// STEP 3: Filter detected markers; /// STEP 3: Filter detected markers;
_filterDetectedMarkers(_corners, _ids, _corners, _ids); _filterDetectedMarkers(candidates, ids);
// copy to output arrays
_copyVector2Output(candidates, _corners);
Mat(ids).copyTo(_ids);
/// STEP 4: Corner refinement /// STEP 4: Corner refinement
if(_params->doCornerRefinement) { if(_params->doCornerRefinement) {
...@@ -841,7 +807,7 @@ void detectMarkers(InputArray _image, Ptr<Dictionary> &_dictionary, OutputArrayO ...@@ -841,7 +807,7 @@ void detectMarkers(InputArray _image, Ptr<Dictionary> &_dictionary, OutputArrayO
_params->cornerRefinementMinAccuracy > 0); _params->cornerRefinementMinAccuracy > 0);
//// do corner refinement for each of the detected markers //// do corner refinement for each of the detected markers
// for (unsigned int i = 0; i < _corners.total(); i++) { // for (unsigned int i = 0; i < _corners.cols(); i++) {
// cornerSubPix(grey, _corners.getMat(i), // cornerSubPix(grey, _corners.getMat(i),
// Size(params.cornerRefinementWinSize, params.cornerRefinementWinSize), // Size(params.cornerRefinementWinSize, params.cornerRefinementWinSize),
// Size(-1, -1), TermCriteria(TermCriteria::MAX_ITER | TermCriteria::EPS, // Size(-1, -1), TermCriteria(TermCriteria::MAX_ITER | TermCriteria::EPS,
...@@ -850,7 +816,7 @@ void detectMarkers(InputArray _image, Ptr<Dictionary> &_dictionary, OutputArrayO ...@@ -850,7 +816,7 @@ void detectMarkers(InputArray _image, Ptr<Dictionary> &_dictionary, OutputArrayO
//} //}
// this is the parallel call for the previous commented loop (result is equivalent) // this is the parallel call for the previous commented loop (result is equivalent)
parallel_for_(Range(0, (int)_corners.total()), parallel_for_(Range(0, _corners.cols()),
MarkerSubpixelParallel(&grey, _corners, _params)); MarkerSubpixelParallel(&grey, _corners, _params));
} }
} }
......
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