findCirclesGrid fails even though blob_detector is working

Hi there,

Been working on some pose estimation for a probe of mine. Built this nice 3D holder and made a marker. Previously I had a marker that was like 85% detected all the time and worked well. But the circles were quite small so I upped the circle size and decreased the pattern size.

Now I have run into some problems, as the title suggests my detector works just fine (in the example I have used the default params but have also played around with area and color etc.).

Any suggestions? I’ve read some posts that suggest the minDensity is the problem.

I’ve also heard that some pattern shapes are just not that great with findCirclesgrid, I generated the pattern using opencv/doc/pattern_tools/gen_pattern.py at cbf71c380f5e593263ab9bdc9119fb8d81c30de1 · opencv/opencv · GitHub

To reproduce:

import yaml
import cv2
import numpy as np

# load params
with open("stereo_params.yaml", 'r') as f:
    cam_params = yaml.safe_load(f)
cam_matrix = np.array(cam_params["intrinsicMatrix1"], dtype=float)
dist_coeff = np.array(cam_params["distortionCoefficients1"], dtype=float)
print(f"Cam: {cam_matrix}")
print(f"Dist: {dist_coeff}")

# pattern params
square_size = 1.2
units = "mm"
rows = 5
cols = 3

# opencv
image = cv2.imread("1724938837392487927.png")
image = cv2.undistort(image, cam_matrix, dist_coeff)
gray_img = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

# show gray
cv2.imwrite("gray.png", gray_img)

# detector
params = cv2.SimpleBlobDetector_Params()
detector = cv2.SimpleBlobDetector_create(params)
keypoints = detector.detect(gray_img)
img_with_keypoints = cv2.drawKeypoints(
    image, keypoints, np.zeros((1, 1)),
    (0, 0, 255), cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)
cv2.imwrite("detector.png", img_with_keypoints)

# find circles
ret, pts2d = cv2.findCirclesGrid(
        gray_img, (rows, cols), None,
        blobDetector=detector,
        flags=(cv2.CALIB_CB_ASYMMETRIC_GRID + cv2.CALIB_CB_CLUSTERING))
print(ret, pts2d)

# find circles
ret, pts2d = cv2.findCirclesGrid(
        gray_img, (cols, rows), None,
        blobDetector=detector,
        flags=(cv2.CALIB_CB_ASYMMETRIC_GRID + cv2.CALIB_CB_CLUSTERING))
print(ret, pts2d)

Output:

Cam: [[3.64475028e+03 0.00000000e+00 4.92827864e+02]
 [0.00000000e+00 7.27007227e+03 5.37142715e+02]
 [0.00000000e+00 0.00000000e+00 1.00000000e+00]]
Dist: [ -0.73274696 -27.03501149   0.           0.           0.        ]
False None
False None

Note if I turn the clustering flag off, I detect three points:

Cam: [[3.64475028e+03 0.00000000e+00 4.92827864e+02]
 [0.00000000e+00 7.27007227e+03 5.37142715e+02]
 [0.00000000e+00 0.00000000e+00 1.00000000e+00]]
Dist: [ -0.73274696 -27.03501149   0.           0.           0.        ]
False [[[451.56924 542.8147 ]]

 [[479.2859  544.4424 ]]

 [[506.4867  546.06793]]]
False [[[451.56924 542.8147 ]]

 [[479.2859  544.4424 ]]

 [[506.4867  546.06793]]]



My best guess is 5 cols, 3 rows asymmetric isn’t enough, my previous was 6, 5 and seemed to work well.

Perhaps from the docs (OpenCV: Camera Calibration and 3D Reconstruction), having 1 point on a row just isn’t enough?

Pattern shape argument:

patternSize|number of circles per row and column ( patternSize = Size(points_per_row, points_per_colum)

picture looks squashed. why is that?

Picture is taken from the left half of a stereo microscope, could be why you think it looks squashed.

Normally we output the frames from the microscope in a “side by side” format. So half the res in width.

that’s a cute board !
but imo, it needs more white space (‘quiet zone’) at top & bottom

Gotcha! Definitely feel the marker needs a re-do.

What is weird (and hopefully you can explain), is that this board does remarkably better:

Any reason why this might be the case?