Why does cv2.findCircleGrid not accept calibration patterns that are ambiguous at 180 degrees?

I’m trying to use an asymmetric circle grid of dimensions 7 rows and 11 columns to calibrate a camera. However for this dimension or any ambiguous configuration it seems that cv2.findCirclesGrid returns ret=False. Is this how it’s intended to work since for monocular camera the ambiguity shouldn’t matter. The call to cv2.findCirclesGrid:
ret, corners = cv2.findCirclesGrid(enhancedImage, (7, 11), blobDetector=myblobDetector, flags = (cv2.CALIB_CB_ASYMMETRIC_GRID + cv2.CALIB_CB_CLUSTERING ) )

Hi @TdiRex

As you know, symmetric patterns look the same when you turn them 180º. So an algorithm can come up with two solutions, and that’s why you don’t use symmetric patterns when calibrating stereo cameras.

Thus, when you use symmetric pattern on a monocular camera, findCirclesGrid uses a different algorithm, an specialized one that knows there can be two solutions, and knows which one to choose.

And that’s pretty much all of this.

1 Like

Hi, thank you for the answer, but how would it know to use the monocular algorithm? Do i have to specify additional flags? Because for the configuration i listed in my question findCirclesGrid always returns ret=False, and doesn’t find the circles grid. However it does work for other non-symmetric configurations, and the blobDetector always finds all the circles. So how would I specify for it to use the monocular version, or do I have to change the source code? Again thank you for the information.

you tell it, by giving CALIB_CB_ASYMMETRIC_GRID.

your grid isn’t that, it’s symmetric. that is the issue.

the “different algorithms” are one and the same algorithm, but with different expectations of what it’ll see. the difference is not monocular/binocular. it’s merely the arrangement of points.

it doesn’t magically know which solution to choose in the ambiguous case.

in the ambiguous case (only symmetric grids), it’ll use some ordering based which blob occurs first in the picture (topmost/leftmost), so it’s going to be stable… within some angle. run it interactively, rotate your board around, watch how it gets labeled. then you stay away from those angles where the labeling flips… stay away from those angles in both camera views. then you’re good.

please post complete but minimal code to reproduce the issue (you never showed how you initialized myblobDetector). I’ll assume you intend to use the picture you already posted.

your problem is that you ask to find an asymmetric grid but you give a symmetric one.

I see, i assumed the symmetric grid option referred to a pattern like this :

Thank you.

However now when i do specify the symmetric option like so:
ret, corners = cv2.findCirclesGrid(im_with_keypoints_gray, (7, 11), blobDetector=myblobDetector, flags = cv2.CALIB_CB_SYMMETRIC_GRID)
I get an error:
Message=OpenCV(4.5.1) C:\Users\appveyor\AppData\Local\Temp\1\pip-req-build-oduouqig\opencv\modules\core\src\matmul.dispatch.cpp:439: error: (-215:Assertion failed) scn == m.cols || scn + 1 == m.cols in function ‘cv::transform’, line 125, in
ret, corners = cv2.findCirclesGrid(im_with_keypoints_gray, (7, 11), blobDetector=myblobDetector, flags = (cv2.CALIB_CB_SYMMETRIC_GRID) )

The blob detector is initialized like this:

blobParams = cv2.SimpleBlobDetector_Params()

blobParams.minThreshold = 8
blobParams.maxThreshold = 255

blobParams.filterByArea = True
blobParams.minArea = 10
blobParams.maxArea = 10000

blobParams.filterByCircularity = True
blobParams.minCircularity = 0.1

blobParams.filterByConvexity = True
blobParams.minConvexity = 0.87

blobParams.filterByInertia = True
blobParams.minInertiaRatio = 0.01

myblobDetector = cv2.SimpleBlobDetector_create(blobParams)

you are right, that square grid is the symmetric variant. your initial pattern can’t be handled.

the asymmetric variant, where circles are arranged in “diamond” shape, i.e. a square grid at 45 degree angles, has “6 corners” if you take the convex hull, so the first and last rows are different, not equal. a “diamond” grid with 4 or 8 corners (first and last row equal) appears unanticipated by OpenCV’s code.

the grid you posted last isn’t an 11x7 grid though. that ought to be a 12x8 grid. I am not surprised that detection fails.

Well the grid i posted is just an example, i’m not trying to do detection on that. So I guess the first pattern i posted can’t be handled with openCV at this point?