mirror of
https://github.com/opencv/opencv.git
synced 2024-11-27 20:50:25 +08:00
Merge pull request #19079 from alalek:issue_18713
This commit is contained in:
commit
1bfc75ac23
@ -1453,6 +1453,7 @@ struct CV_EXPORTS_W_SIMPLE CirclesGridFinderParameters2 : public CirclesGridFind
|
||||
- **CALIB_CB_CLUSTERING** uses a special algorithm for grid detection. It is more robust to
|
||||
perspective distortions but much more sensitive to background clutter.
|
||||
@param blobDetector feature detector that finds blobs like dark circles on light background.
|
||||
If `blobDetector` is NULL then `image` represents Point2f array of candidates.
|
||||
@param parameters struct for finding circles in a grid pattern.
|
||||
|
||||
The function attempts to determine whether the input image contains a grid of circles. If it is, the
|
||||
|
@ -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,
|
||||
OutputArray centers, int flags,
|
||||
const Ptr<FeatureDetector> &blobDetector,
|
||||
@ -2205,15 +2198,22 @@ bool findCirclesGrid2(InputArray _image, Size patternSize,
|
||||
bool isSymmetricGrid = (flags & CALIB_CB_SYMMETRIC_GRID ) ? true : false;
|
||||
CV_Assert(isAsymmetricGrid ^ isSymmetricGrid);
|
||||
|
||||
Mat image = _image.getMat();
|
||||
std::vector<Point2f> centers;
|
||||
|
||||
std::vector<KeyPoint> keypoints;
|
||||
blobDetector->detect(image, keypoints);
|
||||
std::vector<Point2f> points;
|
||||
for (size_t i = 0; i < keypoints.size(); i++)
|
||||
if (blobDetector)
|
||||
{
|
||||
points.push_back (keypoints[i].pt);
|
||||
std::vector<KeyPoint> keypoints;
|
||||
blobDetector->detect(_image, keypoints);
|
||||
for (size_t i = 0; i < keypoints.size(); i++)
|
||||
{
|
||||
points.push_back(keypoints[i].pt);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
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)
|
||||
@ -2229,64 +2229,59 @@ bool findCirclesGrid2(InputArray _image, Size patternSize,
|
||||
return !centers.empty();
|
||||
}
|
||||
|
||||
bool isValid = false;
|
||||
const int attempts = 2;
|
||||
const size_t minHomographyPoints = 4;
|
||||
Mat H;
|
||||
for (int i = 0; i < attempts; i++)
|
||||
{
|
||||
centers.clear();
|
||||
CirclesGridFinder boxFinder(patternSize, points, parameters);
|
||||
bool isFound = false;
|
||||
#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)
|
||||
centers.clear();
|
||||
CirclesGridFinder boxFinder(patternSize, points, parameters);
|
||||
try
|
||||
{
|
||||
case CirclesGridFinderParameters::SYMMETRIC_GRID:
|
||||
boxFinder.getHoles(centers);
|
||||
break;
|
||||
case CirclesGridFinderParameters::ASYMMETRIC_GRID:
|
||||
boxFinder.getAsymmetricHoles(centers);
|
||||
break;
|
||||
default:
|
||||
CV_Error(Error::StsBadArg, "Unknown pattern type");
|
||||
bool isFound = boxFinder.findHoles();
|
||||
if (isFound)
|
||||
{
|
||||
switch(parameters.gridType)
|
||||
{
|
||||
case CirclesGridFinderParameters::SYMMETRIC_GRID:
|
||||
boxFinder.getHoles(centers);
|
||||
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;
|
||||
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);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
boxFinder.getHoles(centers);
|
||||
if (i != attempts - 1)
|
||||
{
|
||||
if (centers.size() < minHomographyPoints)
|
||||
break;
|
||||
H = CirclesGridFinder::rectifyGrid(boxFinder.getDetectedGridSize(), centers, points, points);
|
||||
}
|
||||
if (!H.empty()) // undone rectification
|
||||
{
|
||||
Mat orgPointsMat;
|
||||
transform(centers, orgPointsMat, H.inv());
|
||||
convertPointsFromHomogeneous(orgPointsMat, centers);
|
||||
}
|
||||
Mat(centers).copyTo(_centers);
|
||||
return false;
|
||||
return isValid;
|
||||
}
|
||||
|
||||
bool findCirclesGrid(InputArray _image, Size patternSize,
|
||||
|
@ -1622,7 +1622,7 @@ size_t CirclesGridFinder::getFirstCorner(std::vector<Point> &largeCornerIndices,
|
||||
int cornerIdx = 0;
|
||||
bool waitOutsider = true;
|
||||
|
||||
for(;;)
|
||||
for (size_t i = 0; i < cornersCount * 2; ++i)
|
||||
{
|
||||
if (waitOutsider)
|
||||
{
|
||||
@ -1632,11 +1632,11 @@ size_t CirclesGridFinder::getFirstCorner(std::vector<Point> &largeCornerIndices,
|
||||
else
|
||||
{
|
||||
if (isInsider[(cornerIdx + 1) % cornersCount])
|
||||
break;
|
||||
return cornerIdx;
|
||||
}
|
||||
|
||||
cornerIdx = (cornerIdx + 1) % cornersCount;
|
||||
}
|
||||
|
||||
return cornerIdx;
|
||||
CV_Error(Error::StsNoConv, "isInsider array has the same values");
|
||||
}
|
||||
|
@ -487,5 +487,59 @@ TEST(Calib3d_CirclesPatternDetectorWithClustering, accuracy)
|
||||
ASSERT_LE(error, precise_success_error_level);
|
||||
}
|
||||
|
||||
TEST(Calib3d_AsymmetricCirclesPatternDetector, regression_18713)
|
||||
{
|
||||
float pts_[][2] = {
|
||||
{ 166.5, 107 }, { 146, 236 }, { 147, 92 }, { 184, 162 }, { 150, 185.5 },
|
||||
{ 215, 105 }, { 270.5, 186 }, { 159, 142 }, { 6, 205.5 }, { 32, 148.5 },
|
||||
{ 126, 163.5 }, { 181, 208.5 }, { 240.5, 62 }, { 84.5, 76.5 }, { 190, 120.5 },
|
||||
{ 10, 189 }, { 266, 104 }, { 307.5, 207.5 }, { 97, 184 }, { 116.5, 210 },
|
||||
{ 114, 139 }, { 84.5, 233 }, { 269.5, 139 }, { 136, 126.5 }, { 120, 107.5 },
|
||||
{ 129.5, 65.5 }, { 212.5, 140.5 }, { 204.5, 60.5 }, { 207.5, 241 }, { 61.5, 94.5 },
|
||||
{ 186.5, 61.5 }, { 220, 63 }, { 239, 120.5 }, { 212, 186 }, { 284, 87.5 },
|
||||
{ 62, 114.5 }, { 283, 61.5 }, { 238.5, 88.5 }, { 243, 159 }, { 245, 208 },
|
||||
{ 298.5, 158.5 }, { 57, 129 }, { 156.5, 63.5 }, { 192, 90.5 }, { 281, 235.5 },
|
||||
{ 172, 62.5 }, { 291.5, 119.5 }, { 90, 127 }, { 68.5, 166.5 }, { 108.5, 83.5 },
|
||||
{ 22, 176 }
|
||||
};
|
||||
Mat candidates(51, 1, CV_32FC2, (void*)pts_);
|
||||
Size patternSize(4, 9);
|
||||
|
||||
std::vector< Point2f > result;
|
||||
bool res = false;
|
||||
|
||||
// issue reports about hangs
|
||||
EXPECT_NO_THROW(res = findCirclesGrid(candidates, patternSize, result, CALIB_CB_ASYMMETRIC_GRID, Ptr<FeatureDetector>()/*blobDetector=NULL*/));
|
||||
EXPECT_FALSE(res);
|
||||
|
||||
if (cvtest::debugLevel > 0)
|
||||
{
|
||||
std::cout << Mat(candidates) << std::endl;
|
||||
std::cout << Mat(result) << std::endl;
|
||||
Mat img(Size(400, 300), CV_8UC3, Scalar::all(0));
|
||||
|
||||
std::vector< Point2f > centers;
|
||||
candidates.copyTo(centers);
|
||||
|
||||
for (size_t i = 0; i < centers.size(); i++)
|
||||
{
|
||||
const Point2f& pt = centers[i];
|
||||
//printf("{ %g, %g }, \n", pt.x, pt.y);
|
||||
circle(img, pt, 5, Scalar(0, 255, 0));
|
||||
}
|
||||
for (size_t i = 0; i < result.size(); i++)
|
||||
{
|
||||
const Point2f& pt = result[i];
|
||||
circle(img, pt, 10, Scalar(0, 0, 255));
|
||||
}
|
||||
imwrite("test_18713.png", img);
|
||||
if (cvtest::debugLevel >= 10)
|
||||
{
|
||||
imshow("result", img);
|
||||
waitKey();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}} // namespace
|
||||
/* End of file. */
|
||||
|
Loading…
Reference in New Issue
Block a user