mirror of
https://github.com/opencv/opencv.git
synced 2025-06-20 01:41:14 +08:00
Undo multi dict functionality of refineDetectedMarkers method
This commit is contained in:
parent
1f9d6aa6cf
commit
364eedb87e
@ -1240,6 +1240,7 @@ void ArucoDetector::refineDetectedMarkers(InputArray _image, const Board& _board
|
|||||||
InputOutputArrayOfArrays _rejectedCorners, InputArray _cameraMatrix,
|
InputOutputArrayOfArrays _rejectedCorners, InputArray _cameraMatrix,
|
||||||
InputArray _distCoeffs, OutputArray _recoveredIdxs) const {
|
InputArray _distCoeffs, OutputArray _recoveredIdxs) const {
|
||||||
DetectorParameters& detectorParams = arucoDetectorImpl->detectorParams;
|
DetectorParameters& detectorParams = arucoDetectorImpl->detectorParams;
|
||||||
|
const Dictionary& dictionary = arucoDetectorImpl->dictionaries.at(0);
|
||||||
RefineParameters& refineParams = arucoDetectorImpl->refineParams;
|
RefineParameters& refineParams = arucoDetectorImpl->refineParams;
|
||||||
CV_Assert(refineParams.minRepDistance > 0);
|
CV_Assert(refineParams.minRepDistance > 0);
|
||||||
|
|
||||||
@ -1262,6 +1263,10 @@ void ArucoDetector::refineDetectedMarkers(InputArray _image, const Board& _board
|
|||||||
// list of missing markers indicating if they have been assigned to a candidate
|
// list of missing markers indicating if they have been assigned to a candidate
|
||||||
vector<bool > alreadyIdentified(_rejectedCorners.total(), false);
|
vector<bool > alreadyIdentified(_rejectedCorners.total(), false);
|
||||||
|
|
||||||
|
// maximum bits that can be corrected
|
||||||
|
int maxCorrectionRecalculated =
|
||||||
|
int(double(dictionary.maxCorrectionBits) * refineParams.errorCorrectionRate);
|
||||||
|
|
||||||
Mat grey;
|
Mat grey;
|
||||||
_convertToGrey(_image, grey);
|
_convertToGrey(_image, grey);
|
||||||
|
|
||||||
@ -1277,112 +1282,106 @@ void ArucoDetector::refineDetectedMarkers(InputArray _image, const Board& _board
|
|||||||
}
|
}
|
||||||
vector<int> recoveredIdxs; // original indexes of accepted markers in _rejectedCorners
|
vector<int> recoveredIdxs; // original indexes of accepted markers in _rejectedCorners
|
||||||
|
|
||||||
for (const auto& dictionary : arucoDetectorImpl->dictionaries) {
|
// for each missing marker, try to find a correspondence
|
||||||
// maximum bits that can be corrected
|
for(unsigned int i = 0; i < undetectedMarkersIds.size(); i++) {
|
||||||
int maxCorrectionRecalculated =
|
|
||||||
int(double(dictionary.maxCorrectionBits) * refineParams.errorCorrectionRate);
|
|
||||||
|
|
||||||
// for each missing marker, try to find a correspondence
|
// best match at the moment
|
||||||
for(unsigned int i = 0; i < undetectedMarkersIds.size(); i++) {
|
int closestCandidateIdx = -1;
|
||||||
|
double closestCandidateDistance = refineParams.minRepDistance * refineParams.minRepDistance + 1;
|
||||||
|
Mat closestRotatedMarker;
|
||||||
|
|
||||||
// best match at the moment
|
for(unsigned int j = 0; j < _rejectedCorners.total(); j++) {
|
||||||
int closestCandidateIdx = -1;
|
if(alreadyIdentified[j]) continue;
|
||||||
double closestCandidateDistance = refineParams.minRepDistance * refineParams.minRepDistance + 1;
|
|
||||||
Mat closestRotatedMarker;
|
|
||||||
|
|
||||||
for(unsigned int j = 0; j < _rejectedCorners.total(); j++) {
|
// check distance
|
||||||
if(alreadyIdentified[j]) continue;
|
double minDistance = closestCandidateDistance + 1;
|
||||||
|
bool valid = false;
|
||||||
// check distance
|
int validRot = 0;
|
||||||
double minDistance = closestCandidateDistance + 1;
|
for(int c = 0; c < 4; c++) { // first corner in rejected candidate
|
||||||
bool valid = false;
|
double currentMaxDistance = 0;
|
||||||
int validRot = 0;
|
for(int k = 0; k < 4; k++) {
|
||||||
for(int c = 0; c < 4; c++) { // first corner in rejected candidate
|
Point2f rejCorner = _rejectedCorners.getMat(j).ptr<Point2f>()[(c + k) % 4];
|
||||||
double currentMaxDistance = 0;
|
Point2f distVector = undetectedMarkersCorners[i][k] - rejCorner;
|
||||||
for(int k = 0; k < 4; k++) {
|
double cornerDist = distVector.x * distVector.x + distVector.y * distVector.y;
|
||||||
Point2f rejCorner = _rejectedCorners.getMat(j).ptr<Point2f>()[(c + k) % 4];
|
currentMaxDistance = max(currentMaxDistance, cornerDist);
|
||||||
Point2f distVector = undetectedMarkersCorners[i][k] - rejCorner;
|
|
||||||
double cornerDist = distVector.x * distVector.x + distVector.y * distVector.y;
|
|
||||||
currentMaxDistance = max(currentMaxDistance, cornerDist);
|
|
||||||
}
|
|
||||||
// if distance is better than current best distance
|
|
||||||
if(currentMaxDistance < closestCandidateDistance) {
|
|
||||||
valid = true;
|
|
||||||
validRot = c;
|
|
||||||
minDistance = currentMaxDistance;
|
|
||||||
}
|
|
||||||
if(!refineParams.checkAllOrders) break;
|
|
||||||
}
|
}
|
||||||
|
// if distance is better than current best distance
|
||||||
if(!valid) continue;
|
if(currentMaxDistance < closestCandidateDistance) {
|
||||||
|
valid = true;
|
||||||
// apply rotation
|
validRot = c;
|
||||||
Mat rotatedMarker;
|
minDistance = currentMaxDistance;
|
||||||
if(refineParams.checkAllOrders) {
|
|
||||||
rotatedMarker = Mat(4, 1, CV_32FC2);
|
|
||||||
for(int c = 0; c < 4; c++)
|
|
||||||
rotatedMarker.ptr<Point2f>()[c] =
|
|
||||||
_rejectedCorners.getMat(j).ptr<Point2f>()[(c + 4 + validRot) % 4];
|
|
||||||
}
|
|
||||||
else rotatedMarker = _rejectedCorners.getMat(j);
|
|
||||||
|
|
||||||
// last filter, check if inner code is close enough to the assigned marker code
|
|
||||||
int codeDistance = 0;
|
|
||||||
// if errorCorrectionRate, dont check code
|
|
||||||
if(refineParams.errorCorrectionRate >= 0) {
|
|
||||||
|
|
||||||
// extract bits
|
|
||||||
Mat bits = _extractBits(
|
|
||||||
grey, rotatedMarker, dictionary.markerSize, detectorParams.markerBorderBits,
|
|
||||||
detectorParams.perspectiveRemovePixelPerCell,
|
|
||||||
detectorParams.perspectiveRemoveIgnoredMarginPerCell, detectorParams.minOtsuStdDev);
|
|
||||||
|
|
||||||
Mat onlyBits =
|
|
||||||
bits.rowRange(detectorParams.markerBorderBits, bits.rows - detectorParams.markerBorderBits)
|
|
||||||
.colRange(detectorParams.markerBorderBits, bits.rows - detectorParams.markerBorderBits);
|
|
||||||
|
|
||||||
codeDistance =
|
|
||||||
dictionary.getDistanceToId(onlyBits, undetectedMarkersIds[i], false);
|
|
||||||
}
|
|
||||||
|
|
||||||
// if everythin is ok, assign values to current best match
|
|
||||||
if(refineParams.errorCorrectionRate < 0 || codeDistance < maxCorrectionRecalculated) {
|
|
||||||
closestCandidateIdx = j;
|
|
||||||
closestCandidateDistance = minDistance;
|
|
||||||
closestRotatedMarker = rotatedMarker;
|
|
||||||
}
|
}
|
||||||
|
if(!refineParams.checkAllOrders) break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// if at least one good match, we have rescue the missing marker
|
if(!valid) continue;
|
||||||
if(closestCandidateIdx >= 0) {
|
|
||||||
|
|
||||||
// subpixel refinement
|
// apply rotation
|
||||||
if(detectorParams.cornerRefinementMethod == (int)CORNER_REFINE_SUBPIX) {
|
Mat rotatedMarker;
|
||||||
CV_Assert(detectorParams.cornerRefinementWinSize > 0 &&
|
if(refineParams.checkAllOrders) {
|
||||||
detectorParams.cornerRefinementMaxIterations > 0 &&
|
rotatedMarker = Mat(4, 1, CV_32FC2);
|
||||||
detectorParams.cornerRefinementMinAccuracy > 0);
|
for(int c = 0; c < 4; c++)
|
||||||
|
rotatedMarker.ptr<Point2f>()[c] =
|
||||||
std::vector<Point2f> marker(closestRotatedMarker.begin<Point2f>(), closestRotatedMarker.end<Point2f>());
|
_rejectedCorners.getMat(j).ptr<Point2f>()[(c + 4 + validRot) % 4];
|
||||||
int cornerRefinementWinSize = std::max(1, cvRound(detectorParams.relativeCornerRefinmentWinSize*
|
|
||||||
getAverageModuleSize(marker, dictionary.markerSize, detectorParams.markerBorderBits)));
|
|
||||||
cornerRefinementWinSize = min(cornerRefinementWinSize, detectorParams.cornerRefinementWinSize);
|
|
||||||
cornerSubPix(grey, closestRotatedMarker,
|
|
||||||
Size(cornerRefinementWinSize, cornerRefinementWinSize),
|
|
||||||
Size(-1, -1), TermCriteria(TermCriteria::MAX_ITER | TermCriteria::EPS,
|
|
||||||
detectorParams.cornerRefinementMaxIterations,
|
|
||||||
detectorParams.cornerRefinementMinAccuracy));
|
|
||||||
}
|
|
||||||
|
|
||||||
// remove from rejected
|
|
||||||
alreadyIdentified[closestCandidateIdx] = true;
|
|
||||||
|
|
||||||
// add to detected
|
|
||||||
finalAcceptedCorners.push_back(closestRotatedMarker);
|
|
||||||
finalAcceptedIds.push_back(undetectedMarkersIds[i]);
|
|
||||||
|
|
||||||
// add the original index of the candidate
|
|
||||||
recoveredIdxs.push_back(closestCandidateIdx);
|
|
||||||
}
|
}
|
||||||
|
else rotatedMarker = _rejectedCorners.getMat(j);
|
||||||
|
|
||||||
|
// last filter, check if inner code is close enough to the assigned marker code
|
||||||
|
int codeDistance = 0;
|
||||||
|
// if errorCorrectionRate, dont check code
|
||||||
|
if(refineParams.errorCorrectionRate >= 0) {
|
||||||
|
|
||||||
|
// extract bits
|
||||||
|
Mat bits = _extractBits(
|
||||||
|
grey, rotatedMarker, dictionary.markerSize, detectorParams.markerBorderBits,
|
||||||
|
detectorParams.perspectiveRemovePixelPerCell,
|
||||||
|
detectorParams.perspectiveRemoveIgnoredMarginPerCell, detectorParams.minOtsuStdDev);
|
||||||
|
|
||||||
|
Mat onlyBits =
|
||||||
|
bits.rowRange(detectorParams.markerBorderBits, bits.rows - detectorParams.markerBorderBits)
|
||||||
|
.colRange(detectorParams.markerBorderBits, bits.rows - detectorParams.markerBorderBits);
|
||||||
|
|
||||||
|
codeDistance =
|
||||||
|
dictionary.getDistanceToId(onlyBits, undetectedMarkersIds[i], false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// if everythin is ok, assign values to current best match
|
||||||
|
if(refineParams.errorCorrectionRate < 0 || codeDistance < maxCorrectionRecalculated) {
|
||||||
|
closestCandidateIdx = j;
|
||||||
|
closestCandidateDistance = minDistance;
|
||||||
|
closestRotatedMarker = rotatedMarker;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// if at least one good match, we have rescue the missing marker
|
||||||
|
if(closestCandidateIdx >= 0) {
|
||||||
|
|
||||||
|
// subpixel refinement
|
||||||
|
if(detectorParams.cornerRefinementMethod == (int)CORNER_REFINE_SUBPIX) {
|
||||||
|
CV_Assert(detectorParams.cornerRefinementWinSize > 0 &&
|
||||||
|
detectorParams.cornerRefinementMaxIterations > 0 &&
|
||||||
|
detectorParams.cornerRefinementMinAccuracy > 0);
|
||||||
|
|
||||||
|
std::vector<Point2f> marker(closestRotatedMarker.begin<Point2f>(), closestRotatedMarker.end<Point2f>());
|
||||||
|
int cornerRefinementWinSize = std::max(1, cvRound(detectorParams.relativeCornerRefinmentWinSize*
|
||||||
|
getAverageModuleSize(marker, dictionary.markerSize, detectorParams.markerBorderBits)));
|
||||||
|
cornerRefinementWinSize = min(cornerRefinementWinSize, detectorParams.cornerRefinementWinSize);
|
||||||
|
cornerSubPix(grey, closestRotatedMarker,
|
||||||
|
Size(cornerRefinementWinSize, cornerRefinementWinSize),
|
||||||
|
Size(-1, -1), TermCriteria(TermCriteria::MAX_ITER | TermCriteria::EPS,
|
||||||
|
detectorParams.cornerRefinementMaxIterations,
|
||||||
|
detectorParams.cornerRefinementMinAccuracy));
|
||||||
|
}
|
||||||
|
|
||||||
|
// remove from rejected
|
||||||
|
alreadyIdentified[closestCandidateIdx] = true;
|
||||||
|
|
||||||
|
// add to detected
|
||||||
|
finalAcceptedCorners.push_back(closestRotatedMarker);
|
||||||
|
finalAcceptedIds.push_back(undetectedMarkersIds[i]);
|
||||||
|
|
||||||
|
// add the original index of the candidate
|
||||||
|
recoveredIdxs.push_back(closestCandidateIdx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user