Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix CORNER REFINE CONTOUR #3186

Merged
merged 1 commit into from
Mar 16, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 4 additions & 6 deletions modules/aruco/include/opencv2/aruco.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -206,21 +206,19 @@ struct CV_EXPORTS_W DetectorParameters {
* @param parameters marker detection parameters
* @param rejectedImgPoints contains the imgPoints of those squares whose inner code has not a
* correct codification. Useful for debugging purposes.
* @param cameraMatrix optional input 3x3 floating-point camera matrix
* \f$A = \vecthreethree{f_x}{0}{c_x}{0}{f_y}{c_y}{0}{0}{1}\f$
* @param distCoeff optional vector of distortion coefficients
* \f$(k_1, k_2, p_1, p_2[, k_3[, k_4, k_5, k_6],[s_1, s_2, s_3, s_4]])\f$ of 4, 5, 8 or 12 elements
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I propose to add reference to undistortPoints and fisheye::undistortPoints to @sa. And also add note like "The function does not correct lens distortion or takes it into account. It's recommended to undistort input image with corresponging camera model, if camera parameters are known."

*
* Performs marker detection in the input image. Only markers included in the specific dictionary
* are searched. For each detected marker, it returns the 2D position of its corner in the image
* and its corresponding identifier.
* Note that this function does not perform pose estimation.
* @sa estimatePoseSingleMarkers, estimatePoseBoard
* @note The function does not correct lens distortion or takes it into account. It's recommended to undistort
* input image with corresponging camera model, if camera parameters are known
* @sa undistort, estimatePoseSingleMarkers, estimatePoseBoard
*
*/
CV_EXPORTS_W void detectMarkers(InputArray image, const Ptr<Dictionary> &dictionary, OutputArrayOfArrays corners,
OutputArray ids, const Ptr<DetectorParameters> &parameters = DetectorParameters::create(),
OutputArrayOfArrays rejectedImgPoints = noArray(), InputArray cameraMatrix= noArray(), InputArray distCoeff= noArray());
OutputArrayOfArrays rejectedImgPoints = noArray());



Expand Down
43 changes: 9 additions & 34 deletions modules/aruco/src/aruco.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -857,6 +857,7 @@ class MarkerSubpixelParallel : public ParallelLoopBody {
* @param nContours, contour-container
*/
static Point3f _interpolate2Dline(const std::vector<cv::Point2f>& nContours){
CV_Assert(nContours.size() >= 2);
float minX, minY, maxX, maxY;
minX = maxX = nContours[0].x;
minY = maxY = nContours[0].y;
Expand Down Expand Up @@ -907,35 +908,15 @@ static Point2f _getCrossPoint(Point3f nLine1, Point3f nLine2){
return Vec2f(A.solve(B).val);
}

static void _distortPoints(vector<cv::Point2f>& in, const Mat& camMatrix, const Mat& distCoeff) {
// trivial extrinsics
Matx31f Rvec(0,0,0);
Matx31f Tvec(0,0,0);

// calculate 3d points and then reproject, so opencv makes the distortion internally
vector<cv::Point3f> cornersPoints3d;
for (unsigned int i = 0; i < in.size(); i++){
float x= (in[i].x - float(camMatrix.at<double>(0, 2))) / float(camMatrix.at<double>(0, 0));
float y= (in[i].y - float(camMatrix.at<double>(1, 2))) / float(camMatrix.at<double>(1, 1));
cornersPoints3d.push_back(Point3f(x,y,1));
}
cv::projectPoints(cornersPoints3d, Rvec, Tvec, camMatrix, distCoeff, in);
}

/**
* Refine Corners using the contour vector :: Called from function detectMarkers
* @param nContours, contour-container
* @param nCorners, candidate Corners
* @param camMatrix, cameraMatrix input 3x3 floating-point camera matrix
* @param distCoeff, distCoeffs vector of distortion coefficient
*/
static void _refineCandidateLines(std::vector<Point>& nContours, std::vector<Point2f>& nCorners, const Mat& camMatrix, const Mat& distCoeff){
static void _refineCandidateLines(std::vector<Point>& nContours, std::vector<Point2f>& nCorners){
vector<Point2f> contour2f(nContours.begin(), nContours.end());

if(!camMatrix.empty() && !distCoeff.empty()){
undistortPoints(contour2f, contour2f, camMatrix, distCoeff);
}

/* 5 groups :: to group the edges
* 4 - classified by its corner
* extra group - (temporary) if contours do not begin with a corner
Expand All @@ -953,10 +934,10 @@ static void _refineCandidateLines(std::vector<Point>& nContours, std::vector<Poi
}
cntPts[group].push_back(contour2f[i]);
}

for (int i = 0; i < 4; i++)
CV_Assert(cornerIndex[i] != -1);
Comment on lines +937 to +938
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added check that each of the four corners is found.

// saves extra group into corresponding
if( !cntPts[4].empty() ){
CV_CheckLT(group, 4, "FIXIT: avoiding infinite loop: implementation should be revised: https://github.com/opencv/opencv_contrib/issues/2738");
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If each (or at least one) of the 4 corners is found, then group will not be equal to 4.

for( unsigned int i=0; i < cntPts[4].size() ; i++ )
cntPts[group].push_back(cntPts[4].at(i));
cntPts[4].clear();
Expand Down Expand Up @@ -989,10 +970,6 @@ static void _refineCandidateLines(std::vector<Point>& nContours, std::vector<Poi
else
nCorners[i] = _getCrossPoint(lines[ i ], lines[ (i+3)%4 ]); // 30 01 12 23
}

if(!camMatrix.empty() && !distCoeff.empty()){
_distortPoints(nCorners, camMatrix, distCoeff);
}
}


Expand All @@ -1002,13 +979,13 @@ static void _refineCandidateLines(std::vector<Point>& nContours, std::vector<Poi
*/
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){}
MarkerContourParallel( vector< vector< Point > >& _contours, vector< vector< Point2f > >& _candidates)
: contours(_contours), candidates(_candidates){}

void operator()(const Range &range) const CV_OVERRIDE {

for(int i = range.start; i < range.end; i++) {
_refineCandidateLines(contours[i], candidates[i], camMatrix, distCoeff);
_refineCandidateLines(contours[i], candidates[i]);
}
}

Expand All @@ -1019,8 +996,6 @@ class MarkerContourParallel : public ParallelLoopBody {

vector< vector< Point > >& contours;
vector< vector< Point2f > >& candidates;
const Mat& camMatrix;
const Mat& distCoeff;
};

#ifdef APRIL_DEBUG
Expand Down Expand Up @@ -1162,7 +1137,7 @@ static void _apriltag(Mat im_orig, const Ptr<DetectorParameters> & _params, std:
*/
void detectMarkers(InputArray _image, const Ptr<Dictionary> &_dictionary, OutputArrayOfArrays _corners,
OutputArray _ids, const Ptr<DetectorParameters> &_params,
OutputArrayOfArrays _rejectedImgPoints, InputArrayOfArrays camMatrix, InputArrayOfArrays distCoeff) {
OutputArrayOfArrays _rejectedImgPoints) {

CV_Assert(!_image.empty());

Expand Down Expand Up @@ -1221,7 +1196,7 @@ 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()), MarkerContourParallel(contours, candidates));

// copy the corners to the output array
_copyVector2Output(candidates, _corners);
Expand Down