|
|
@ -2178,13 +2178,6 @@ void drawChessboardCorners( InputOutputArray image, Size patternSize, |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static int quiet_error(int /*status*/, const char* /*func_name*/, |
|
|
|
|
|
|
|
const char* /*err_msg*/, const char* /*file_name*/, |
|
|
|
|
|
|
|
int /*line*/, void* /*userdata*/) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
return 0; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool findCirclesGrid(InputArray image, Size patternSize, |
|
|
|
bool findCirclesGrid(InputArray image, Size patternSize, |
|
|
|
OutputArray centers, int flags, |
|
|
|
OutputArray centers, int flags, |
|
|
|
const Ptr<FeatureDetector> &blobDetector, |
|
|
|
const Ptr<FeatureDetector> &blobDetector, |
|
|
@ -2205,15 +2198,22 @@ bool findCirclesGrid2(InputArray _image, Size patternSize, |
|
|
|
bool isSymmetricGrid = (flags & CALIB_CB_SYMMETRIC_GRID ) ? true : false; |
|
|
|
bool isSymmetricGrid = (flags & CALIB_CB_SYMMETRIC_GRID ) ? true : false; |
|
|
|
CV_Assert(isAsymmetricGrid ^ isSymmetricGrid); |
|
|
|
CV_Assert(isAsymmetricGrid ^ isSymmetricGrid); |
|
|
|
|
|
|
|
|
|
|
|
Mat image = _image.getMat(); |
|
|
|
|
|
|
|
std::vector<Point2f> centers; |
|
|
|
std::vector<Point2f> centers; |
|
|
|
|
|
|
|
|
|
|
|
std::vector<KeyPoint> keypoints; |
|
|
|
|
|
|
|
blobDetector->detect(image, keypoints); |
|
|
|
|
|
|
|
std::vector<Point2f> points; |
|
|
|
std::vector<Point2f> points; |
|
|
|
for (size_t i = 0; i < keypoints.size(); i++) |
|
|
|
if (blobDetector) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
std::vector<KeyPoint> keypoints; |
|
|
|
|
|
|
|
blobDetector->detect(_image, keypoints); |
|
|
|
|
|
|
|
for (size_t i = 0; i < keypoints.size(); i++) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
points.push_back(keypoints[i].pt); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
else |
|
|
|
{ |
|
|
|
{ |
|
|
|
points.push_back (keypoints[i].pt); |
|
|
|
CV_CheckTypeEQ(_image.type(), CV_32FC2, "blobDetector must be provided or image must contains Point2f array (std::vector<Point2f>) with candidates"); |
|
|
|
|
|
|
|
_image.copyTo(points); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if(flags & CALIB_CB_ASYMMETRIC_GRID) |
|
|
|
if(flags & CALIB_CB_ASYMMETRIC_GRID) |
|
|
@ -2229,64 +2229,59 @@ bool findCirclesGrid2(InputArray _image, Size patternSize, |
|
|
|
return !centers.empty(); |
|
|
|
return !centers.empty(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool isValid = false; |
|
|
|
const int attempts = 2; |
|
|
|
const int attempts = 2; |
|
|
|
const size_t minHomographyPoints = 4; |
|
|
|
const size_t minHomographyPoints = 4; |
|
|
|
Mat H; |
|
|
|
Mat H; |
|
|
|
for (int i = 0; i < attempts; i++) |
|
|
|
for (int i = 0; i < attempts; i++) |
|
|
|
{ |
|
|
|
{ |
|
|
|
centers.clear(); |
|
|
|
centers.clear(); |
|
|
|
CirclesGridFinder boxFinder(patternSize, points, parameters); |
|
|
|
CirclesGridFinder boxFinder(patternSize, points, parameters); |
|
|
|
bool isFound = false; |
|
|
|
try |
|
|
|
#define BE_QUIET 1 |
|
|
|
|
|
|
|
#if BE_QUIET |
|
|
|
|
|
|
|
void* oldCbkData; |
|
|
|
|
|
|
|
ErrorCallback oldCbk = redirectError(quiet_error, 0, &oldCbkData); // FIXIT not thread safe
|
|
|
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
try |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
isFound = boxFinder.findHoles(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
catch (const cv::Exception &) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
#if BE_QUIET |
|
|
|
|
|
|
|
redirectError(oldCbk, oldCbkData); |
|
|
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
if (isFound) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
switch(parameters.gridType) |
|
|
|
|
|
|
|
{ |
|
|
|
{ |
|
|
|
case CirclesGridFinderParameters::SYMMETRIC_GRID: |
|
|
|
bool isFound = boxFinder.findHoles(); |
|
|
|
boxFinder.getHoles(centers); |
|
|
|
if (isFound) |
|
|
|
break; |
|
|
|
{ |
|
|
|
case CirclesGridFinderParameters::ASYMMETRIC_GRID: |
|
|
|
switch(parameters.gridType) |
|
|
|
boxFinder.getAsymmetricHoles(centers); |
|
|
|
{ |
|
|
|
break; |
|
|
|
case CirclesGridFinderParameters::SYMMETRIC_GRID: |
|
|
|
default: |
|
|
|
boxFinder.getHoles(centers); |
|
|
|
CV_Error(Error::StsBadArg, "Unknown pattern type"); |
|
|
|
break; |
|
|
|
|
|
|
|
case CirclesGridFinderParameters::ASYMMETRIC_GRID: |
|
|
|
|
|
|
|
boxFinder.getAsymmetricHoles(centers); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
default: |
|
|
|
|
|
|
|
CV_Error(Error::StsBadArg, "Unknown pattern type"); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
isValid = true; |
|
|
|
|
|
|
|
break; // done, return result
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
catch (const cv::Exception& e) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
CV_UNUSED(e); |
|
|
|
|
|
|
|
CV_LOG_DEBUG(NULL, "findCirclesGrid2: attempt=" << i << ": " << e.what()); |
|
|
|
|
|
|
|
// nothing, next attempt
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (i != 0) |
|
|
|
boxFinder.getHoles(centers); |
|
|
|
|
|
|
|
if (i != attempts - 1) |
|
|
|
{ |
|
|
|
{ |
|
|
|
Mat orgPointsMat; |
|
|
|
if (centers.size() < minHomographyPoints) |
|
|
|
transform(centers, orgPointsMat, H.inv()); |
|
|
|
break; |
|
|
|
convertPointsFromHomogeneous(orgPointsMat, centers); |
|
|
|
H = CirclesGridFinder::rectifyGrid(boxFinder.getDetectedGridSize(), centers, points, points); |
|
|
|
} |
|
|
|
} |
|
|
|
Mat(centers).copyTo(_centers); |
|
|
|
} |
|
|
|
return true; |
|
|
|
|
|
|
|
} |
|
|
|
if (!H.empty()) // undone rectification
|
|
|
|
|
|
|
|
{ |
|
|
|
boxFinder.getHoles(centers); |
|
|
|
Mat orgPointsMat; |
|
|
|
if (i != attempts - 1) |
|
|
|
transform(centers, orgPointsMat, H.inv()); |
|
|
|
{ |
|
|
|
convertPointsFromHomogeneous(orgPointsMat, centers); |
|
|
|
if (centers.size() < minHomographyPoints) |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
H = CirclesGridFinder::rectifyGrid(boxFinder.getDetectedGridSize(), centers, points, points); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
Mat(centers).copyTo(_centers); |
|
|
|
Mat(centers).copyTo(_centers); |
|
|
|
return false; |
|
|
|
return isValid; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
bool findCirclesGrid(InputArray _image, Size patternSize, |
|
|
|
bool findCirclesGrid(InputArray _image, Size patternSize, |
|
|
|