Skip to content
5 changes: 5 additions & 0 deletions modules/aruco/include/opencv2/aruco.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,8 @@ enum CornerRefineMethod{
* done at full resolution.
* - aprilTagQuadSigma: What Gaussian blur should be applied to the segmented image (used for quad detection?)
* Parameter is the standard deviation in pixels. Very noisy images benefit from non-zero values (e.g. 0.8).
* - detectInvertedMarker: to check if there is a white marker. In order to generate a "white" marker just
* invert a normal marker by using a tilde, ~markerImage. (default false)
*/
struct CV_EXPORTS_W DetectorParameters {

Expand Down Expand Up @@ -183,6 +185,9 @@ struct CV_EXPORTS_W DetectorParameters {
CV_PROP_RW float aprilTagMaxLineFitMse;
CV_PROP_RW int aprilTagMinWhiteBlackDiff;
CV_PROP_RW int aprilTagDeglitch;

// to detect white markers
CV_PROP_RW bool detectInvertedMarker;
};


Expand Down
16 changes: 14 additions & 2 deletions modules/aruco/src/aruco.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,8 @@ DetectorParameters::DetectorParameters()
aprilTagCriticalRad( (float)(10* CV_PI /180) ),
aprilTagMaxLineFitMse(10.0),
aprilTagMinWhiteBlackDiff(5),
aprilTagDeglitch(0){}
aprilTagDeglitch(0),
detectInvertedMarker(false){}


/**
Expand Down Expand Up @@ -512,7 +513,18 @@ static bool _identifyOneCandidate(const Ptr<Dictionary>& dictionary, InputArray
int(dictionary->markerSize * dictionary->markerSize * params->maxErroneousBitsInBorderRate);
int borderErrors =
_getBorderErrors(candidateBits, dictionary->markerSize, params->markerBorderBits);
if(borderErrors > maximumErrorsInBorder) return false; // border is wrong

// check if it is a white marker
if(params->detectInvertedMarker){
// to get from 255 to 1
int invBError = _getBorderErrors(~candidateBits-254, dictionary->markerSize, params->markerBorderBits);
// white marker
if(invBError<borderErrors){
borderErrors = invBError;
candidateBits=~candidateBits-254;
}
}
if(borderErrors > maximumErrorsInBorder) return false;

// take only inner bits
Mat onlyBits =
Expand Down