I have some approximate circles in an approximate grid shape, but there is distortion.
How can I get the centers in the order of left to right, top to bottom?
I tried findCirclesGrid, but I don't think it works with distortion.
I don't think blob detection has an order.
findCirclesGrid()
is intended for camera calibration. Such patterns are expected to have distortion, just like yours. It's definitely supposed to work on your data.
It just needs a little help. It uses a BlobDetector
internally, which is initialized with some defaults that work well for the usual circles grids that show well-defined circles.
For your picture, you need a BlobDetector
with custom parameters. To find all those lumpy blobs, you need to disable all the filtering it usually does.
params = cv.SimpleBlobDetector_Params()
params.filterByArea = False
params.filterByCircularity = False
params.filterByColor = False
params.filterByConvexity = False
params.filterByInertia = False
blobdet = cv.SimpleBlobDetector_create(params)
Result of keypoints = blobdet.detect(im)
and cv.drawKeypoints()
:
You also need to be careful with the flags to findCirclesGrid()
. CALIB_CB_CLUSTERING
failed in that it misassigned points to grid positions.
(rv, gridpts) = cv.findCirclesGrid(
im, (10, 7),
flags=cv.CALIB_CB_SYMMETRIC_GRID,
blobDetector=blobdet)
And that'll give you gridpts
having shape (70, 1, 2)
.
Some visualization:
im_with_grid = cv.cvtColor(cv.pyrUp(im >> 1), cv.COLOR_GRAY2BGR)
for k in range(1, len(gridpts)):
[p1] = gridpts[k-1]
[p2] = gridpts[k]
cv.line(im_with_grid, (p1 * 2.0).astype(int), (p2 * 2.0).astype(int), (0, 0, 255), 2)
for i,[pt] in enumerate(gridpts):
cv.circle(im_with_grid, (pt * 2.0).astype(int), 5, (0, 255, 0), -1)
cv.putText(
im_with_grid, f"{i}", (pt * 2.0).astype(int),
cv.FONT_HERSHEY_SIMPLEX, 0.7, (255, 255, 255), 2, cv.LINE_AA )
Or if you specify the grid size as (7, 10)
, it'll be flipped along its diagonal and look like this:
findCirclesGrid
will fail if the grid has any defects, i.e. missing points. It can't go around those defects. You need a perfect detection of all grid points.